blob: 7af0b05f9cc5cbffd6689be676bb1f8471414e1a [file] [log] [blame]
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001/**
2 * Copyright (C) 2012 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 */
16package android.service.dreams;
17
Tor Norbye7b9c9122013-05-30 16:48:33 -070018import android.annotation.IdRes;
19import android.annotation.LayoutRes;
Scott Kennedyc0519552015-02-11 15:33:10 -080020import android.annotation.Nullable;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070021import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
Jeff Brown26875502014-01-30 21:47:47 -080023import android.app.AlarmManager;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070024import android.app.Service;
25import android.content.Intent;
Dianne Hackborn4c1e3182012-10-05 18:37:54 -070026import android.graphics.PixelFormat;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070027import android.graphics.drawable.ColorDrawable;
28import android.os.Handler;
29import android.os.IBinder;
Jeff Brown970d4132014-07-19 11:33:47 -070030import android.os.PowerManager;
31import android.os.RemoteException;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070032import android.os.ServiceManager;
Clara Bayarri75e09792015-07-29 16:20:40 +010033import android.util.MathUtils;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070034import android.util.Slog;
35import android.view.ActionMode;
Jeff Brown970d4132014-07-19 11:33:47 -070036import android.view.Display;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070037import android.view.KeyEvent;
Clara Bayarri75e09792015-07-29 16:20:40 +010038import android.view.KeyboardShortcutGroup;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070039import android.view.Menu;
40import android.view.MenuItem;
41import android.view.MotionEvent;
Tim Kilbourn6a975b32015-04-09 17:14:34 -070042import android.view.SearchEvent;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070043import android.view.View;
44import android.view.ViewGroup;
45import android.view.Window;
46import android.view.WindowManager;
47import android.view.WindowManager.LayoutParams;
Clara Bayarri75e09792015-07-29 16:20:40 +010048import android.view.WindowManagerGlobal;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070049import android.view.accessibility.AccessibilityEvent;
50
Clara Bayarri75e09792015-07-29 16:20:40 +010051import com.android.internal.policy.PhoneWindow;
Jeff Brown26875502014-01-30 21:47:47 -080052import com.android.internal.util.DumpUtils;
53import com.android.internal.util.DumpUtils.Dump;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070054
Clara Bayarri75e09792015-07-29 16:20:40 +010055import java.io.FileDescriptor;
56import java.io.PrintWriter;
57import java.util.List;
58
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070059/**
Scott Main6c9a1a12012-11-19 11:58:59 -080060 * Extend this class to implement a custom dream (available to the user as a "Daydream").
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070061 *
62 * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
63 * desk dock. Dreams provide another modality for apps to express themselves, tailored for
64 * an exhibition/lean-back experience.</p>
65 *
Scott Main6c9a1a12012-11-19 11:58:59 -080066 * <p>The {@code DreamService} lifecycle is as follows:</p>
Scott Main6237ac12012-10-08 22:30:29 -070067 * <ol>
68 * <li>{@link #onAttachedToWindow}
69 * <p>Use this for initial setup, such as calling {@link #setContentView setContentView()}.</li>
70 * <li>{@link #onDreamingStarted}
71 * <p>Your dream has started, so you should begin animations or other behaviors here.</li>
72 * <li>{@link #onDreamingStopped}
73 * <p>Use this to stop the things you started in {@link #onDreamingStarted}.</li>
74 * <li>{@link #onDetachedFromWindow}
Scott Main6c9a1a12012-11-19 11:58:59 -080075 * <p>Use this to dismantle resources (for example, detach from handlers
76 * and listeners).</li>
Scott Main6237ac12012-10-08 22:30:29 -070077 * </ol>
Daniel Sandler2d784902012-10-03 23:04:50 -040078 *
79 * <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but
80 * initialization and teardown should be done by overriding the hooks above.</p>
81 *
Scott Main6c9a1a12012-11-19 11:58:59 -080082 * <p>To be available to the system, your {@code DreamService} should be declared in the
83 * manifest as follows:</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070084 * <pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -040085 * &lt;service
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070086 * android:name=".MyDream"
87 * android:exported="true"
88 * android:icon="@drawable/my_icon"
89 * android:label="@string/my_dream_label" >
90 *
John Spurlock3a4d41a2012-10-01 09:30:49 -040091 * &lt;intent-filter>
92 * &lt;action android:name="android.service.dreams.DreamService" />
93 * &lt;category android:name="android.intent.category.DEFAULT" />
94 * &lt;/intent-filter>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070095 *
John Spurlock3a4d41a2012-10-01 09:30:49 -040096 * &lt;!-- Point to additional information for this dream (optional) -->
97 * &lt;meta-data
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070098 * android:name="android.service.dream"
99 * android:resource="@xml/my_dream" />
John Spurlock3a4d41a2012-10-01 09:30:49 -0400100 * &lt;/service>
101 * </pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -0400102 *
Neil Fuller71fbb812015-11-30 09:51:33 +0000103 * <p>If specified with the {@code <meta-data>} element,
Scott Main6237ac12012-10-08 22:30:29 -0700104 * additional information for the dream is defined using the
105 * {@link android.R.styleable#Dream &lt;dream&gt;} element in a separate XML file.
106 * Currently, the only addtional
107 * information you can provide is for a settings activity that allows the user to configure
108 * the dream behavior. For example:</p>
109 * <p class="code-caption">res/xml/my_dream.xml</p>
110 * <pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -0400111 * &lt;dream xmlns:android="http://schemas.android.com/apk/res/android"
112 * android:settingsActivity="com.example.app/.MyDreamSettingsActivity" />
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700113 * </pre>
Scott Main6237ac12012-10-08 22:30:29 -0700114 * <p>This makes a Settings button available alongside your dream's listing in the
115 * system settings, which when pressed opens the specified activity.</p>
116 *
117 *
118 * <p>To specify your dream layout, call {@link #setContentView}, typically during the
119 * {@link #onAttachedToWindow} callback. For example:</p>
120 * <pre>
121 * public class MyDream extends DreamService {
122 *
123 * &#64;Override
124 * public void onAttachedToWindow() {
125 * super.onAttachedToWindow();
126 *
127 * // Exit dream upon user touch
128 * setInteractive(false);
129 * // Hide system UI
130 * setFullscreen(true);
131 * // Set the dream layout
132 * setContentView(R.layout.dream);
133 * }
134 * }
135 * </pre>
John Spurlockeb8d1be2014-06-25 17:46:15 -0400136 *
137 * <p>When targeting api level 21 and above, you must declare the service in your manifest file
138 * with the {@link android.Manifest.permission#BIND_DREAM_SERVICE} permission. For example:</p>
139 * <pre>
140 * &lt;service
141 * android:name=".MyDream"
142 * android:exported="true"
143 * android:icon="@drawable/my_icon"
144 * android:label="@string/my_dream_label"
Jeff Brown970d4132014-07-19 11:33:47 -0700145 * android:permission="android.permission.BIND_DREAM_SERVICE">
146 * &lt;intent-filter>
147 * &lt;action android:name=”android.service.dreams.DreamService” />
148 * &lt;category android:name=”android.intent.category.DEFAULT” />
149 * &lt;/intent-filter>
John Spurlockeb8d1be2014-06-25 17:46:15 -0400150 * &lt;/service>
151 * </pre>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700152 */
153public class DreamService extends Service implements Window.Callback {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700154 private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
155
156 /**
157 * The name of the dream manager service.
158 * @hide
159 */
160 public static final String DREAM_SERVICE = "dreams";
161
162 /**
163 * The {@link Intent} that must be declared as handled by the service.
164 */
165 @SdkConstant(SdkConstantType.SERVICE_ACTION)
166 public static final String SERVICE_INTERFACE =
167 "android.service.dreams.DreamService";
168
169 /**
170 * Name under which a Dream publishes information about itself.
171 * This meta-data must reference an XML resource containing
172 * a <code>&lt;{@link android.R.styleable#Dream dream}&gt;</code>
173 * tag.
174 */
175 public static final String DREAM_META_DATA = "android.service.dream";
176
Jeff Brown26875502014-01-30 21:47:47 -0800177 private final IDreamManager mSandman;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700178 private final Handler mHandler = new Handler();
179 private IBinder mWindowToken;
180 private Window mWindow;
Jeff Brown344812d2014-04-02 20:00:36 -0700181 private boolean mInteractive;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700182 private boolean mLowProfile = true;
Jeff Brown344812d2014-04-02 20:00:36 -0700183 private boolean mFullscreen;
Chris Wrena934fd12012-10-08 18:19:16 -0400184 private boolean mScreenBright = true;
Jeff Brown344812d2014-04-02 20:00:36 -0700185 private boolean mStarted;
Jeff Brownf6d46682014-07-17 22:44:20 -0700186 private boolean mWaking;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700187 private boolean mFinished;
Jeff Brown26875502014-01-30 21:47:47 -0800188 private boolean mCanDoze;
189 private boolean mDozing;
John Spurlockbf370992014-06-17 13:58:31 -0400190 private boolean mWindowless;
Jeff Brown970d4132014-07-19 11:33:47 -0700191 private int mDozeScreenState = Display.STATE_UNKNOWN;
192 private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700193
Daniel Sandler2d784902012-10-03 23:04:50 -0400194 private boolean mDebug = false;
195
Jeff Brown26875502014-01-30 21:47:47 -0800196 public DreamService() {
197 mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
198 }
199
Daniel Sandler2d784902012-10-03 23:04:50 -0400200 /**
201 * @hide
202 */
203 public void setDebug(boolean dbg) {
204 mDebug = dbg;
205 }
206
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700207 // begin Window.Callback methods
208 /** {@inheritDoc} */
209 @Override
210 public boolean dispatchKeyEvent(KeyEvent event) {
211 // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
212 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700213 if (mDebug) Slog.v(TAG, "Waking up on keyEvent");
214 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700215 return true;
216 } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700217 if (mDebug) Slog.v(TAG, "Waking up on back key");
218 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700219 return true;
220 }
221 return mWindow.superDispatchKeyEvent(event);
222 }
223
224 /** {@inheritDoc} */
225 @Override
226 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400227 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700228 if (mDebug) Slog.v(TAG, "Waking up on keyShortcutEvent");
229 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700230 return true;
231 }
232 return mWindow.superDispatchKeyShortcutEvent(event);
233 }
234
235 /** {@inheritDoc} */
236 @Override
237 public boolean dispatchTouchEvent(MotionEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400238 // TODO: create more flexible version of mInteractive that allows clicks
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700239 // but finish()es on any other kind of activity
Daniel Sandler2d784902012-10-03 23:04:50 -0400240 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700241 if (mDebug) Slog.v(TAG, "Waking up on touchEvent");
242 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700243 return true;
244 }
245 return mWindow.superDispatchTouchEvent(event);
246 }
247
248 /** {@inheritDoc} */
249 @Override
250 public boolean dispatchTrackballEvent(MotionEvent event) {
251 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700252 if (mDebug) Slog.v(TAG, "Waking up on trackballEvent");
253 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700254 return true;
255 }
256 return mWindow.superDispatchTrackballEvent(event);
257 }
258
259 /** {@inheritDoc} */
260 @Override
261 public boolean dispatchGenericMotionEvent(MotionEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400262 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700263 if (mDebug) Slog.v(TAG, "Waking up on genericMotionEvent");
264 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700265 return true;
266 }
267 return mWindow.superDispatchGenericMotionEvent(event);
268 }
269
270 /** {@inheritDoc} */
271 @Override
272 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
273 return false;
274 }
275
276 /** {@inheritDoc} */
277 @Override
278 public View onCreatePanelView(int featureId) {
279 return null;
280 }
281
282 /** {@inheritDoc} */
283 @Override
284 public boolean onCreatePanelMenu(int featureId, Menu menu) {
285 return false;
286 }
287
288 /** {@inheritDoc} */
289 @Override
290 public boolean onPreparePanel(int featureId, View view, Menu menu) {
291 return false;
292 }
293
294 /** {@inheritDoc} */
295 @Override
296 public boolean onMenuOpened(int featureId, Menu menu) {
297 return false;
298 }
299
300 /** {@inheritDoc} */
301 @Override
302 public boolean onMenuItemSelected(int featureId, MenuItem item) {
303 return false;
304 }
305
306 /** {@inheritDoc} */
307 @Override
308 public void onWindowAttributesChanged(LayoutParams attrs) {
309 }
310
311 /** {@inheritDoc} */
312 @Override
313 public void onContentChanged() {
314 }
315
316 /** {@inheritDoc} */
317 @Override
318 public void onWindowFocusChanged(boolean hasFocus) {
319 }
320
321 /** {@inheritDoc} */
322 @Override
323 public void onAttachedToWindow() {
324 }
325
326 /** {@inheritDoc} */
327 @Override
328 public void onDetachedFromWindow() {
329 }
330
331 /** {@inheritDoc} */
332 @Override
333 public void onPanelClosed(int featureId, Menu menu) {
334 }
335
336 /** {@inheritDoc} */
337 @Override
Tim Kilbourn6a975b32015-04-09 17:14:34 -0700338 public boolean onSearchRequested(SearchEvent event) {
339 return onSearchRequested();
340 }
341
342 /** {@inheritDoc} */
343 @Override
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700344 public boolean onSearchRequested() {
345 return false;
346 }
347
348 /** {@inheritDoc} */
349 @Override
350 public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
351 return null;
352 }
353
354 /** {@inheritDoc} */
355 @Override
Clara Bayarri4423d912015-03-02 19:42:48 +0000356 public ActionMode onWindowStartingActionMode(
357 android.view.ActionMode.Callback callback, int type) {
358 return null;
359 }
360
361 /** {@inheritDoc} */
362 @Override
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700363 public void onActionModeStarted(ActionMode mode) {
364 }
365
366 /** {@inheritDoc} */
367 @Override
368 public void onActionModeFinished(ActionMode mode) {
369 }
370 // end Window.Callback methods
371
372 // begin public api
373 /**
374 * Retrieves the current {@link android.view.WindowManager} for the dream.
375 * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
376 *
377 * @return The current window manager, or null if the dream is not started.
378 */
379 public WindowManager getWindowManager() {
Jeff Brown344812d2014-04-02 20:00:36 -0700380 return mWindow != null ? mWindow.getWindowManager() : null;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700381 }
382
383 /**
384 * Retrieves the current {@link android.view.Window} for the dream.
385 * Behaves similarly to {@link android.app.Activity#getWindow()}.
386 *
387 * @return The current window, or null if the dream is not started.
388 */
389 public Window getWindow() {
390 return mWindow;
391 }
392
393 /**
394 * Inflates a layout resource and set it to be the content view for this Dream.
395 * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
396 *
397 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
398 *
399 * @param layoutResID Resource ID to be inflated.
Daniel Sandler2d784902012-10-03 23:04:50 -0400400 *
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700401 * @see #setContentView(android.view.View)
402 * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
403 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700404 public void setContentView(@LayoutRes int layoutResID) {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700405 getWindow().setContentView(layoutResID);
406 }
407
408 /**
409 * Sets a view to be the content view for this Dream.
Scott Main6237ac12012-10-08 22:30:29 -0700410 * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)} in an activity,
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700411 * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
412 *
Scott Main6237ac12012-10-08 22:30:29 -0700413 * <p>Note: This requires a window, so you should usually call it during
414 * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
415 * during {@link #onCreate}).</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700416 *
417 * @see #setContentView(int)
418 * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
419 */
420 public void setContentView(View view) {
421 getWindow().setContentView(view);
422 }
423
424 /**
425 * Sets a view to be the content view for this Dream.
Daniel Sandler2d784902012-10-03 23:04:50 -0400426 * Behaves similarly to
Scott Main6237ac12012-10-08 22:30:29 -0700427 * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
428 * in an activity.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700429 *
Scott Main6237ac12012-10-08 22:30:29 -0700430 * <p>Note: This requires a window, so you should usually call it during
431 * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
432 * during {@link #onCreate}).</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700433 *
434 * @param view The desired content to display.
435 * @param params Layout parameters for the view.
436 *
437 * @see #setContentView(android.view.View)
438 * @see #setContentView(int)
439 */
440 public void setContentView(View view, ViewGroup.LayoutParams params) {
441 getWindow().setContentView(view, params);
442 }
443
444 /**
445 * Adds a view to the Dream's window, leaving other content views in place.
446 *
447 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
448 *
449 * @param view The desired content to display.
450 * @param params Layout parameters for the view.
451 */
452 public void addContentView(View view, ViewGroup.LayoutParams params) {
453 getWindow().addContentView(view, params);
454 }
455
456 /**
457 * Finds a view that was identified by the id attribute from the XML that
458 * was processed in {@link #onCreate}.
459 *
460 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
461 *
462 * @return The view if found or null otherwise.
463 */
Scott Kennedyc0519552015-02-11 15:33:10 -0800464 @Nullable
Tor Norbye7b9c9122013-05-30 16:48:33 -0700465 public View findViewById(@IdRes int id) {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700466 return getWindow().findViewById(id);
467 }
468
469 /**
470 * Marks this dream as interactive to receive input events.
471 *
472 * <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
473 *
474 * <p>Interactive dreams should call {@link #finish()} to dismiss themselves.</p>
475 *
476 * @param interactive True if this dream will handle input events.
477 */
478 public void setInteractive(boolean interactive) {
479 mInteractive = interactive;
480 }
481
482 /**
483 * Returns whether or not this dream is interactive. Defaults to false.
484 *
485 * @see #setInteractive(boolean)
486 */
487 public boolean isInteractive() {
488 return mInteractive;
489 }
490
491 /**
492 * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
493 *
494 * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700495 * @hide There is no reason to have this -- dreams can set this flag
496 * on their own content view, and from there can actually do the
497 * correct interactions with it (seeing when it is cleared etc).
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700498 */
499 public void setLowProfile(boolean lowProfile) {
Jeff Brown26875502014-01-30 21:47:47 -0800500 if (mLowProfile != lowProfile) {
501 mLowProfile = lowProfile;
502 int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
503 applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
504 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700505 }
506
507 /**
508 * Returns whether or not this dream is in low profile mode. Defaults to true.
509 *
510 * @see #setLowProfile(boolean)
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700511 * @hide
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700512 */
513 public boolean isLowProfile() {
514 return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
515 }
516
517 /**
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700518 * Controls {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN}
519 * on the dream's window.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700520 *
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700521 * @param fullscreen If true, the fullscreen flag will be set; else it
522 * will be cleared.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700523 */
524 public void setFullscreen(boolean fullscreen) {
Jeff Brown26875502014-01-30 21:47:47 -0800525 if (mFullscreen != fullscreen) {
526 mFullscreen = fullscreen;
527 int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
528 applyWindowFlags(mFullscreen ? flag : 0, flag);
529 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700530 }
531
532 /**
533 * Returns whether or not this dream is in fullscreen mode. Defaults to false.
534 *
535 * @see #setFullscreen(boolean)
536 */
537 public boolean isFullscreen() {
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700538 return mFullscreen;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700539 }
540
541 /**
542 * Marks this dream as keeping the screen bright while dreaming.
543 *
544 * @param screenBright True to keep the screen bright while dreaming.
545 */
546 public void setScreenBright(boolean screenBright) {
Jeff Brown26875502014-01-30 21:47:47 -0800547 if (mScreenBright != screenBright) {
548 mScreenBright = screenBright;
549 int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
550 applyWindowFlags(mScreenBright ? flag : 0, flag);
551 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700552 }
553
554 /**
Jeff Brown26875502014-01-30 21:47:47 -0800555 * Returns whether or not this dream keeps the screen bright while dreaming.
556 * Defaults to false, allowing the screen to dim if necessary.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700557 *
558 * @see #setScreenBright(boolean)
559 */
560 public boolean isScreenBright() {
561 return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
562 }
563
564 /**
John Spurlockbf370992014-06-17 13:58:31 -0400565 * Marks this dream as windowless. Only available to doze dreams.
566 *
567 * @hide
568 */
569 public void setWindowless(boolean windowless) {
570 mWindowless = windowless;
571 }
572
573 /**
574 * Returns whether or not this dream is windowless. Only available to doze dreams.
575 *
576 * @hide
577 */
578 public boolean isWindowless() {
579 return mWindowless;
580 }
581
582 /**
Jeff Brown26875502014-01-30 21:47:47 -0800583 * Returns true if this dream is allowed to doze.
584 * <p>
585 * The value returned by this method is only meaningful when the dream has started.
586 * </p>
587 *
588 * @return True if this dream can doze.
589 * @see #startDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700590 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800591 */
592 public boolean canDoze() {
593 return mCanDoze;
594 }
595
596 /**
597 * Starts dozing, entering a deep dreamy sleep.
598 * <p>
599 * Dozing enables the system to conserve power while the user is not actively interacting
600 * with the device. While dozing, the display will remain on in a low-power state
601 * and will continue to show its previous contents but the application processor and
602 * other system components will be allowed to suspend when possible.
603 * </p><p>
604 * While the application processor is suspended, the dream may stop executing code
605 * for long periods of time. Prior to being suspended, the dream may schedule periodic
606 * wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}.
607 * The dream may also keep the CPU awake by acquiring a
608 * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary.
609 * Note that since the purpose of doze mode is to conserve power (especially when
610 * running on battery), the dream should not wake the CPU very often or keep it
611 * awake for very long.
612 * </p><p>
613 * It is a good idea to call this method some time after the dream's entry animation
614 * has completed and the dream is ready to doze. It is important to completely
615 * finish all of the work needed before dozing since the application processor may
616 * be suspended at any moment once this method is called unless other wake locks
617 * are being held.
618 * </p><p>
619 * Call {@link #stopDozing} or {@link #finish} to stop dozing.
620 * </p>
621 *
622 * @see #stopDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700623 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800624 */
625 public void startDozing() {
626 if (mCanDoze && !mDozing) {
627 mDozing = true;
Jeff Brown970d4132014-07-19 11:33:47 -0700628 updateDoze();
629 }
630 }
631
632 private void updateDoze() {
633 if (mDozing) {
Jeff Brown26875502014-01-30 21:47:47 -0800634 try {
Jeff Brown970d4132014-07-19 11:33:47 -0700635 mSandman.startDozing(mWindowToken, mDozeScreenState, mDozeScreenBrightness);
Jeff Brown26875502014-01-30 21:47:47 -0800636 } catch (RemoteException ex) {
637 // system server died
638 }
639 }
640 }
641
642 /**
643 * Stops dozing, returns to active dreaming.
644 * <p>
645 * This method reverses the effect of {@link #startDozing}. From this moment onward,
646 * the application processor will be kept awake as long as the dream is running
647 * or until the dream starts dozing again.
648 * </p>
649 *
650 * @see #startDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700651 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800652 */
653 public void stopDozing() {
654 if (mDozing) {
655 mDozing = false;
656 try {
657 mSandman.stopDozing(mWindowToken);
658 } catch (RemoteException ex) {
659 // system server died
660 }
661 }
662 }
663
664 /**
665 * Returns true if the dream will allow the system to enter a low-power state while
666 * it is running without actually turning off the screen. Defaults to false,
667 * keeping the application processor awake while the dream is running.
668 *
669 * @return True if the dream is dozing.
670 *
671 * @see #setDozing(boolean)
Jeff Brown970d4132014-07-19 11:33:47 -0700672 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800673 */
674 public boolean isDozing() {
675 return mDozing;
676 }
677
678 /**
Jeff Brown970d4132014-07-19 11:33:47 -0700679 * Gets the screen state to use while dozing.
680 *
681 * @return The screen state to use while dozing, such as {@link Display#STATE_ON},
682 * {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
683 * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
684 * behavior.
685 *
686 * @see #setDozeScreenState
687 * @hide For use by system UI components only.
688 */
689 public int getDozeScreenState() {
690 return mDozeScreenState;
691 }
692
693 /**
694 * Sets the screen state to use while dozing.
695 * <p>
696 * The value of this property determines the power state of the primary display
697 * once {@link #startDozing} has been called. The default value is
698 * {@link Display#STATE_UNKNOWN} which lets the system decide.
699 * The dream may set a different state before starting to doze and may
700 * perform transitions between states while dozing to conserve power and
701 * achieve various effects.
702 * </p><p>
703 * It is recommended that the state be set to {@link Display#STATE_DOZE_SUSPEND}
704 * once the dream has completely finished drawing and before it releases its wakelock
705 * to allow the display hardware to be fully suspended. While suspended, the
706 * display will preserve its on-screen contents or hand off control to dedicated
707 * doze hardware if the devices supports it. If the doze suspend state is
708 * used, the dream must make sure to set the mode back
709 * to {@link Display#STATE_DOZE} or {@link Display#STATE_ON} before drawing again
710 * since the display updates may be ignored and not seen by the user otherwise.
711 * </p><p>
712 * The set of available display power states and their behavior while dozing is
713 * hardware dependent and may vary across devices. The dream may therefore
714 * need to be modified or configured to correctly support the hardware.
715 * </p>
716 *
717 * @param state The screen state to use while dozing, such as {@link Display#STATE_ON},
718 * {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
719 * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
720 * behavior.
721 *
722 * @hide For use by system UI components only.
723 */
724 public void setDozeScreenState(int state) {
725 if (mDozeScreenState != state) {
726 mDozeScreenState = state;
727 updateDoze();
728 }
729 }
730
731 /**
732 * Gets the screen brightness to use while dozing.
733 *
734 * @return The screen brightness while dozing as a value between
735 * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
736 * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
737 * its default policy based on the screen state.
738 *
739 * @see #setDozeScreenBrightness
740 * @hide For use by system UI components only.
741 */
742 public int getDozeScreenBrightness() {
743 return mDozeScreenBrightness;
744 }
745
746 /**
747 * Sets the screen brightness to use while dozing.
748 * <p>
749 * The value of this property determines the power state of the primary display
750 * once {@link #startDozing} has been called. The default value is
751 * {@link PowerManager#BRIGHTNESS_DEFAULT} which lets the system decide.
752 * The dream may set a different brightness before starting to doze and may adjust
753 * the brightness while dozing to conserve power and achieve various effects.
754 * </p><p>
755 * Note that dream may specify any brightness in the full 0-255 range, including
756 * values that are less than the minimum value for manual screen brightness
757 * adjustments by the user. In particular, the value may be set to 0 which may
758 * turn off the backlight entirely while still leaving the screen on although
759 * this behavior is device dependent and not guaranteed.
760 * </p><p>
761 * The available range of display brightness values and their behavior while dozing is
762 * hardware dependent and may vary across devices. The dream may therefore
763 * need to be modified or configured to correctly support the hardware.
764 * </p>
765 *
766 * @param brightness The screen brightness while dozing as a value between
767 * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
768 * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
769 * its default policy based on the screen state.
770 *
771 * @hide For use by system UI components only.
772 */
773 public void setDozeScreenBrightness(int brightness) {
774 if (brightness != PowerManager.BRIGHTNESS_DEFAULT) {
775 brightness = clampAbsoluteBrightness(brightness);
776 }
777 if (mDozeScreenBrightness != brightness) {
778 mDozeScreenBrightness = brightness;
779 updateDoze();
780 }
781 }
782
783 /**
Daniel Sandler2d784902012-10-03 23:04:50 -0400784 * Called when this Dream is constructed.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700785 */
786 @Override
787 public void onCreate() {
Jeff Brown970d4132014-07-19 11:33:47 -0700788 if (mDebug) Slog.v(TAG, "onCreate()");
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700789 super.onCreate();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700790 }
791
792 /**
Daniel Sandler2d784902012-10-03 23:04:50 -0400793 * Called when the dream's window has been created and is visible and animation may now begin.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700794 */
Daniel Sandler2d784902012-10-03 23:04:50 -0400795 public void onDreamingStarted() {
796 if (mDebug) Slog.v(TAG, "onDreamingStarted()");
797 // hook for subclasses
798 }
799
800 /**
801 * Called when this Dream is stopped, either by external request or by calling finish(),
802 * before the window has been removed.
803 */
804 public void onDreamingStopped() {
805 if (mDebug) Slog.v(TAG, "onDreamingStopped()");
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700806 // hook for subclasses
807 }
808
Jeff Brownf6d46682014-07-17 22:44:20 -0700809 /**
810 * Called when the dream is being asked to stop itself and wake.
811 * <p>
812 * The default implementation simply calls {@link #finish} which ends the dream
813 * immediately. Subclasses may override this function to perform a smooth exit
814 * transition then call {@link #finish} afterwards.
815 * </p><p>
816 * Note that the dream will only be given a short period of time (currently about
817 * five seconds) to wake up. If the dream does not finish itself in a timely manner
818 * then the system will forcibly finish it once the time allowance is up.
819 * </p>
820 */
821 public void onWakeUp() {
822 finish();
823 }
824
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700825 /** {@inheritDoc} */
826 @Override
827 public final IBinder onBind(Intent intent) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400828 if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700829 return new DreamServiceWrapper();
830 }
831
832 /**
Jeff Brown26875502014-01-30 21:47:47 -0800833 * Stops the dream and detaches from the window.
834 * <p>
835 * When the dream ends, the system will be allowed to go to sleep fully unless there
836 * is a reason for it to be awake such as recent user activity or wake locks being held.
837 * </p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700838 */
Daniel Sandler2d784902012-10-03 23:04:50 -0400839 public final void finish() {
Jeff Brownf6d46682014-07-17 22:44:20 -0700840 if (mDebug) Slog.v(TAG, "finish(): mFinished=" + mFinished);
841
842 if (!mFinished) {
843 mFinished = true;
844
845 if (mWindowToken == null) {
846 Slog.w(TAG, "Finish was called before the dream was attached.");
847 } else {
848 try {
849 mSandman.finishSelf(mWindowToken, true /*immediate*/);
850 } catch (RemoteException ex) {
851 // system server died
852 }
853 }
854
855 stopSelf(); // if launched via any other means
856 }
857 }
858
859 /**
860 * Wakes the dream up gently.
861 * <p>
862 * Calls {@link #onWakeUp} to give the dream a chance to perform an exit transition.
863 * When the transition is over, the dream should call {@link #finish}.
864 * </p>
865 */
866 public final void wakeUp() {
867 wakeUp(false);
868 }
869
870 private void wakeUp(boolean fromSystem) {
871 if (mDebug) Slog.v(TAG, "wakeUp(): fromSystem=" + fromSystem
872 + ", mWaking=" + mWaking + ", mFinished=" + mFinished);
873
874 if (!mWaking && !mFinished) {
875 mWaking = true;
876
877 // As a minor optimization, invoke the callback first in case it simply
878 // calls finish() immediately so there wouldn't be much point in telling
879 // the system that we are finishing the dream gently.
880 onWakeUp();
881
882 // Now tell the system we are waking gently, unless we already told
883 // it we were finishing immediately.
884 if (!fromSystem && !mFinished) {
885 if (mWindowToken == null) {
886 Slog.w(TAG, "WakeUp was called before the dream was attached.");
887 } else {
888 try {
889 mSandman.finishSelf(mWindowToken, false /*immediate*/);
890 } catch (RemoteException ex) {
891 // system server died
892 }
893 }
894 }
895 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700896 }
897
898 /** {@inheritDoc} */
899 @Override
900 public void onDestroy() {
Daniel Sandler2d784902012-10-03 23:04:50 -0400901 if (mDebug) Slog.v(TAG, "onDestroy()");
Daniel Sandler2d784902012-10-03 23:04:50 -0400902 // hook for subclasses
Daniel Sandlerc1310702012-10-09 17:44:45 -0700903
904 // Just in case destroy came in before detach, let's take care of that now
905 detach();
906
907 super.onDestroy();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700908 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400909
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700910 // end public api
911
Daniel Sandler2d784902012-10-03 23:04:50 -0400912 /**
Daniel Sandlerc1310702012-10-09 17:44:45 -0700913 * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed.
Daniel Sandler2d784902012-10-03 23:04:50 -0400914 *
915 * Must run on mHandler.
916 */
917 private final void detach() {
Jeff Brown344812d2014-04-02 20:00:36 -0700918 if (mStarted) {
919 if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
920 mStarted = false;
921 onDreamingStopped();
Daniel Sandler2d784902012-10-03 23:04:50 -0400922 }
923
Jeff Brown344812d2014-04-02 20:00:36 -0700924 if (mWindow != null) {
925 // force our window to be removed synchronously
926 if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
927 mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView());
928 mWindow = null;
929 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400930
Jeff Brown344812d2014-04-02 20:00:36 -0700931 if (mWindowToken != null) {
932 // the following will print a log message if it finds any other leaked windows
933 WindowManagerGlobal.getInstance().closeAll(mWindowToken,
934 this.getClass().getName(), "Dream");
935 mWindowToken = null;
John Spurlockbf370992014-06-17 13:58:31 -0400936 mCanDoze = false;
Jeff Brown344812d2014-04-02 20:00:36 -0700937 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400938 }
939
940 /**
941 * Called when the Dream is ready to be shown.
942 *
943 * Must run on mHandler.
944 *
945 * @param windowToken A window token that will allow a window to be created in the correct layer.
946 */
Jeff Brown26875502014-01-30 21:47:47 -0800947 private final void attach(IBinder windowToken, boolean canDoze) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400948 if (mWindowToken != null) {
949 Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
950 return;
951 }
Jeff Brownf6d46682014-07-17 22:44:20 -0700952 if (mFinished || mWaking) {
Jeff Brown26875502014-01-30 21:47:47 -0800953 Slog.w(TAG, "attach() called after dream already finished");
954 try {
Jeff Brownf6d46682014-07-17 22:44:20 -0700955 mSandman.finishSelf(windowToken, true /*immediate*/);
Jeff Brown26875502014-01-30 21:47:47 -0800956 } catch (RemoteException ex) {
957 // system server died
958 }
959 return;
960 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400961
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700962 mWindowToken = windowToken;
Jeff Brown344812d2014-04-02 20:00:36 -0700963 mCanDoze = canDoze;
John Spurlockbf370992014-06-17 13:58:31 -0400964 if (mWindowless && !mCanDoze) {
965 throw new IllegalStateException("Only doze dreams can be windowless");
Jeff Brown344812d2014-04-02 20:00:36 -0700966 }
John Spurlockbf370992014-06-17 13:58:31 -0400967 if (!mWindowless) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100968 mWindow = new PhoneWindow(this);
John Spurlockbf370992014-06-17 13:58:31 -0400969 mWindow.setCallback(this);
970 mWindow.requestFeature(Window.FEATURE_NO_TITLE);
971 mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
972 mWindow.setFormat(PixelFormat.OPAQUE);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700973
John Spurlockbf370992014-06-17 13:58:31 -0400974 if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
975 windowToken, WindowManager.LayoutParams.TYPE_DREAM));
976
977 WindowManager.LayoutParams lp = mWindow.getAttributes();
978 lp.type = WindowManager.LayoutParams.TYPE_DREAM;
979 lp.token = windowToken;
980 lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
981 lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
982 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
983 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
984 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
985 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
986 | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
987 | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
988 );
989 mWindow.setAttributes(lp);
Adrian Roos9d38f352014-09-26 01:02:49 +0200990 // Workaround: Currently low-profile and in-window system bar backgrounds don't go
991 // along well. Dreams usually don't need such bars anyways, so disable them by default.
992 mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
John Spurlockbf370992014-06-17 13:58:31 -0400993 mWindow.setWindowManager(null, windowToken, "dream", true);
994
995 applySystemUiVisibilityFlags(
996 (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
997 View.SYSTEM_UI_FLAG_LOW_PROFILE);
998
999 try {
1000 getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
1001 } catch (WindowManager.BadTokenException ex) {
1002 // This can happen because the dream manager service will remove the token
1003 // immediately without necessarily waiting for the dream to start.
1004 // We should receive a finish message soon.
1005 Slog.i(TAG, "attach() called after window token already removed, dream will "
1006 + "finish soon");
1007 mWindow = null;
1008 return;
1009 }
1010 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001011 // We need to defer calling onDreamingStarted until after onWindowAttached,
1012 // which is posted to the handler by addView, so we post onDreamingStarted
1013 // to the handler also. Need to watch out here in case detach occurs before
1014 // this callback is invoked.
1015 mHandler.post(new Runnable() {
1016 @Override
1017 public void run() {
John Spurlockbf370992014-06-17 13:58:31 -04001018 if (mWindow != null || mWindowless) {
Jeff Brown037c33e2014-04-09 00:31:55 -07001019 if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
1020 mStarted = true;
1021 onDreamingStarted();
1022 }
1023 }
1024 });
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001025 }
1026
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001027 private boolean getWindowFlagValue(int flag, boolean defaultValue) {
1028 return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
1029 }
1030
1031 private void applyWindowFlags(int flags, int mask) {
1032 if (mWindow != null) {
1033 WindowManager.LayoutParams lp = mWindow.getAttributes();
1034 lp.flags = applyFlags(lp.flags, flags, mask);
1035 mWindow.setAttributes(lp);
Jeff Brown344812d2014-04-02 20:00:36 -07001036 mWindow.getWindowManager().updateViewLayout(mWindow.getDecorView(), lp);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001037 }
1038 }
1039
1040 private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
1041 View v = mWindow == null ? null : mWindow.getDecorView();
1042 return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
1043 }
1044
1045 private void applySystemUiVisibilityFlags(int flags, int mask) {
1046 View v = mWindow == null ? null : mWindow.getDecorView();
1047 if (v != null) {
1048 v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
1049 }
1050 }
1051
1052 private int applyFlags(int oldFlags, int flags, int mask) {
1053 return (oldFlags&~mask) | (flags&mask);
1054 }
1055
Daniel Sandler2d784902012-10-03 23:04:50 -04001056 @Override
John Spurlock66127272014-06-28 11:27:17 -04001057 protected void dump(final FileDescriptor fd, PrintWriter pw, final String[] args) {
Jeff Brown26875502014-01-30 21:47:47 -08001058 DumpUtils.dumpAsync(mHandler, new Dump() {
1059 @Override
Dianne Hackbornae6688b2015-02-11 17:02:41 -08001060 public void dump(PrintWriter pw, String prefix) {
John Spurlock66127272014-06-28 11:27:17 -04001061 dumpOnHandler(fd, pw, args);
Jeff Brown26875502014-01-30 21:47:47 -08001062 }
Dianne Hackbornae6688b2015-02-11 17:02:41 -08001063 }, pw, "", 1000);
Daniel Sandler2d784902012-10-03 23:04:50 -04001064 }
1065
John Spurlock66127272014-06-28 11:27:17 -04001066 /** @hide */
1067 protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
1068 pw.print(TAG + ": ");
1069 if (mWindowToken == null) {
1070 pw.println("stopped");
1071 } else {
1072 pw.println("running (token=" + mWindowToken + ")");
1073 }
1074 pw.println(" window: " + mWindow);
1075 pw.print(" flags:");
1076 if (isInteractive()) pw.print(" interactive");
1077 if (isLowProfile()) pw.print(" lowprofile");
1078 if (isFullscreen()) pw.print(" fullscreen");
1079 if (isScreenBright()) pw.print(" bright");
1080 if (isWindowless()) pw.print(" windowless");
1081 if (isDozing()) pw.print(" dozing");
Jeff Brown970d4132014-07-19 11:33:47 -07001082 else if (canDoze()) pw.print(" candoze");
John Spurlock66127272014-06-28 11:27:17 -04001083 pw.println();
Jeff Brown970d4132014-07-19 11:33:47 -07001084 if (canDoze()) {
Jeff Brown970d4132014-07-19 11:33:47 -07001085 pw.println(" doze screen state: " + Display.stateToString(mDozeScreenState));
1086 pw.println(" doze screen brightness: " + mDozeScreenBrightness);
1087 }
1088 }
1089
1090 private static int clampAbsoluteBrightness(int value) {
1091 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
John Spurlock66127272014-06-28 11:27:17 -04001092 }
1093
Jeff Brown26875502014-01-30 21:47:47 -08001094 private final class DreamServiceWrapper extends IDreamService.Stub {
1095 @Override
1096 public void attach(final IBinder windowToken, final boolean canDoze) {
Daniel Sandler2d784902012-10-03 23:04:50 -04001097 mHandler.post(new Runnable() {
1098 @Override
1099 public void run() {
Jeff Brown26875502014-01-30 21:47:47 -08001100 DreamService.this.attach(windowToken, canDoze);
Daniel Sandler2d784902012-10-03 23:04:50 -04001101 }
1102 });
1103 }
Jeff Brown26875502014-01-30 21:47:47 -08001104
1105 @Override
Daniel Sandler2d784902012-10-03 23:04:50 -04001106 public void detach() {
1107 mHandler.post(new Runnable() {
1108 @Override
1109 public void run() {
1110 DreamService.this.detach();
1111 }
1112 });
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001113 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001114
Jeff Brownf6d46682014-07-17 22:44:20 -07001115 @Override
1116 public void wakeUp() {
1117 mHandler.post(new Runnable() {
1118 @Override
1119 public void run() {
1120 DreamService.this.wakeUp(true /*fromSystem*/);
1121 }
1122 });
1123 }
1124 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001125}