Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ LOCAL_SRC_FILES += \ core/java/android/print/IWriteResultCallback.aidl \ core/java/android/printservice/IPrintService.aidl \ core/java/android/printservice/IPrintServiceClient.aidl \ core/java/android/service/dreams/IDozeHardware.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ Loading core/java/android/os/PowerManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,18 @@ public final class PowerManager { */ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020; /** * Wake lock level: Put the screen in a low power state and allow the CPU to suspend * if no other wake locks are held. * <p> * This is used by the dream manager to implement doze mode. It currently * has no effect unless the power manager is in the dozing state. * </p> * * {@hide} */ public static final int DOZE_WAKE_LOCK = 0x00000040; /** * Mask for the wake lock level component of a combined wake lock level and flags integer. * Loading Loading @@ -437,6 +449,7 @@ public final class PowerManager { case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: case PROXIMITY_SCREEN_OFF_WAKE_LOCK: case DOZE_WAKE_LOCK: break; default: throw new IllegalArgumentException("Must specify a valid wake lock level."); Loading core/java/android/service/dreams/DozeHardware.java 0 → 100644 +77 −0 Original line number Diff line number Diff line /** * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; import android.os.RemoteException; import android.util.Log; /** * Provides access to low-level hardware features that a dream may use to provide * a richer user experience while dozing. * <p> * This class contains functions that should be called by the dream to configure * hardware before starting to doze and allowing the application processor to suspend. * For example, the dream may provide the hardware with enough information to render * some content on its own without any further assistance from the application processor. * </p><p> * This object is obtained by calling {@link DreamService#getDozeHardware()}. * </p> * * @hide experimental */ public final class DozeHardware { private static final String TAG = "DozeHardware"; public static final String MSG_ENABLE_MCU = "enable_mcu"; public static final byte[] VALUE_ON = "on".getBytes(); public static final byte[] VALUE_OFF = "off".getBytes(); private final IDozeHardware mHardware; DozeHardware(IDozeHardware hardware) { mHardware = hardware; } /** * Sets whether to enable the microcontroller. * * @param enable If true, enables the MCU otherwise disables it. */ public void setEnableMcu(boolean enable) { sendMessage(MSG_ENABLE_MCU, enable ? VALUE_ON : VALUE_OFF); } /** * Sends a message to the doze hardware module. * * @param msg The name of the message to send. * @param arg An optional argument data blob, may be null. * @return A result data blob, may be null. */ public byte[] sendMessage(String msg, byte[] arg) { if (msg == null) { throw new IllegalArgumentException("msg must not be null"); } try { return mHardware.sendMessage(msg, arg); } catch (RemoteException ex) { Log.e(TAG, "Failed to send message to doze hardware module.", ex); return null; } } } core/java/android/service/dreams/DreamManagerInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ public abstract class DreamManagerInternal { /** * Called by the power manager to start a dream. */ public abstract void startDream(); public abstract void startDream(boolean doze); /** * Called by the power manager to stop a dream. Loading core/java/android/service/dreams/DreamService.java +209 −85 Original line number Diff line number Diff line Loading @@ -20,12 +20,14 @@ import java.io.PrintWriter; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.AlarmManager; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; Loading @@ -42,6 +44,8 @@ import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import com.android.internal.policy.PolicyManager; import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils.Dump; /** * Extend this class to implement a custom dream (available to the user as a "Daydream"). Loading Loading @@ -145,19 +149,26 @@ public class DreamService extends Service implements Window.Callback { */ public static final String DREAM_META_DATA = "android.service.dream"; private final IDreamManager mSandman; private final Handler mHandler = new Handler(); private IBinder mWindowToken; private Window mWindow; private WindowManager mWindowManager; private IDreamManager mSandman; private boolean mInteractive = false; private boolean mLowProfile = true; private boolean mFullscreen = false; private boolean mScreenBright = true; private boolean mFinished; private boolean mCanDoze; private boolean mDozing; private DozeHardware mDozeHardware; private boolean mDebug = false; public DreamService() { mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); } /** * @hide */ Loading Loading @@ -444,10 +455,12 @@ public class DreamService extends Service implements Window.Callback { * correct interactions with it (seeing when it is cleared etc). */ public void setLowProfile(boolean lowProfile) { if (mLowProfile != lowProfile) { mLowProfile = lowProfile; int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag); } } /** * Returns whether or not this dream is in low profile mode. Defaults to true. Loading @@ -467,10 +480,12 @@ public class DreamService extends Service implements Window.Callback { * will be cleared. */ public void setFullscreen(boolean fullscreen) { if (mFullscreen != fullscreen) { mFullscreen = fullscreen; int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; applyWindowFlags(mFullscreen ? flag : 0, flag); } } /** * Returns whether or not this dream is in fullscreen mode. Defaults to false. Loading @@ -487,14 +502,16 @@ public class DreamService extends Service implements Window.Callback { * @param screenBright True to keep the screen bright while dreaming. */ public void setScreenBright(boolean screenBright) { if (mScreenBright != screenBright) { mScreenBright = screenBright; int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; applyWindowFlags(mScreenBright ? flag : 0, flag); } } /** * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false, * allowing the screen to dim if necessary. * Returns whether or not this dream keeps the screen bright while dreaming. * Defaults to false, allowing the screen to dim if necessary. * * @see #setScreenBright(boolean) */ Loading @@ -502,6 +519,119 @@ public class DreamService extends Service implements Window.Callback { return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright); } /** * Returns true if this dream is allowed to doze. * <p> * The value returned by this method is only meaningful when the dream has started. * </p> * * @return True if this dream can doze. * @see #startDozing * @hide experimental */ public boolean canDoze() { return mCanDoze; } /** * Starts dozing, entering a deep dreamy sleep. * <p> * Dozing enables the system to conserve power while the user is not actively interacting * with the device. While dozing, the display will remain on in a low-power state * and will continue to show its previous contents but the application processor and * other system components will be allowed to suspend when possible. * </p><p> * While the application processor is suspended, the dream may stop executing code * for long periods of time. Prior to being suspended, the dream may schedule periodic * wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}. * The dream may also keep the CPU awake by acquiring a * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary. * Note that since the purpose of doze mode is to conserve power (especially when * running on battery), the dream should not wake the CPU very often or keep it * awake for very long. * </p><p> * It is a good idea to call this method some time after the dream's entry animation * has completed and the dream is ready to doze. It is important to completely * finish all of the work needed before dozing since the application processor may * be suspended at any moment once this method is called unless other wake locks * are being held. * </p><p> * Call {@link #stopDozing} or {@link #finish} to stop dozing. * </p> * * @see #stopDozing * @hide experimental */ public void startDozing() { if (mCanDoze && !mDozing) { mDozing = true; try { mSandman.startDozing(mWindowToken); } catch (RemoteException ex) { // system server died } } } /** * Stops dozing, returns to active dreaming. * <p> * This method reverses the effect of {@link #startDozing}. From this moment onward, * the application processor will be kept awake as long as the dream is running * or until the dream starts dozing again. * </p> * * @see #startDozing * @hide experimental */ public void stopDozing() { if (mDozing) { mDozing = false; try { mSandman.stopDozing(mWindowToken); } catch (RemoteException ex) { // system server died } } } /** * Returns true if the dream will allow the system to enter a low-power state while * it is running without actually turning off the screen. Defaults to false, * keeping the application processor awake while the dream is running. * * @return True if the dream is dozing. * * @see #setDozing(boolean) * @hide experimental */ public boolean isDozing() { return mDozing; } /** * Gets an object that may be used to access low-level hardware features that a * dream may use to provide a richer user experience while dozing. * * @return An instance of {@link DozeHardware} or null if this device does not offer * hardware support for dozing. * * @hide experimental */ public DozeHardware getDozeHardware() { if (mCanDoze && mDozeHardware == null) { try { IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken); if (hardware != null) { mDozeHardware = new DozeHardware(hardware); } } catch (RemoteException ex) { // system server died } } return mDozeHardware; } /** * Called when this Dream is constructed. */ Loading Loading @@ -536,7 +666,11 @@ public class DreamService extends Service implements Window.Callback { } /** * Stops the dream, detaches from the window, and wakes up. * Stops the dream and detaches from the window. * <p> * When the dream ends, the system will be allowed to go to sleep fully unless there * is a reason for it to be awake such as recent user activity or wake locks being held. * </p> */ public final void finish() { if (mDebug) Slog.v(TAG, "finish()"); Loading @@ -557,10 +691,6 @@ public class DreamService extends Service implements Window.Callback { // end public api private void loadSandman() { mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); } /** * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed. * Loading @@ -572,23 +702,16 @@ public class DreamService extends Service implements Window.Callback { return; } try { if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()"); onDreamingStopped(); } catch (Throwable t) { Slog.w(TAG, "Crashed in onDreamingStopped()", t); // we were going to stop anyway } if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); try { // force our window to be removed synchronously mWindowManager.removeViewImmediate(mWindow.getDecorView()); // the following will print a log message if it finds any other leaked windows WindowManagerGlobal.getInstance().closeAll(mWindowToken, this.getClass().getName(), "Dream"); } catch (Throwable t) { Slog.w(TAG, "Crashed removing window view", t); } mWindow = null; mWindowToken = null; Loading @@ -601,23 +724,30 @@ public class DreamService extends Service implements Window.Callback { * * @param windowToken A window token that will allow a window to be created in the correct layer. */ private final void attach(IBinder windowToken) { private final void attach(IBinder windowToken, boolean canDoze) { if (mWindowToken != null) { Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken); return; } if (mFinished) { Slog.w(TAG, "attach() called after dream already finished"); try { mSandman.finishSelf(windowToken); } catch (RemoteException ex) { // system server died } return; } if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); if (mSandman == null) { loadSandman(); } mWindowToken = windowToken; mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); mWindow.setFormat(PixelFormat.OPAQUE); mCanDoze = canDoze; if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", windowToken, WindowManager.LayoutParams.TYPE_DREAM)); Loading @@ -642,40 +772,25 @@ public class DreamService extends Service implements Window.Callback { mWindowManager = mWindow.getWindowManager(); if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); try { applySystemUiVisibilityFlags( (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), View.SYSTEM_UI_FLAG_LOW_PROFILE); getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); } catch (Throwable t) { Slog.w(TAG, "Crashed adding window view", t); safelyFinish(); return; } // start it up mHandler.post(new Runnable() { @Override public void run() { try { if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); onDreamingStarted(); } catch (Throwable t) { Slog.w(TAG, "Crashed in onDreamingStarted()", t); safelyFinish(); } } }); } private void safelyFinish() { if (mDebug) Slog.v(TAG, "safelyFinish()"); try { finish(); } catch (Throwable t) { Slog.w(TAG, "Crashed in safelyFinish()", t); finishInternal(); return; } if (!mFinished) { Slog.w(TAG, "Bad dream, did not call super.finish()"); Loading @@ -685,19 +800,21 @@ public class DreamService extends Service implements Window.Callback { private void finishInternal() { if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished); if (mFinished) return; try { if (!mFinished) { mFinished = true; if (mSandman != null) { mSandman.finishSelf(mWindowToken); if (mWindowToken == null) { Slog.w(TAG, "Finish was called before the dream was attached."); } else { Slog.w(TAG, "No dream manager found"); try { mSandman.finishSelf(mWindowToken); } catch (RemoteException ex) { // system server died } } stopSelf(); // if launched via any other means } catch (Throwable t) { Slog.w(TAG, "Crashed in finishInternal()", t); stopSelf(); // if launched via any other means } } Loading Loading @@ -732,8 +849,9 @@ public class DreamService extends Service implements Window.Callback { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { super.dump(fd, pw, args); DumpUtils.dumpAsync(mHandler, new Dump() { @Override public void dump(PrintWriter pw) { pw.print(TAG + ": "); if (mWindowToken == null) { pw.println("stopped"); Loading @@ -746,18 +864,24 @@ public class DreamService extends Service implements Window.Callback { if (isLowProfile()) pw.print(" lowprofile"); if (isFullscreen()) pw.print(" fullscreen"); if (isScreenBright()) pw.print(" bright"); if (isDozing()) pw.print(" dozing"); pw.println(); } }, pw, 1000); } private class DreamServiceWrapper extends IDreamService.Stub { public void attach(final IBinder windowToken) { private final class DreamServiceWrapper extends IDreamService.Stub { @Override public void attach(final IBinder windowToken, final boolean canDoze) { mHandler.post(new Runnable() { @Override public void run() { DreamService.this.attach(windowToken); DreamService.this.attach(windowToken, canDoze); } }); } @Override public void detach() { mHandler.post(new Runnable() { @Override Loading Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ LOCAL_SRC_FILES += \ core/java/android/print/IWriteResultCallback.aidl \ core/java/android/printservice/IPrintService.aidl \ core/java/android/printservice/IPrintServiceClient.aidl \ core/java/android/service/dreams/IDozeHardware.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ Loading
core/java/android/os/PowerManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,18 @@ public final class PowerManager { */ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020; /** * Wake lock level: Put the screen in a low power state and allow the CPU to suspend * if no other wake locks are held. * <p> * This is used by the dream manager to implement doze mode. It currently * has no effect unless the power manager is in the dozing state. * </p> * * {@hide} */ public static final int DOZE_WAKE_LOCK = 0x00000040; /** * Mask for the wake lock level component of a combined wake lock level and flags integer. * Loading Loading @@ -437,6 +449,7 @@ public final class PowerManager { case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: case PROXIMITY_SCREEN_OFF_WAKE_LOCK: case DOZE_WAKE_LOCK: break; default: throw new IllegalArgumentException("Must specify a valid wake lock level."); Loading
core/java/android/service/dreams/DozeHardware.java 0 → 100644 +77 −0 Original line number Diff line number Diff line /** * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; import android.os.RemoteException; import android.util.Log; /** * Provides access to low-level hardware features that a dream may use to provide * a richer user experience while dozing. * <p> * This class contains functions that should be called by the dream to configure * hardware before starting to doze and allowing the application processor to suspend. * For example, the dream may provide the hardware with enough information to render * some content on its own without any further assistance from the application processor. * </p><p> * This object is obtained by calling {@link DreamService#getDozeHardware()}. * </p> * * @hide experimental */ public final class DozeHardware { private static final String TAG = "DozeHardware"; public static final String MSG_ENABLE_MCU = "enable_mcu"; public static final byte[] VALUE_ON = "on".getBytes(); public static final byte[] VALUE_OFF = "off".getBytes(); private final IDozeHardware mHardware; DozeHardware(IDozeHardware hardware) { mHardware = hardware; } /** * Sets whether to enable the microcontroller. * * @param enable If true, enables the MCU otherwise disables it. */ public void setEnableMcu(boolean enable) { sendMessage(MSG_ENABLE_MCU, enable ? VALUE_ON : VALUE_OFF); } /** * Sends a message to the doze hardware module. * * @param msg The name of the message to send. * @param arg An optional argument data blob, may be null. * @return A result data blob, may be null. */ public byte[] sendMessage(String msg, byte[] arg) { if (msg == null) { throw new IllegalArgumentException("msg must not be null"); } try { return mHardware.sendMessage(msg, arg); } catch (RemoteException ex) { Log.e(TAG, "Failed to send message to doze hardware module.", ex); return null; } } }
core/java/android/service/dreams/DreamManagerInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ public abstract class DreamManagerInternal { /** * Called by the power manager to start a dream. */ public abstract void startDream(); public abstract void startDream(boolean doze); /** * Called by the power manager to stop a dream. Loading
core/java/android/service/dreams/DreamService.java +209 −85 Original line number Diff line number Diff line Loading @@ -20,12 +20,14 @@ import java.io.PrintWriter; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.AlarmManager; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; Loading @@ -42,6 +44,8 @@ import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import com.android.internal.policy.PolicyManager; import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils.Dump; /** * Extend this class to implement a custom dream (available to the user as a "Daydream"). Loading Loading @@ -145,19 +149,26 @@ public class DreamService extends Service implements Window.Callback { */ public static final String DREAM_META_DATA = "android.service.dream"; private final IDreamManager mSandman; private final Handler mHandler = new Handler(); private IBinder mWindowToken; private Window mWindow; private WindowManager mWindowManager; private IDreamManager mSandman; private boolean mInteractive = false; private boolean mLowProfile = true; private boolean mFullscreen = false; private boolean mScreenBright = true; private boolean mFinished; private boolean mCanDoze; private boolean mDozing; private DozeHardware mDozeHardware; private boolean mDebug = false; public DreamService() { mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); } /** * @hide */ Loading Loading @@ -444,10 +455,12 @@ public class DreamService extends Service implements Window.Callback { * correct interactions with it (seeing when it is cleared etc). */ public void setLowProfile(boolean lowProfile) { if (mLowProfile != lowProfile) { mLowProfile = lowProfile; int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE; applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag); } } /** * Returns whether or not this dream is in low profile mode. Defaults to true. Loading @@ -467,10 +480,12 @@ public class DreamService extends Service implements Window.Callback { * will be cleared. */ public void setFullscreen(boolean fullscreen) { if (mFullscreen != fullscreen) { mFullscreen = fullscreen; int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; applyWindowFlags(mFullscreen ? flag : 0, flag); } } /** * Returns whether or not this dream is in fullscreen mode. Defaults to false. Loading @@ -487,14 +502,16 @@ public class DreamService extends Service implements Window.Callback { * @param screenBright True to keep the screen bright while dreaming. */ public void setScreenBright(boolean screenBright) { if (mScreenBright != screenBright) { mScreenBright = screenBright; int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; applyWindowFlags(mScreenBright ? flag : 0, flag); } } /** * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false, * allowing the screen to dim if necessary. * Returns whether or not this dream keeps the screen bright while dreaming. * Defaults to false, allowing the screen to dim if necessary. * * @see #setScreenBright(boolean) */ Loading @@ -502,6 +519,119 @@ public class DreamService extends Service implements Window.Callback { return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright); } /** * Returns true if this dream is allowed to doze. * <p> * The value returned by this method is only meaningful when the dream has started. * </p> * * @return True if this dream can doze. * @see #startDozing * @hide experimental */ public boolean canDoze() { return mCanDoze; } /** * Starts dozing, entering a deep dreamy sleep. * <p> * Dozing enables the system to conserve power while the user is not actively interacting * with the device. While dozing, the display will remain on in a low-power state * and will continue to show its previous contents but the application processor and * other system components will be allowed to suspend when possible. * </p><p> * While the application processor is suspended, the dream may stop executing code * for long periods of time. Prior to being suspended, the dream may schedule periodic * wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}. * The dream may also keep the CPU awake by acquiring a * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary. * Note that since the purpose of doze mode is to conserve power (especially when * running on battery), the dream should not wake the CPU very often or keep it * awake for very long. * </p><p> * It is a good idea to call this method some time after the dream's entry animation * has completed and the dream is ready to doze. It is important to completely * finish all of the work needed before dozing since the application processor may * be suspended at any moment once this method is called unless other wake locks * are being held. * </p><p> * Call {@link #stopDozing} or {@link #finish} to stop dozing. * </p> * * @see #stopDozing * @hide experimental */ public void startDozing() { if (mCanDoze && !mDozing) { mDozing = true; try { mSandman.startDozing(mWindowToken); } catch (RemoteException ex) { // system server died } } } /** * Stops dozing, returns to active dreaming. * <p> * This method reverses the effect of {@link #startDozing}. From this moment onward, * the application processor will be kept awake as long as the dream is running * or until the dream starts dozing again. * </p> * * @see #startDozing * @hide experimental */ public void stopDozing() { if (mDozing) { mDozing = false; try { mSandman.stopDozing(mWindowToken); } catch (RemoteException ex) { // system server died } } } /** * Returns true if the dream will allow the system to enter a low-power state while * it is running without actually turning off the screen. Defaults to false, * keeping the application processor awake while the dream is running. * * @return True if the dream is dozing. * * @see #setDozing(boolean) * @hide experimental */ public boolean isDozing() { return mDozing; } /** * Gets an object that may be used to access low-level hardware features that a * dream may use to provide a richer user experience while dozing. * * @return An instance of {@link DozeHardware} or null if this device does not offer * hardware support for dozing. * * @hide experimental */ public DozeHardware getDozeHardware() { if (mCanDoze && mDozeHardware == null) { try { IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken); if (hardware != null) { mDozeHardware = new DozeHardware(hardware); } } catch (RemoteException ex) { // system server died } } return mDozeHardware; } /** * Called when this Dream is constructed. */ Loading Loading @@ -536,7 +666,11 @@ public class DreamService extends Service implements Window.Callback { } /** * Stops the dream, detaches from the window, and wakes up. * Stops the dream and detaches from the window. * <p> * When the dream ends, the system will be allowed to go to sleep fully unless there * is a reason for it to be awake such as recent user activity or wake locks being held. * </p> */ public final void finish() { if (mDebug) Slog.v(TAG, "finish()"); Loading @@ -557,10 +691,6 @@ public class DreamService extends Service implements Window.Callback { // end public api private void loadSandman() { mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); } /** * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed. * Loading @@ -572,23 +702,16 @@ public class DreamService extends Service implements Window.Callback { return; } try { if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()"); onDreamingStopped(); } catch (Throwable t) { Slog.w(TAG, "Crashed in onDreamingStopped()", t); // we were going to stop anyway } if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); try { // force our window to be removed synchronously mWindowManager.removeViewImmediate(mWindow.getDecorView()); // the following will print a log message if it finds any other leaked windows WindowManagerGlobal.getInstance().closeAll(mWindowToken, this.getClass().getName(), "Dream"); } catch (Throwable t) { Slog.w(TAG, "Crashed removing window view", t); } mWindow = null; mWindowToken = null; Loading @@ -601,23 +724,30 @@ public class DreamService extends Service implements Window.Callback { * * @param windowToken A window token that will allow a window to be created in the correct layer. */ private final void attach(IBinder windowToken) { private final void attach(IBinder windowToken, boolean canDoze) { if (mWindowToken != null) { Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken); return; } if (mFinished) { Slog.w(TAG, "attach() called after dream already finished"); try { mSandman.finishSelf(windowToken); } catch (RemoteException ex) { // system server died } return; } if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); if (mSandman == null) { loadSandman(); } mWindowToken = windowToken; mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); mWindow.setFormat(PixelFormat.OPAQUE); mCanDoze = canDoze; if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", windowToken, WindowManager.LayoutParams.TYPE_DREAM)); Loading @@ -642,40 +772,25 @@ public class DreamService extends Service implements Window.Callback { mWindowManager = mWindow.getWindowManager(); if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); try { applySystemUiVisibilityFlags( (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), View.SYSTEM_UI_FLAG_LOW_PROFILE); getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); } catch (Throwable t) { Slog.w(TAG, "Crashed adding window view", t); safelyFinish(); return; } // start it up mHandler.post(new Runnable() { @Override public void run() { try { if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); onDreamingStarted(); } catch (Throwable t) { Slog.w(TAG, "Crashed in onDreamingStarted()", t); safelyFinish(); } } }); } private void safelyFinish() { if (mDebug) Slog.v(TAG, "safelyFinish()"); try { finish(); } catch (Throwable t) { Slog.w(TAG, "Crashed in safelyFinish()", t); finishInternal(); return; } if (!mFinished) { Slog.w(TAG, "Bad dream, did not call super.finish()"); Loading @@ -685,19 +800,21 @@ public class DreamService extends Service implements Window.Callback { private void finishInternal() { if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished); if (mFinished) return; try { if (!mFinished) { mFinished = true; if (mSandman != null) { mSandman.finishSelf(mWindowToken); if (mWindowToken == null) { Slog.w(TAG, "Finish was called before the dream was attached."); } else { Slog.w(TAG, "No dream manager found"); try { mSandman.finishSelf(mWindowToken); } catch (RemoteException ex) { // system server died } } stopSelf(); // if launched via any other means } catch (Throwable t) { Slog.w(TAG, "Crashed in finishInternal()", t); stopSelf(); // if launched via any other means } } Loading Loading @@ -732,8 +849,9 @@ public class DreamService extends Service implements Window.Callback { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { super.dump(fd, pw, args); DumpUtils.dumpAsync(mHandler, new Dump() { @Override public void dump(PrintWriter pw) { pw.print(TAG + ": "); if (mWindowToken == null) { pw.println("stopped"); Loading @@ -746,18 +864,24 @@ public class DreamService extends Service implements Window.Callback { if (isLowProfile()) pw.print(" lowprofile"); if (isFullscreen()) pw.print(" fullscreen"); if (isScreenBright()) pw.print(" bright"); if (isDozing()) pw.print(" dozing"); pw.println(); } }, pw, 1000); } private class DreamServiceWrapper extends IDreamService.Stub { public void attach(final IBinder windowToken) { private final class DreamServiceWrapper extends IDreamService.Stub { @Override public void attach(final IBinder windowToken, final boolean canDoze) { mHandler.post(new Runnable() { @Override public void run() { DreamService.this.attach(windowToken); DreamService.this.attach(windowToken, canDoze); } }); } @Override public void detach() { mHandler.post(new Runnable() { @Override Loading