1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.cts.verifier.os;
17 
18 import android.app.Activity;
19 import android.app.AlarmManager;
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.util.Log;
25 import android.view.WindowManager;
26 
27 import java.lang.reflect.Field;
28 
29 /**
30  * Activity resets the screen timeout to its original timeout. Used devices without Device Admin.
31  */
32 public class TimeoutResetActivity extends Activity {
33     public static final String EXTRA_OLD_TIMEOUT = "com.android.cts.verifier.extra.OLD_TIMEOUT";
34     /** Set the timeout to the default to reset the activity to if not specified. */
35     public static final long FALLBACK_TIMEOUT = -1L;
36     /**
37      * Empirically determined buffer time in milliseconds between setting short timeout time and
38      * resetting the timeout.
39      */
40     public static final long RESET_BUFFER_TIME = 2000L;
41     /** Short timeout to trigger screen off. */
42     public static final long SCREEN_OFF_TIMEOUT = 0L;
43     public static final String TAG = TimeoutResetActivity.class.getSimpleName();
44 
getUserActivityTimeout(WindowManager.LayoutParams params)45     private static long getUserActivityTimeout(WindowManager.LayoutParams params) {
46         try {
47             return getUserActivityTimeoutField(params).getLong(params);
48         } catch (Exception e) {
49             Log.e(TAG, "error loading the userActivityTimeout field", e);
50             return -1;
51         }
52     }
53 
getUserActivityTimeoutField(WindowManager.LayoutParams params)54     private static Field getUserActivityTimeoutField(WindowManager.LayoutParams params)
55             throws NoSuchFieldException {
56         return params.getClass().getField("userActivityTimeout");
57     }
58 
setUserActivityTimeout(WindowManager.LayoutParams params, long timeout)59     private static void setUserActivityTimeout(WindowManager.LayoutParams params, long timeout) {
60         try {
61             getUserActivityTimeoutField(params).setLong(params, timeout);
62             Log.d(TAG, "UserActivityTimeout set to " + timeout);
63         } catch (Exception e) {
64             Log.e(TAG, "error setting the userActivityTimeout field", e);
65             throw new RuntimeException(e);
66         }
67     }
68 
turnOffScreen(final Activity activity)69     public static void turnOffScreen(final Activity activity) {
70         activity.runOnUiThread(new Runnable() {
71             @Override
72             public void run() {
73                 WindowManager.LayoutParams params = activity.getWindow().getAttributes();
74 
75                 // to restore timeout after shutoff
76                 final long oldTimeout = getUserActivityTimeout(params);
77 
78                 final long timeout = SCREEN_OFF_TIMEOUT;
79                 setUserActivityTimeout(params, timeout);
80 
81                 // upon setting this, timeout will be reduced
82                 activity.getWindow().setAttributes(params);
83 
84                 ((AlarmManager) activity.getSystemService(ALARM_SERVICE)).setExact(
85                         AlarmManager.RTC,
86                         System.currentTimeMillis() + RESET_BUFFER_TIME,
87                         PendingIntent.getActivity(
88                                 activity.getApplicationContext(),
89                                 0,
90                                 new Intent(activity, TimeoutResetActivity.class)
91                                         .putExtra(EXTRA_OLD_TIMEOUT, oldTimeout),
92                                 0));
93             }
94         });
95     }
96 
97     @Override
onCreate(Bundle savedInstanceState)98     protected void onCreate(Bundle savedInstanceState) {
99         super.onCreate(savedInstanceState);
100 
101         long timeout = getIntent().getLongExtra(EXTRA_OLD_TIMEOUT, FALLBACK_TIMEOUT);
102         if (timeout < 1000) { // in case the old timeout was super low by accident
103             timeout = FALLBACK_TIMEOUT;
104         }
105 
106         WindowManager.LayoutParams params = getWindow().getAttributes();
107         setUserActivityTimeout(params, timeout);
108         getWindow().setAttributes(params);
109 
110         finish();
111     }
112 }
113