From bc632a28e4fba4a659baf39b9fd3d06d10cfda97 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 31 Jul 2012 08:28:12 -0400 Subject: [PATCH] Re-enable dreams: frameworks/base Enable feature in config. Expose Dream in public api for unbundled apps. Unhide package. Add isDreaming() method to service. Re-arrange the Dream api a bit. (use onStart as hook for subclasses). Coordinate properly with power manager. Replace old dock mode (don't fire old intent). Change-Id: I1318d20cc1613e5d862f2913f2fcdc9719302cf7 Bug: 6921930 --- api/current.txt | 44 +++++++++++++++ core/java/android/service/dreams/Dream.java | 53 ++++++++++--------- .../service/dreams/DreamManagerService.java | 20 ++++--- .../android/service/dreams/IDreamManager.aidl | 1 + core/res/res/values/config.xml | 2 +- .../policy/impl/PhoneWindowManager.java | 6 ++- .../java/com/android/server/DockObserver.java | 27 +++++++++- .../server/power/PowerManagerService.java | 14 ++++- 8 files changed, 130 insertions(+), 37 deletions(-) diff --git a/api/current.txt b/api/current.txt index 4b433185811cf..cc67e89c204f1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -19927,6 +19927,50 @@ package android.security { } +package android.service.dreams { + + public class Dream extends android.app.Service implements android.view.Window.Callback { + ctor public Dream(); + method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams); + method public boolean dispatchGenericMotionEvent(android.view.MotionEvent); + method public boolean dispatchKeyEvent(android.view.KeyEvent); + method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent); + method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); + method public boolean dispatchTouchEvent(android.view.MotionEvent); + method public boolean dispatchTrackballEvent(android.view.MotionEvent); + method public android.view.View findViewById(int); + method public void finish(); + method public android.view.Window getWindow(); + method public android.view.WindowManager getWindowManager(); + method public boolean isInteractive(); + method protected void lightsOut(); + method public void onActionModeFinished(android.view.ActionMode); + method public void onActionModeStarted(android.view.ActionMode); + method public void onAttachedToWindow(); + method public final android.os.IBinder onBind(android.content.Intent); + method public void onContentChanged(); + method public boolean onCreatePanelMenu(int, android.view.Menu); + method public android.view.View onCreatePanelView(int); + method public void onDetachedFromWindow(); + method public boolean onMenuItemSelected(int, android.view.MenuItem); + method public boolean onMenuOpened(int, android.view.Menu); + method public void onPanelClosed(int, android.view.Menu); + method public boolean onPreparePanel(int, android.view.View, android.view.Menu); + method public boolean onSearchRequested(); + method public void onStart(); + method public final int onStartCommand(android.content.Intent, int, int); + method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); + method public void onWindowFocusChanged(boolean); + method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback); + method public void setContentView(int); + method public void setContentView(android.view.View); + method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams); + method public void setInteractive(boolean); + field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.Dream"; + } + +} + package android.service.textservice { public abstract class SpellCheckerService extends android.app.Service { diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java index 83464c936d818..9a903e468a724 100644 --- a/core/java/android/service/dreams/Dream.java +++ b/core/java/android/service/dreams/Dream.java @@ -1,26 +1,31 @@ /** - * + * Copyright (C) 2012 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 com.android.internal.policy.PolicyManager; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; -import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.graphics.drawable.ColorDrawable; -import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; -import android.view.IWindowManager; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; @@ -28,14 +33,14 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; -import android.view.WindowManager; -import android.view.WindowManagerImpl; + +import com.android.internal.policy.PolicyManager; /** - * @hide - * + * Extend this class to implement a custom screensaver. */ public class Dream extends Service implements Window.Callback { private final static boolean DEBUG = true; @@ -61,7 +66,7 @@ public class Dream extends Service implements Window.Callback { final Handler mHandler = new Handler(); boolean mFinished = false; - + // begin Window.Callback methods @Override public boolean dispatchKeyEvent(KeyEvent event) { @@ -210,19 +215,14 @@ public class Dream extends Service implements Window.Callback { mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); } - + /** - * Called when this Dream is started. Place your initialization here. - * - * Subclasses must call through to the superclass implementation. - * - * XXX(dsandler) Might want to make this final and have a different method for clients to override + * Called when this Dream is started. */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - return super.onStartCommand(intent, flags, startId); + public void onStart() { + // hook for subclasses } - + /** * Inflate a layout resource and set it to be the content view for this Dream. * Behaves similarly to {@link android.app.Activity#setContentView(int)}. @@ -351,9 +351,12 @@ public class Dream extends Service implements Window.Callback { @Override public void run() { if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId()); - + getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); - }}); + + // start it up + onStart(); + }}); } /** diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java index 4a14cedbf9b39..d6b38a1cf080b 100644 --- a/core/java/android/service/dreams/DreamManagerService.java +++ b/core/java/android/service/dreams/DreamManagerService.java @@ -114,11 +114,19 @@ public class DreamManagerService if (DEBUG) Slog.v(TAG, "awaken()"); synchronized (mLock) { if (mCurrentDream != null) { + if (DEBUG) Slog.v(TAG, "disconnecting: " + mCurrentDreamComponent + " service: " + mCurrentDream); mContext.unbindService(this); + mCurrentDream = null; + mCurrentDreamToken = null; } } } + // IDreamManager method + public boolean isDreaming() { + return mCurrentDream != null; + } + public void bindDreamComponentL(ComponentName componentName, boolean test) { if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); @@ -129,11 +137,7 @@ public class DreamManagerService Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ) .putExtra("android.dreams.TEST", test); - - if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { - Slog.w(TAG, "unable to bind service: " + componentName); - return; - } + mCurrentDreamComponent = componentName; mCurrentDreamToken = new Binder(); try { @@ -145,6 +149,9 @@ public class DreamManagerService Slog.w(TAG, "Unable to add window token. Proceed at your own risk."); } + if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { + Slog.w(TAG, "unable to bind service: " + componentName); + } } @Override @@ -163,8 +170,7 @@ public class DreamManagerService @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream); - mCurrentDream = null; - mCurrentDreamToken = null; + // Only happens in exceptional circumstances } @Override diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 722501391f0da..b64dd8f966ecf 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -27,4 +27,5 @@ interface IDreamManager { void setDreamComponent(in ComponentName componentName); ComponentName getDreamComponent(); void testDream(in ComponentName componentName); + boolean isDreaming(); } \ No newline at end of file diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 39129e5dfe418..b752471069b74 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -852,7 +852,7 @@ - false + true com.google.android.deskclock/com.android.deskclock.Screensaver diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 97b4cb5a81885..215f5978fbed5 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1132,7 +1132,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.bool.config_enableDreams); mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver, - Settings.Secure.SCREENSAVER_ENABLED, 1); + Settings.Secure.SCREENSAVER_ENABLED, 0); if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) { mScreenSaverTimeout = Settings.Secure.getInt(resolver, @@ -4076,7 +4076,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (dm == null) return; try { - if (localLOGV) Log.v(TAG, "startScreenSaver: awakening..."); + if (!dm.isDreaming()) return; + + if (localLOGV) Log.v(TAG, "stopScreenSaver: awakening..."); dm.awaken(); } catch (RemoteException ex) { diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index e7dac72301943..8bac52c760afd 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -29,9 +29,12 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Handler; import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.UEventObserver; import android.provider.Settings; +import android.service.dreams.IDreamManager; import android.util.Log; import android.util.Slog; @@ -194,7 +197,29 @@ class DockObserver extends UEventObserver { } } - mContext.sendStickyBroadcast(intent); + IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); + if (mgr != null) { + // dreams feature enabled + boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED; + if (undocked) { + try { + if (mgr.isDreaming()) { + mgr.awaken(); + } + } catch (RemoteException e) { + Slog.w(TAG, "Unable to awaken!", e); + } + } else { + try { + mgr.dream(); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to dream!", e); + } + } + } else { + // dreams feature not enabled, send legacy intent + mContext.sendStickyBroadcast(intent); + } } break; } diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 453c7a475b0a8..cb6db3cec8289 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -424,6 +424,11 @@ public class PowerManagerService extends IPowerManager.Stub forceUserActivityLocked(); } } + + // stop the screensaver if we're now unplugged + if (mPolicy != null) { + mPolicy.stopScreenSaver(); + } } } } @@ -1826,7 +1831,7 @@ public class PowerManagerService extends IPowerManager.Stub final boolean stateChanged = mPowerState != newState; if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) { - if (mPolicy != null && mPolicy.isScreenSaverEnabled()) { + if (mPolicy != null && mPolicy.isScreenSaverEnabled() && mIsPowered) { if (DEBUG) { Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen"); } @@ -1922,6 +1927,13 @@ public class PowerManagerService extends IPowerManager.Stub } else { err = 0; } + + // stop the screensaver if user turned screen off + if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_USER) { + if (mPolicy != null) { + mPolicy.stopScreenSaver(); + } + } } } else if (stateChanged) { // Screen on/off didn't change, but lights may have.