blob: 0557d138eb741a11c77d43c22d2577b274bfe1bd [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;
38import android.view.Menu;
39import android.view.MenuItem;
40import android.view.MotionEvent;
Tim Kilbourn6a975b32015-04-09 17:14:34 -070041import android.view.SearchEvent;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070042import android.view.View;
43import android.view.ViewGroup;
44import android.view.Window;
45import android.view.WindowManager;
46import android.view.WindowManager.LayoutParams;
Clara Bayarri75e09792015-07-29 16:20:40 +010047import android.view.WindowManagerGlobal;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070048import android.view.accessibility.AccessibilityEvent;
49
Clara Bayarri75e09792015-07-29 16:20:40 +010050import com.android.internal.policy.PhoneWindow;
Jeff Brown26875502014-01-30 21:47:47 -080051import com.android.internal.util.DumpUtils;
52import com.android.internal.util.DumpUtils.Dump;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070053
Clara Bayarri75e09792015-07-29 16:20:40 +010054import java.io.FileDescriptor;
55import java.io.PrintWriter;
56import java.util.List;
57
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070058/**
Scott Main6c9a1a12012-11-19 11:58:59 -080059 * Extend this class to implement a custom dream (available to the user as a "Daydream").
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070060 *
61 * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
62 * desk dock. Dreams provide another modality for apps to express themselves, tailored for
63 * an exhibition/lean-back experience.</p>
64 *
Scott Main6c9a1a12012-11-19 11:58:59 -080065 * <p>The {@code DreamService} lifecycle is as follows:</p>
Scott Main6237ac12012-10-08 22:30:29 -070066 * <ol>
67 * <li>{@link #onAttachedToWindow}
68 * <p>Use this for initial setup, such as calling {@link #setContentView setContentView()}.</li>
69 * <li>{@link #onDreamingStarted}
70 * <p>Your dream has started, so you should begin animations or other behaviors here.</li>
71 * <li>{@link #onDreamingStopped}
72 * <p>Use this to stop the things you started in {@link #onDreamingStarted}.</li>
73 * <li>{@link #onDetachedFromWindow}
Scott Main6c9a1a12012-11-19 11:58:59 -080074 * <p>Use this to dismantle resources (for example, detach from handlers
75 * and listeners).</li>
Scott Main6237ac12012-10-08 22:30:29 -070076 * </ol>
Daniel Sandler2d784902012-10-03 23:04:50 -040077 *
78 * <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but
79 * initialization and teardown should be done by overriding the hooks above.</p>
80 *
Scott Main6c9a1a12012-11-19 11:58:59 -080081 * <p>To be available to the system, your {@code DreamService} should be declared in the
82 * manifest as follows:</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070083 * <pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -040084 * &lt;service
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070085 * android:name=".MyDream"
86 * android:exported="true"
87 * android:icon="@drawable/my_icon"
88 * android:label="@string/my_dream_label" >
89 *
John Spurlock3a4d41a2012-10-01 09:30:49 -040090 * &lt;intent-filter>
91 * &lt;action android:name="android.service.dreams.DreamService" />
92 * &lt;category android:name="android.intent.category.DEFAULT" />
93 * &lt;/intent-filter>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070094 *
John Spurlock3a4d41a2012-10-01 09:30:49 -040095 * &lt;!-- Point to additional information for this dream (optional) -->
96 * &lt;meta-data
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -070097 * android:name="android.service.dream"
98 * android:resource="@xml/my_dream" />
John Spurlock3a4d41a2012-10-01 09:30:49 -040099 * &lt;/service>
100 * </pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -0400101 *
Neil Fuller71fbb812015-11-30 09:51:33 +0000102 * <p>If specified with the {@code <meta-data>} element,
Scott Main6237ac12012-10-08 22:30:29 -0700103 * additional information for the dream is defined using the
104 * {@link android.R.styleable#Dream &lt;dream&gt;} element in a separate XML file.
105 * Currently, the only addtional
106 * information you can provide is for a settings activity that allows the user to configure
107 * the dream behavior. For example:</p>
108 * <p class="code-caption">res/xml/my_dream.xml</p>
109 * <pre>
John Spurlock3a4d41a2012-10-01 09:30:49 -0400110 * &lt;dream xmlns:android="http://schemas.android.com/apk/res/android"
111 * android:settingsActivity="com.example.app/.MyDreamSettingsActivity" />
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700112 * </pre>
Scott Main6237ac12012-10-08 22:30:29 -0700113 * <p>This makes a Settings button available alongside your dream's listing in the
114 * system settings, which when pressed opens the specified activity.</p>
115 *
116 *
117 * <p>To specify your dream layout, call {@link #setContentView}, typically during the
118 * {@link #onAttachedToWindow} callback. For example:</p>
119 * <pre>
120 * public class MyDream extends DreamService {
121 *
122 * &#64;Override
123 * public void onAttachedToWindow() {
124 * super.onAttachedToWindow();
125 *
126 * // Exit dream upon user touch
127 * setInteractive(false);
128 * // Hide system UI
129 * setFullscreen(true);
130 * // Set the dream layout
131 * setContentView(R.layout.dream);
132 * }
133 * }
134 * </pre>
John Spurlockeb8d1be2014-06-25 17:46:15 -0400135 *
136 * <p>When targeting api level 21 and above, you must declare the service in your manifest file
137 * with the {@link android.Manifest.permission#BIND_DREAM_SERVICE} permission. For example:</p>
138 * <pre>
139 * &lt;service
140 * android:name=".MyDream"
141 * android:exported="true"
142 * android:icon="@drawable/my_icon"
143 * android:label="@string/my_dream_label"
Jeff Brown970d4132014-07-19 11:33:47 -0700144 * android:permission="android.permission.BIND_DREAM_SERVICE">
145 * &lt;intent-filter>
146 * &lt;action android:name=”android.service.dreams.DreamService” />
147 * &lt;category android:name=”android.intent.category.DEFAULT” />
148 * &lt;/intent-filter>
John Spurlockeb8d1be2014-06-25 17:46:15 -0400149 * &lt;/service>
150 * </pre>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700151 */
152public class DreamService extends Service implements Window.Callback {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700153 private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
154
155 /**
156 * The name of the dream manager service.
157 * @hide
158 */
159 public static final String DREAM_SERVICE = "dreams";
160
161 /**
162 * The {@link Intent} that must be declared as handled by the service.
163 */
164 @SdkConstant(SdkConstantType.SERVICE_ACTION)
165 public static final String SERVICE_INTERFACE =
166 "android.service.dreams.DreamService";
167
168 /**
169 * Name under which a Dream publishes information about itself.
170 * This meta-data must reference an XML resource containing
171 * a <code>&lt;{@link android.R.styleable#Dream dream}&gt;</code>
172 * tag.
173 */
174 public static final String DREAM_META_DATA = "android.service.dream";
175
Jeff Brown26875502014-01-30 21:47:47 -0800176 private final IDreamManager mSandman;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700177 private final Handler mHandler = new Handler();
178 private IBinder mWindowToken;
179 private Window mWindow;
Jeff Brown344812d2014-04-02 20:00:36 -0700180 private boolean mInteractive;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700181 private boolean mLowProfile = true;
Jeff Brown344812d2014-04-02 20:00:36 -0700182 private boolean mFullscreen;
Chris Wrena934fd12012-10-08 18:19:16 -0400183 private boolean mScreenBright = true;
Jeff Brown344812d2014-04-02 20:00:36 -0700184 private boolean mStarted;
Jeff Brownf6d46682014-07-17 22:44:20 -0700185 private boolean mWaking;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700186 private boolean mFinished;
Jeff Brown26875502014-01-30 21:47:47 -0800187 private boolean mCanDoze;
188 private boolean mDozing;
John Spurlockbf370992014-06-17 13:58:31 -0400189 private boolean mWindowless;
Jeff Brown970d4132014-07-19 11:33:47 -0700190 private int mDozeScreenState = Display.STATE_UNKNOWN;
191 private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700192
Daniel Sandler2d784902012-10-03 23:04:50 -0400193 private boolean mDebug = false;
194
Jeff Brown26875502014-01-30 21:47:47 -0800195 public DreamService() {
196 mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
197 }
198
Daniel Sandler2d784902012-10-03 23:04:50 -0400199 /**
200 * @hide
201 */
202 public void setDebug(boolean dbg) {
203 mDebug = dbg;
204 }
205
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700206 // begin Window.Callback methods
207 /** {@inheritDoc} */
208 @Override
209 public boolean dispatchKeyEvent(KeyEvent event) {
210 // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
211 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700212 if (mDebug) Slog.v(TAG, "Waking up on keyEvent");
213 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700214 return true;
215 } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700216 if (mDebug) Slog.v(TAG, "Waking up on back key");
217 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700218 return true;
219 }
220 return mWindow.superDispatchKeyEvent(event);
221 }
222
223 /** {@inheritDoc} */
224 @Override
225 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400226 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700227 if (mDebug) Slog.v(TAG, "Waking up on keyShortcutEvent");
228 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700229 return true;
230 }
231 return mWindow.superDispatchKeyShortcutEvent(event);
232 }
233
234 /** {@inheritDoc} */
235 @Override
236 public boolean dispatchTouchEvent(MotionEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400237 // TODO: create more flexible version of mInteractive that allows clicks
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700238 // but finish()es on any other kind of activity
Daniel Sandler2d784902012-10-03 23:04:50 -0400239 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700240 if (mDebug) Slog.v(TAG, "Waking up on touchEvent");
241 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700242 return true;
243 }
244 return mWindow.superDispatchTouchEvent(event);
245 }
246
247 /** {@inheritDoc} */
248 @Override
249 public boolean dispatchTrackballEvent(MotionEvent event) {
250 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700251 if (mDebug) Slog.v(TAG, "Waking up on trackballEvent");
252 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700253 return true;
254 }
255 return mWindow.superDispatchTrackballEvent(event);
256 }
257
258 /** {@inheritDoc} */
259 @Override
260 public boolean dispatchGenericMotionEvent(MotionEvent event) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400261 if (!mInteractive) {
Jeff Brownf6d46682014-07-17 22:44:20 -0700262 if (mDebug) Slog.v(TAG, "Waking up on genericMotionEvent");
263 wakeUp();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700264 return true;
265 }
266 return mWindow.superDispatchGenericMotionEvent(event);
267 }
268
269 /** {@inheritDoc} */
270 @Override
271 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
272 return false;
273 }
274
275 /** {@inheritDoc} */
276 @Override
277 public View onCreatePanelView(int featureId) {
278 return null;
279 }
280
281 /** {@inheritDoc} */
282 @Override
283 public boolean onCreatePanelMenu(int featureId, Menu menu) {
284 return false;
285 }
286
287 /** {@inheritDoc} */
288 @Override
289 public boolean onPreparePanel(int featureId, View view, Menu menu) {
290 return false;
291 }
292
293 /** {@inheritDoc} */
294 @Override
295 public boolean onMenuOpened(int featureId, Menu menu) {
296 return false;
297 }
298
299 /** {@inheritDoc} */
300 @Override
301 public boolean onMenuItemSelected(int featureId, MenuItem item) {
302 return false;
303 }
304
305 /** {@inheritDoc} */
306 @Override
307 public void onWindowAttributesChanged(LayoutParams attrs) {
308 }
309
310 /** {@inheritDoc} */
311 @Override
312 public void onContentChanged() {
313 }
314
315 /** {@inheritDoc} */
316 @Override
317 public void onWindowFocusChanged(boolean hasFocus) {
318 }
319
320 /** {@inheritDoc} */
321 @Override
322 public void onAttachedToWindow() {
323 }
324
325 /** {@inheritDoc} */
326 @Override
327 public void onDetachedFromWindow() {
328 }
329
330 /** {@inheritDoc} */
331 @Override
332 public void onPanelClosed(int featureId, Menu menu) {
333 }
334
335 /** {@inheritDoc} */
336 @Override
Tim Kilbourn6a975b32015-04-09 17:14:34 -0700337 public boolean onSearchRequested(SearchEvent event) {
338 return onSearchRequested();
339 }
340
341 /** {@inheritDoc} */
342 @Override
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700343 public boolean onSearchRequested() {
344 return false;
345 }
346
347 /** {@inheritDoc} */
348 @Override
349 public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
350 return null;
351 }
352
353 /** {@inheritDoc} */
354 @Override
Clara Bayarri4423d912015-03-02 19:42:48 +0000355 public ActionMode onWindowStartingActionMode(
356 android.view.ActionMode.Callback callback, int type) {
357 return null;
358 }
359
360 /** {@inheritDoc} */
361 @Override
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700362 public void onActionModeStarted(ActionMode mode) {
363 }
364
365 /** {@inheritDoc} */
366 @Override
367 public void onActionModeFinished(ActionMode mode) {
368 }
369 // end Window.Callback methods
370
371 // begin public api
372 /**
373 * Retrieves the current {@link android.view.WindowManager} for the dream.
374 * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
375 *
376 * @return The current window manager, or null if the dream is not started.
377 */
378 public WindowManager getWindowManager() {
Jeff Brown344812d2014-04-02 20:00:36 -0700379 return mWindow != null ? mWindow.getWindowManager() : null;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700380 }
381
382 /**
383 * Retrieves the current {@link android.view.Window} for the dream.
384 * Behaves similarly to {@link android.app.Activity#getWindow()}.
385 *
386 * @return The current window, or null if the dream is not started.
387 */
388 public Window getWindow() {
389 return mWindow;
390 }
391
392 /**
393 * Inflates a layout resource and set it to be the content view for this Dream.
394 * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
395 *
396 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
397 *
398 * @param layoutResID Resource ID to be inflated.
Daniel Sandler2d784902012-10-03 23:04:50 -0400399 *
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700400 * @see #setContentView(android.view.View)
401 * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
402 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700403 public void setContentView(@LayoutRes int layoutResID) {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700404 getWindow().setContentView(layoutResID);
405 }
406
407 /**
408 * Sets a view to be the content view for this Dream.
Scott Main6237ac12012-10-08 22:30:29 -0700409 * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)} in an activity,
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700410 * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
411 *
Scott Main6237ac12012-10-08 22:30:29 -0700412 * <p>Note: This requires a window, so you should usually call it during
413 * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
414 * during {@link #onCreate}).</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700415 *
416 * @see #setContentView(int)
417 * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
418 */
419 public void setContentView(View view) {
420 getWindow().setContentView(view);
421 }
422
423 /**
424 * Sets a view to be the content view for this Dream.
Daniel Sandler2d784902012-10-03 23:04:50 -0400425 * Behaves similarly to
Scott Main6237ac12012-10-08 22:30:29 -0700426 * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
427 * in an activity.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700428 *
Scott Main6237ac12012-10-08 22:30:29 -0700429 * <p>Note: This requires a window, so you should usually call it during
430 * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
431 * during {@link #onCreate}).</p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700432 *
433 * @param view The desired content to display.
434 * @param params Layout parameters for the view.
435 *
436 * @see #setContentView(android.view.View)
437 * @see #setContentView(int)
438 */
439 public void setContentView(View view, ViewGroup.LayoutParams params) {
440 getWindow().setContentView(view, params);
441 }
442
443 /**
444 * Adds a view to the Dream's window, leaving other content views in place.
445 *
446 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
447 *
448 * @param view The desired content to display.
449 * @param params Layout parameters for the view.
450 */
451 public void addContentView(View view, ViewGroup.LayoutParams params) {
452 getWindow().addContentView(view, params);
453 }
454
455 /**
456 * Finds a view that was identified by the id attribute from the XML that
457 * was processed in {@link #onCreate}.
458 *
459 * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
460 *
461 * @return The view if found or null otherwise.
462 */
Scott Kennedyc0519552015-02-11 15:33:10 -0800463 @Nullable
Tor Norbye7b9c9122013-05-30 16:48:33 -0700464 public View findViewById(@IdRes int id) {
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700465 return getWindow().findViewById(id);
466 }
467
468 /**
469 * Marks this dream as interactive to receive input events.
470 *
471 * <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
472 *
473 * <p>Interactive dreams should call {@link #finish()} to dismiss themselves.</p>
474 *
475 * @param interactive True if this dream will handle input events.
476 */
477 public void setInteractive(boolean interactive) {
478 mInteractive = interactive;
479 }
480
481 /**
482 * Returns whether or not this dream is interactive. Defaults to false.
483 *
484 * @see #setInteractive(boolean)
485 */
486 public boolean isInteractive() {
487 return mInteractive;
488 }
489
490 /**
491 * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
492 *
493 * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700494 * @hide There is no reason to have this -- dreams can set this flag
495 * on their own content view, and from there can actually do the
496 * correct interactions with it (seeing when it is cleared etc).
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700497 */
498 public void setLowProfile(boolean lowProfile) {
Jeff Brown26875502014-01-30 21:47:47 -0800499 if (mLowProfile != lowProfile) {
500 mLowProfile = lowProfile;
501 int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
502 applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
503 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700504 }
505
506 /**
507 * Returns whether or not this dream is in low profile mode. Defaults to true.
508 *
509 * @see #setLowProfile(boolean)
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700510 * @hide
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700511 */
512 public boolean isLowProfile() {
513 return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
514 }
515
516 /**
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700517 * Controls {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN}
518 * on the dream's window.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700519 *
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700520 * @param fullscreen If true, the fullscreen flag will be set; else it
521 * will be cleared.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700522 */
523 public void setFullscreen(boolean fullscreen) {
Jeff Brown26875502014-01-30 21:47:47 -0800524 if (mFullscreen != fullscreen) {
525 mFullscreen = fullscreen;
526 int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
527 applyWindowFlags(mFullscreen ? flag : 0, flag);
528 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700529 }
530
531 /**
532 * Returns whether or not this dream is in fullscreen mode. Defaults to false.
533 *
534 * @see #setFullscreen(boolean)
535 */
536 public boolean isFullscreen() {
Dianne Hackborn4c1e3182012-10-05 18:37:54 -0700537 return mFullscreen;
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700538 }
539
540 /**
541 * Marks this dream as keeping the screen bright while dreaming.
542 *
543 * @param screenBright True to keep the screen bright while dreaming.
544 */
545 public void setScreenBright(boolean screenBright) {
Jeff Brown26875502014-01-30 21:47:47 -0800546 if (mScreenBright != screenBright) {
547 mScreenBright = screenBright;
548 int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
549 applyWindowFlags(mScreenBright ? flag : 0, flag);
550 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700551 }
552
553 /**
Jeff Brown26875502014-01-30 21:47:47 -0800554 * Returns whether or not this dream keeps the screen bright while dreaming.
555 * Defaults to false, allowing the screen to dim if necessary.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700556 *
557 * @see #setScreenBright(boolean)
558 */
559 public boolean isScreenBright() {
560 return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
561 }
562
563 /**
John Spurlockbf370992014-06-17 13:58:31 -0400564 * Marks this dream as windowless. Only available to doze dreams.
565 *
566 * @hide
567 */
568 public void setWindowless(boolean windowless) {
569 mWindowless = windowless;
570 }
571
572 /**
573 * Returns whether or not this dream is windowless. Only available to doze dreams.
574 *
575 * @hide
576 */
577 public boolean isWindowless() {
578 return mWindowless;
579 }
580
581 /**
Jeff Brown26875502014-01-30 21:47:47 -0800582 * Returns true if this dream is allowed to doze.
583 * <p>
584 * The value returned by this method is only meaningful when the dream has started.
585 * </p>
586 *
587 * @return True if this dream can doze.
588 * @see #startDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700589 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800590 */
591 public boolean canDoze() {
592 return mCanDoze;
593 }
594
595 /**
596 * Starts dozing, entering a deep dreamy sleep.
597 * <p>
598 * Dozing enables the system to conserve power while the user is not actively interacting
599 * with the device. While dozing, the display will remain on in a low-power state
600 * and will continue to show its previous contents but the application processor and
601 * other system components will be allowed to suspend when possible.
602 * </p><p>
603 * While the application processor is suspended, the dream may stop executing code
604 * for long periods of time. Prior to being suspended, the dream may schedule periodic
605 * wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}.
606 * The dream may also keep the CPU awake by acquiring a
607 * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary.
608 * Note that since the purpose of doze mode is to conserve power (especially when
609 * running on battery), the dream should not wake the CPU very often or keep it
610 * awake for very long.
611 * </p><p>
612 * It is a good idea to call this method some time after the dream's entry animation
613 * has completed and the dream is ready to doze. It is important to completely
614 * finish all of the work needed before dozing since the application processor may
615 * be suspended at any moment once this method is called unless other wake locks
616 * are being held.
617 * </p><p>
618 * Call {@link #stopDozing} or {@link #finish} to stop dozing.
619 * </p>
620 *
621 * @see #stopDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700622 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800623 */
624 public void startDozing() {
625 if (mCanDoze && !mDozing) {
626 mDozing = true;
Jeff Brown970d4132014-07-19 11:33:47 -0700627 updateDoze();
628 }
629 }
630
631 private void updateDoze() {
632 if (mDozing) {
Jeff Brown26875502014-01-30 21:47:47 -0800633 try {
Jeff Brown970d4132014-07-19 11:33:47 -0700634 mSandman.startDozing(mWindowToken, mDozeScreenState, mDozeScreenBrightness);
Jeff Brown26875502014-01-30 21:47:47 -0800635 } catch (RemoteException ex) {
636 // system server died
637 }
638 }
639 }
640
641 /**
642 * Stops dozing, returns to active dreaming.
643 * <p>
644 * This method reverses the effect of {@link #startDozing}. From this moment onward,
645 * the application processor will be kept awake as long as the dream is running
646 * or until the dream starts dozing again.
647 * </p>
648 *
649 * @see #startDozing
Jeff Brown970d4132014-07-19 11:33:47 -0700650 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800651 */
652 public void stopDozing() {
653 if (mDozing) {
654 mDozing = false;
655 try {
656 mSandman.stopDozing(mWindowToken);
657 } catch (RemoteException ex) {
658 // system server died
659 }
660 }
661 }
662
663 /**
664 * Returns true if the dream will allow the system to enter a low-power state while
665 * it is running without actually turning off the screen. Defaults to false,
666 * keeping the application processor awake while the dream is running.
667 *
668 * @return True if the dream is dozing.
669 *
670 * @see #setDozing(boolean)
Jeff Brown970d4132014-07-19 11:33:47 -0700671 * @hide For use by system UI components only.
Jeff Brown26875502014-01-30 21:47:47 -0800672 */
673 public boolean isDozing() {
674 return mDozing;
675 }
676
677 /**
Jeff Brown970d4132014-07-19 11:33:47 -0700678 * Gets the screen state to use while dozing.
679 *
680 * @return The screen state to use while dozing, such as {@link Display#STATE_ON},
681 * {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
682 * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
683 * behavior.
684 *
685 * @see #setDozeScreenState
686 * @hide For use by system UI components only.
687 */
688 public int getDozeScreenState() {
689 return mDozeScreenState;
690 }
691
692 /**
693 * Sets the screen state to use while dozing.
694 * <p>
695 * The value of this property determines the power state of the primary display
696 * once {@link #startDozing} has been called. The default value is
697 * {@link Display#STATE_UNKNOWN} which lets the system decide.
698 * The dream may set a different state before starting to doze and may
699 * perform transitions between states while dozing to conserve power and
700 * achieve various effects.
701 * </p><p>
702 * It is recommended that the state be set to {@link Display#STATE_DOZE_SUSPEND}
703 * once the dream has completely finished drawing and before it releases its wakelock
704 * to allow the display hardware to be fully suspended. While suspended, the
705 * display will preserve its on-screen contents or hand off control to dedicated
706 * doze hardware if the devices supports it. If the doze suspend state is
707 * used, the dream must make sure to set the mode back
708 * to {@link Display#STATE_DOZE} or {@link Display#STATE_ON} before drawing again
709 * since the display updates may be ignored and not seen by the user otherwise.
710 * </p><p>
711 * The set of available display power states and their behavior while dozing is
712 * hardware dependent and may vary across devices. The dream may therefore
713 * need to be modified or configured to correctly support the hardware.
714 * </p>
715 *
716 * @param state The screen state to use while dozing, such as {@link Display#STATE_ON},
717 * {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
718 * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
719 * behavior.
720 *
721 * @hide For use by system UI components only.
722 */
723 public void setDozeScreenState(int state) {
724 if (mDozeScreenState != state) {
725 mDozeScreenState = state;
726 updateDoze();
727 }
728 }
729
730 /**
731 * Gets the screen brightness to use while dozing.
732 *
733 * @return The screen brightness while dozing as a value between
734 * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
735 * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
736 * its default policy based on the screen state.
737 *
738 * @see #setDozeScreenBrightness
739 * @hide For use by system UI components only.
740 */
741 public int getDozeScreenBrightness() {
742 return mDozeScreenBrightness;
743 }
744
745 /**
746 * Sets the screen brightness to use while dozing.
747 * <p>
748 * The value of this property determines the power state of the primary display
749 * once {@link #startDozing} has been called. The default value is
750 * {@link PowerManager#BRIGHTNESS_DEFAULT} which lets the system decide.
751 * The dream may set a different brightness before starting to doze and may adjust
752 * the brightness while dozing to conserve power and achieve various effects.
753 * </p><p>
754 * Note that dream may specify any brightness in the full 0-255 range, including
755 * values that are less than the minimum value for manual screen brightness
756 * adjustments by the user. In particular, the value may be set to 0 which may
757 * turn off the backlight entirely while still leaving the screen on although
758 * this behavior is device dependent and not guaranteed.
759 * </p><p>
760 * The available range of display brightness values and their behavior while dozing is
761 * hardware dependent and may vary across devices. The dream may therefore
762 * need to be modified or configured to correctly support the hardware.
763 * </p>
764 *
765 * @param brightness The screen brightness while dozing as a value between
766 * {@link PowerManager#BRIGHTNESS_OFF} (0) and {@link PowerManager#BRIGHTNESS_ON} (255),
767 * or {@link PowerManager#BRIGHTNESS_DEFAULT} (-1) to ask the system to apply
768 * its default policy based on the screen state.
769 *
770 * @hide For use by system UI components only.
771 */
772 public void setDozeScreenBrightness(int brightness) {
773 if (brightness != PowerManager.BRIGHTNESS_DEFAULT) {
774 brightness = clampAbsoluteBrightness(brightness);
775 }
776 if (mDozeScreenBrightness != brightness) {
777 mDozeScreenBrightness = brightness;
778 updateDoze();
779 }
780 }
781
782 /**
Daniel Sandler2d784902012-10-03 23:04:50 -0400783 * Called when this Dream is constructed.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700784 */
785 @Override
786 public void onCreate() {
Jeff Brown970d4132014-07-19 11:33:47 -0700787 if (mDebug) Slog.v(TAG, "onCreate()");
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700788 super.onCreate();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700789 }
790
791 /**
Daniel Sandler2d784902012-10-03 23:04:50 -0400792 * Called when the dream's window has been created and is visible and animation may now begin.
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700793 */
Daniel Sandler2d784902012-10-03 23:04:50 -0400794 public void onDreamingStarted() {
795 if (mDebug) Slog.v(TAG, "onDreamingStarted()");
796 // hook for subclasses
797 }
798
799 /**
800 * Called when this Dream is stopped, either by external request or by calling finish(),
801 * before the window has been removed.
802 */
803 public void onDreamingStopped() {
804 if (mDebug) Slog.v(TAG, "onDreamingStopped()");
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700805 // hook for subclasses
806 }
807
Jeff Brownf6d46682014-07-17 22:44:20 -0700808 /**
809 * Called when the dream is being asked to stop itself and wake.
810 * <p>
811 * The default implementation simply calls {@link #finish} which ends the dream
812 * immediately. Subclasses may override this function to perform a smooth exit
813 * transition then call {@link #finish} afterwards.
814 * </p><p>
815 * Note that the dream will only be given a short period of time (currently about
816 * five seconds) to wake up. If the dream does not finish itself in a timely manner
817 * then the system will forcibly finish it once the time allowance is up.
818 * </p>
819 */
820 public void onWakeUp() {
821 finish();
822 }
823
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700824 /** {@inheritDoc} */
825 @Override
826 public final IBinder onBind(Intent intent) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400827 if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700828 return new DreamServiceWrapper();
829 }
830
831 /**
Jeff Brown26875502014-01-30 21:47:47 -0800832 * Stops the dream and detaches from the window.
833 * <p>
834 * When the dream ends, the system will be allowed to go to sleep fully unless there
835 * is a reason for it to be awake such as recent user activity or wake locks being held.
836 * </p>
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700837 */
Daniel Sandler2d784902012-10-03 23:04:50 -0400838 public final void finish() {
Jeff Brownf6d46682014-07-17 22:44:20 -0700839 if (mDebug) Slog.v(TAG, "finish(): mFinished=" + mFinished);
840
841 if (!mFinished) {
842 mFinished = true;
843
844 if (mWindowToken == null) {
845 Slog.w(TAG, "Finish was called before the dream was attached.");
846 } else {
847 try {
848 mSandman.finishSelf(mWindowToken, true /*immediate*/);
849 } catch (RemoteException ex) {
850 // system server died
851 }
852 }
853
854 stopSelf(); // if launched via any other means
855 }
856 }
857
858 /**
859 * Wakes the dream up gently.
860 * <p>
861 * Calls {@link #onWakeUp} to give the dream a chance to perform an exit transition.
862 * When the transition is over, the dream should call {@link #finish}.
863 * </p>
864 */
865 public final void wakeUp() {
866 wakeUp(false);
867 }
868
869 private void wakeUp(boolean fromSystem) {
870 if (mDebug) Slog.v(TAG, "wakeUp(): fromSystem=" + fromSystem
871 + ", mWaking=" + mWaking + ", mFinished=" + mFinished);
872
873 if (!mWaking && !mFinished) {
874 mWaking = true;
875
876 // As a minor optimization, invoke the callback first in case it simply
877 // calls finish() immediately so there wouldn't be much point in telling
878 // the system that we are finishing the dream gently.
879 onWakeUp();
880
881 // Now tell the system we are waking gently, unless we already told
882 // it we were finishing immediately.
883 if (!fromSystem && !mFinished) {
884 if (mWindowToken == null) {
885 Slog.w(TAG, "WakeUp was called before the dream was attached.");
886 } else {
887 try {
888 mSandman.finishSelf(mWindowToken, false /*immediate*/);
889 } catch (RemoteException ex) {
890 // system server died
891 }
892 }
893 }
894 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700895 }
896
897 /** {@inheritDoc} */
898 @Override
899 public void onDestroy() {
Daniel Sandler2d784902012-10-03 23:04:50 -0400900 if (mDebug) Slog.v(TAG, "onDestroy()");
Daniel Sandler2d784902012-10-03 23:04:50 -0400901 // hook for subclasses
Daniel Sandlerc1310702012-10-09 17:44:45 -0700902
903 // Just in case destroy came in before detach, let's take care of that now
904 detach();
905
906 super.onDestroy();
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700907 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400908
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700909 // end public api
910
Daniel Sandler2d784902012-10-03 23:04:50 -0400911 /**
Daniel Sandlerc1310702012-10-09 17:44:45 -0700912 * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed.
Daniel Sandler2d784902012-10-03 23:04:50 -0400913 *
914 * Must run on mHandler.
915 */
916 private final void detach() {
Jeff Brown344812d2014-04-02 20:00:36 -0700917 if (mStarted) {
918 if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
919 mStarted = false;
920 onDreamingStopped();
Daniel Sandler2d784902012-10-03 23:04:50 -0400921 }
922
Jeff Brown344812d2014-04-02 20:00:36 -0700923 if (mWindow != null) {
924 // force our window to be removed synchronously
925 if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
926 mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView());
927 mWindow = null;
928 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400929
Jeff Brown344812d2014-04-02 20:00:36 -0700930 if (mWindowToken != null) {
931 // the following will print a log message if it finds any other leaked windows
932 WindowManagerGlobal.getInstance().closeAll(mWindowToken,
933 this.getClass().getName(), "Dream");
934 mWindowToken = null;
John Spurlockbf370992014-06-17 13:58:31 -0400935 mCanDoze = false;
Jeff Brown344812d2014-04-02 20:00:36 -0700936 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400937 }
938
939 /**
940 * Called when the Dream is ready to be shown.
941 *
942 * Must run on mHandler.
943 *
944 * @param windowToken A window token that will allow a window to be created in the correct layer.
945 */
Jeff Brown26875502014-01-30 21:47:47 -0800946 private final void attach(IBinder windowToken, boolean canDoze) {
Daniel Sandler2d784902012-10-03 23:04:50 -0400947 if (mWindowToken != null) {
948 Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
949 return;
950 }
Jeff Brownf6d46682014-07-17 22:44:20 -0700951 if (mFinished || mWaking) {
Jeff Brown26875502014-01-30 21:47:47 -0800952 Slog.w(TAG, "attach() called after dream already finished");
953 try {
Jeff Brownf6d46682014-07-17 22:44:20 -0700954 mSandman.finishSelf(windowToken, true /*immediate*/);
Jeff Brown26875502014-01-30 21:47:47 -0800955 } catch (RemoteException ex) {
956 // system server died
957 }
958 return;
959 }
Daniel Sandler2d784902012-10-03 23:04:50 -0400960
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700961 mWindowToken = windowToken;
Jeff Brown344812d2014-04-02 20:00:36 -0700962 mCanDoze = canDoze;
John Spurlockbf370992014-06-17 13:58:31 -0400963 if (mWindowless && !mCanDoze) {
964 throw new IllegalStateException("Only doze dreams can be windowless");
Jeff Brown344812d2014-04-02 20:00:36 -0700965 }
John Spurlockbf370992014-06-17 13:58:31 -0400966 if (!mWindowless) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100967 mWindow = new PhoneWindow(this);
John Spurlockbf370992014-06-17 13:58:31 -0400968 mWindow.setCallback(this);
969 mWindow.requestFeature(Window.FEATURE_NO_TITLE);
970 mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
971 mWindow.setFormat(PixelFormat.OPAQUE);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -0700972
John Spurlockbf370992014-06-17 13:58:31 -0400973 if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
974 windowToken, WindowManager.LayoutParams.TYPE_DREAM));
975
976 WindowManager.LayoutParams lp = mWindow.getAttributes();
977 lp.type = WindowManager.LayoutParams.TYPE_DREAM;
978 lp.token = windowToken;
979 lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
980 lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
981 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
982 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
983 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
984 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
985 | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
986 | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
987 );
988 mWindow.setAttributes(lp);
Adrian Roos9d38f352014-09-26 01:02:49 +0200989 // Workaround: Currently low-profile and in-window system bar backgrounds don't go
990 // along well. Dreams usually don't need such bars anyways, so disable them by default.
991 mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
John Spurlockbf370992014-06-17 13:58:31 -0400992 mWindow.setWindowManager(null, windowToken, "dream", true);
993
994 applySystemUiVisibilityFlags(
995 (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
996 View.SYSTEM_UI_FLAG_LOW_PROFILE);
997
998 try {
999 getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
1000 } catch (WindowManager.BadTokenException ex) {
1001 // This can happen because the dream manager service will remove the token
1002 // immediately without necessarily waiting for the dream to start.
1003 // We should receive a finish message soon.
1004 Slog.i(TAG, "attach() called after window token already removed, dream will "
1005 + "finish soon");
1006 mWindow = null;
1007 return;
1008 }
1009 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001010 // We need to defer calling onDreamingStarted until after onWindowAttached,
1011 // which is posted to the handler by addView, so we post onDreamingStarted
1012 // to the handler also. Need to watch out here in case detach occurs before
1013 // this callback is invoked.
1014 mHandler.post(new Runnable() {
1015 @Override
1016 public void run() {
John Spurlockbf370992014-06-17 13:58:31 -04001017 if (mWindow != null || mWindowless) {
Jeff Brown037c33e2014-04-09 00:31:55 -07001018 if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
1019 mStarted = true;
1020 onDreamingStarted();
1021 }
1022 }
1023 });
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001024 }
1025
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001026 private boolean getWindowFlagValue(int flag, boolean defaultValue) {
1027 return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
1028 }
1029
1030 private void applyWindowFlags(int flags, int mask) {
1031 if (mWindow != null) {
1032 WindowManager.LayoutParams lp = mWindow.getAttributes();
1033 lp.flags = applyFlags(lp.flags, flags, mask);
1034 mWindow.setAttributes(lp);
Jeff Brown344812d2014-04-02 20:00:36 -07001035 mWindow.getWindowManager().updateViewLayout(mWindow.getDecorView(), lp);
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001036 }
1037 }
1038
1039 private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
1040 View v = mWindow == null ? null : mWindow.getDecorView();
1041 return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
1042 }
1043
1044 private void applySystemUiVisibilityFlags(int flags, int mask) {
1045 View v = mWindow == null ? null : mWindow.getDecorView();
1046 if (v != null) {
1047 v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
1048 }
1049 }
1050
1051 private int applyFlags(int oldFlags, int flags, int mask) {
1052 return (oldFlags&~mask) | (flags&mask);
1053 }
1054
Daniel Sandler2d784902012-10-03 23:04:50 -04001055 @Override
John Spurlock66127272014-06-28 11:27:17 -04001056 protected void dump(final FileDescriptor fd, PrintWriter pw, final String[] args) {
Jeff Brown26875502014-01-30 21:47:47 -08001057 DumpUtils.dumpAsync(mHandler, new Dump() {
1058 @Override
Dianne Hackbornae6688b2015-02-11 17:02:41 -08001059 public void dump(PrintWriter pw, String prefix) {
John Spurlock66127272014-06-28 11:27:17 -04001060 dumpOnHandler(fd, pw, args);
Jeff Brown26875502014-01-30 21:47:47 -08001061 }
Dianne Hackbornae6688b2015-02-11 17:02:41 -08001062 }, pw, "", 1000);
Daniel Sandler2d784902012-10-03 23:04:50 -04001063 }
1064
John Spurlock66127272014-06-28 11:27:17 -04001065 /** @hide */
1066 protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
1067 pw.print(TAG + ": ");
1068 if (mWindowToken == null) {
1069 pw.println("stopped");
1070 } else {
1071 pw.println("running (token=" + mWindowToken + ")");
1072 }
1073 pw.println(" window: " + mWindow);
1074 pw.print(" flags:");
1075 if (isInteractive()) pw.print(" interactive");
1076 if (isLowProfile()) pw.print(" lowprofile");
1077 if (isFullscreen()) pw.print(" fullscreen");
1078 if (isScreenBright()) pw.print(" bright");
1079 if (isWindowless()) pw.print(" windowless");
1080 if (isDozing()) pw.print(" dozing");
Jeff Brown970d4132014-07-19 11:33:47 -07001081 else if (canDoze()) pw.print(" candoze");
John Spurlock66127272014-06-28 11:27:17 -04001082 pw.println();
Jeff Brown970d4132014-07-19 11:33:47 -07001083 if (canDoze()) {
Jeff Brown970d4132014-07-19 11:33:47 -07001084 pw.println(" doze screen state: " + Display.stateToString(mDozeScreenState));
1085 pw.println(" doze screen brightness: " + mDozeScreenBrightness);
1086 }
1087 }
1088
1089 private static int clampAbsoluteBrightness(int value) {
1090 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
John Spurlock66127272014-06-28 11:27:17 -04001091 }
1092
Jeff Brown26875502014-01-30 21:47:47 -08001093 private final class DreamServiceWrapper extends IDreamService.Stub {
1094 @Override
1095 public void attach(final IBinder windowToken, final boolean canDoze) {
Daniel Sandler2d784902012-10-03 23:04:50 -04001096 mHandler.post(new Runnable() {
1097 @Override
1098 public void run() {
Jeff Brown26875502014-01-30 21:47:47 -08001099 DreamService.this.attach(windowToken, canDoze);
Daniel Sandler2d784902012-10-03 23:04:50 -04001100 }
1101 });
1102 }
Jeff Brown26875502014-01-30 21:47:47 -08001103
1104 @Override
Daniel Sandler2d784902012-10-03 23:04:50 -04001105 public void detach() {
1106 mHandler.post(new Runnable() {
1107 @Override
1108 public void run() {
1109 DreamService.this.detach();
1110 }
1111 });
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001112 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001113
Jeff Brownf6d46682014-07-17 22:44:20 -07001114 @Override
1115 public void wakeUp() {
1116 mHandler.post(new Runnable() {
1117 @Override
1118 public void run() {
1119 DreamService.this.wakeUp(true /*fromSystem*/);
1120 }
1121 });
1122 }
1123 }
Dianne Hackbornbe87e2f2012-09-28 16:31:34 -07001124}