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 
17 package com.android.dreams.dozetest;
18 
19 import android.app.AlarmManager;
20 import android.app.PendingIntent;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.Handler;
26 import android.os.PowerManager;
27 import android.service.dreams.DreamService;
28 import android.text.format.DateFormat;
29 import android.util.Log;
30 import android.view.Display;
31 import android.widget.TextView;
32 
33 import java.util.Date;
34 
35 /**
36  * Simple test for doze mode.
37  * <p>
38  * adb shell setprop debug.doze.component com.android.dreams.dozetest/.DozeTestDream
39  * </p>
40  */
41 public class DozeTestDream extends DreamService {
42     private static final String TAG = DozeTestDream.class.getSimpleName();
43     private static final boolean DEBUG = false;
44 
45     // Amount of time to allow to update the time shown on the screen before releasing
46     // the wakelock.  This timeout is design to compensate for the fact that we don't
47     // currently have a way to know when time display contents have actually been
48     // refreshed once the dream has finished rendering a new frame.
49     private static final int UPDATE_TIME_TIMEOUT = 100;
50 
51     // Not all hardware supports dozing.  We should use Display.STATE_DOZE but
52     // for testing purposes it is convenient to use Display.STATE_ON so the
53     // test still works on hardware that does not support dozing.
54     private static final int DISPLAY_STATE_WHEN_DOZING = Display.STATE_ON;
55 
56     private PowerManager mPowerManager;
57     private PowerManager.WakeLock mWakeLock;
58     private AlarmManager mAlarmManager;
59     private PendingIntent mAlarmIntent;
60     private Handler mHandler = new Handler();
61 
62     private TextView mAlarmClock;
63 
64     private final Date mTime = new Date();
65     private java.text.DateFormat mTimeFormat;
66 
67     private boolean mDreaming;
68 
69     private long mLastTime = Long.MIN_VALUE;
70 
71     @Override
onCreate()72     public void onCreate() {
73         super.onCreate();
74 
75         mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
76         mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
77 
78         mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
79 
80         Intent intent = new Intent("com.android.dreams.dozetest.ACTION_ALARM");
81         intent.setPackage(getPackageName());
82         IntentFilter filter = new IntentFilter();
83         filter.addAction(intent.getAction());
84         registerReceiver(mAlarmReceiver, filter);
85         mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
86                 PendingIntent.FLAG_CANCEL_CURRENT);
87 
88         setDozeScreenState(DISPLAY_STATE_WHEN_DOZING);
89     }
90 
91     @Override
onDestroy()92     public void onDestroy() {
93         super.onDestroy();
94 
95         unregisterReceiver(mAlarmReceiver);
96         mAlarmIntent.cancel();
97     }
98 
99     @Override
onAttachedToWindow()100     public void onAttachedToWindow() {
101         super.onAttachedToWindow();
102         setInteractive(false);
103         setLowProfile(true);
104         setFullscreen(true);
105         setContentView(R.layout.dream);
106         setScreenBright(false);
107 
108         mAlarmClock = (TextView)findViewById(R.id.alarm_clock);
109 
110         mTimeFormat = DateFormat.getTimeFormat(this);
111     }
112 
113     @Override
onDreamingStarted()114     public void onDreamingStarted() {
115         super.onDreamingStarted();
116 
117         mDreaming = true;
118 
119         Log.d(TAG, "Dream started: canDoze=" + canDoze());
120 
121         performTimeUpdate();
122 
123         startDozing();
124     }
125 
126     @Override
onDreamingStopped()127     public void onDreamingStopped() {
128         super.onDreamingStopped();
129 
130         mDreaming = false;
131 
132         Log.d(TAG, "Dream ended: isDozing=" + isDozing());
133 
134         stopDozing();
135         cancelTimeUpdate();
136     }
137 
performTimeUpdate()138     private void performTimeUpdate() {
139         if (mDreaming) {
140             long now = System.currentTimeMillis();
141             now -= now % 60000; // back up to last minute boundary
142             if (mLastTime == now) {
143                 return;
144             }
145 
146             mLastTime = now;
147             mTime.setTime(now);
148             mAlarmClock.setText(mTimeFormat.format(mTime));
149 
150             mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, now + 60000, mAlarmIntent);
151 
152             mWakeLock.acquire(UPDATE_TIME_TIMEOUT + 5000 /*for testing brightness*/);
153 
154             // flash the screen a bit to test these functions
155             setDozeScreenState(DISPLAY_STATE_WHEN_DOZING);
156             setDozeScreenBrightness(200);
157             mHandler.postDelayed(new Runnable() {
158                 @Override
159                 public void run() {
160                     setDozeScreenBrightness(50);
161                 }
162             }, 2000);
163             mHandler.postDelayed(new Runnable() {
164                 @Override
165                 public void run() {
166                     setDozeScreenState(Display.STATE_OFF);
167                 }
168             }, 5000);
169         }
170     }
171 
cancelTimeUpdate()172     private void cancelTimeUpdate() {
173         mAlarmManager.cancel(mAlarmIntent);
174     }
175 
176     private final BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() {
177         @Override
178         public void onReceive(Context context, Intent intent) {
179             performTimeUpdate();
180         }
181     };
182 }
183