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
17package com.android.dreams.dozetest;
18
19import android.app.AlarmManager;
20import android.app.PendingIntent;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.os.Handler;
26import android.os.PowerManager;
27import android.service.dreams.DreamService;
28import android.text.format.DateFormat;
29import android.util.Log;
30import android.view.Display;
31import android.widget.TextView;
32
33import 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 */
41public 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
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
92    public void onDestroy() {
93        super.onDestroy();
94
95        unregisterReceiver(mAlarmReceiver);
96        mAlarmIntent.cancel();
97    }
98
99    @Override
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
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
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
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
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