summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2014-07-17 22:44:20 -0700
committerJeff Brown <jeffbrown@google.com>2014-07-18 21:56:08 -0700
commitf6d466895b74d620d646abbec1c8911f3a0ce0bb (patch)
tree1411bc110ac23d4baa62f44d73fa94681b8c258b /core
parent5dc219142a756d57355b511c8f8ab913c01710da (diff)
downloadframeworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.zip
frameworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.tar.gz
frameworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.tar.bz2
Allow dreams to wake up gently.
This change adds a new DreamService.wakeUp() method to allow a dream to wake itself up gently and perform a transition before finally finishing. The power manager will ask a dream to wake up gently in most cases but may force it to happen immediately when necessary. If the dream takes too long to finish itself then the dream controller will douse it with water summarily after 5 seconds. Change-Id: Ib0564c5650cd5a454e1acc5aa91fe46995eecfa7
Diffstat (limited to 'core')
-rw-r--r--core/java/android/service/dreams/DreamManagerInternal.java8
-rw-r--r--core/java/android/service/dreams/DreamService.java145
-rw-r--r--core/java/android/service/dreams/IDreamManager.aidl2
-rw-r--r--core/java/android/service/dreams/IDreamService.aidl1
4 files changed, 106 insertions, 50 deletions
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index 9f7ddba..ff7cef9 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -24,13 +24,19 @@ package android.service.dreams;
public abstract class DreamManagerInternal {
/**
* Called by the power manager to start a dream.
+ *
+ * @param doze If true, starts the doze dream component if one has been configured,
+ * otherwise starts the user-specified dream.
*/
public abstract void startDream(boolean doze);
/**
* Called by the power manager to stop a dream.
+ *
+ * @param immediate If true, ends the dream summarily, otherwise gives it some time
+ * to perform a proper exit transition.
*/
- public abstract void stopDream();
+ public abstract void stopDream(boolean immediate);
/**
* Called by the power manager to determine whether a dream is running.
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 1e9ce05..5fa542a 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -171,6 +171,7 @@ public class DreamService extends Service implements Window.Callback {
private boolean mFullscreen;
private boolean mScreenBright = true;
private boolean mStarted;
+ private boolean mWaking;
private boolean mFinished;
private boolean mCanDoze;
private boolean mDozing;
@@ -196,12 +197,12 @@ public class DreamService extends Service implements Window.Callback {
public boolean dispatchKeyEvent(KeyEvent event) {
// TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
if (!mInteractive) {
- if (mDebug) Slog.v(TAG, "Finishing on keyEvent");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on keyEvent");
+ wakeUp();
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- if (mDebug) Slog.v(TAG, "Finishing on back key");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on back key");
+ wakeUp();
return true;
}
return mWindow.superDispatchKeyEvent(event);
@@ -211,8 +212,8 @@ public class DreamService extends Service implements Window.Callback {
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
if (!mInteractive) {
- if (mDebug) Slog.v(TAG, "Finishing on keyShortcutEvent");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on keyShortcutEvent");
+ wakeUp();
return true;
}
return mWindow.superDispatchKeyShortcutEvent(event);
@@ -224,8 +225,8 @@ public class DreamService extends Service implements Window.Callback {
// TODO: create more flexible version of mInteractive that allows clicks
// but finish()es on any other kind of activity
if (!mInteractive) {
- if (mDebug) Slog.v(TAG, "Finishing on touchEvent");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on touchEvent");
+ wakeUp();
return true;
}
return mWindow.superDispatchTouchEvent(event);
@@ -235,8 +236,8 @@ public class DreamService extends Service implements Window.Callback {
@Override
public boolean dispatchTrackballEvent(MotionEvent event) {
if (!mInteractive) {
- if (mDebug) Slog.v(TAG, "Finishing on trackballEvent");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on trackballEvent");
+ wakeUp();
return true;
}
return mWindow.superDispatchTrackballEvent(event);
@@ -246,8 +247,8 @@ public class DreamService extends Service implements Window.Callback {
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event) {
if (!mInteractive) {
- if (mDebug) Slog.v(TAG, "Finishing on genericMotionEvent");
- safelyFinish();
+ if (mDebug) Slog.v(TAG, "Waking up on genericMotionEvent");
+ wakeUp();
return true;
}
return mWindow.superDispatchGenericMotionEvent(event);
@@ -690,6 +691,22 @@ public class DreamService extends Service implements Window.Callback {
// hook for subclasses
}
+ /**
+ * Called when the dream is being asked to stop itself and wake.
+ * <p>
+ * The default implementation simply calls {@link #finish} which ends the dream
+ * immediately. Subclasses may override this function to perform a smooth exit
+ * transition then call {@link #finish} afterwards.
+ * </p><p>
+ * Note that the dream will only be given a short period of time (currently about
+ * five seconds) to wake up. If the dream does not finish itself in a timely manner
+ * then the system will forcibly finish it once the time allowance is up.
+ * </p>
+ */
+ public void onWakeUp() {
+ finish();
+ }
+
/** {@inheritDoc} */
@Override
public final IBinder onBind(Intent intent) {
@@ -705,8 +722,62 @@ public class DreamService extends Service implements Window.Callback {
* </p>
*/
public final void finish() {
- if (mDebug) Slog.v(TAG, "finish()");
- finishInternal();
+ if (mDebug) Slog.v(TAG, "finish(): mFinished=" + mFinished);
+
+ if (!mFinished) {
+ mFinished = true;
+
+ if (mWindowToken == null) {
+ Slog.w(TAG, "Finish was called before the dream was attached.");
+ } else {
+ try {
+ mSandman.finishSelf(mWindowToken, true /*immediate*/);
+ } catch (RemoteException ex) {
+ // system server died
+ }
+ }
+
+ stopSelf(); // if launched via any other means
+ }
+ }
+
+ /**
+ * Wakes the dream up gently.
+ * <p>
+ * Calls {@link #onWakeUp} to give the dream a chance to perform an exit transition.
+ * When the transition is over, the dream should call {@link #finish}.
+ * </p>
+ */
+ public final void wakeUp() {
+ wakeUp(false);
+ }
+
+ private void wakeUp(boolean fromSystem) {
+ if (mDebug) Slog.v(TAG, "wakeUp(): fromSystem=" + fromSystem
+ + ", mWaking=" + mWaking + ", mFinished=" + mFinished);
+
+ if (!mWaking && !mFinished) {
+ mWaking = true;
+
+ // As a minor optimization, invoke the callback first in case it simply
+ // calls finish() immediately so there wouldn't be much point in telling
+ // the system that we are finishing the dream gently.
+ onWakeUp();
+
+ // Now tell the system we are waking gently, unless we already told
+ // it we were finishing immediately.
+ if (!fromSystem && !mFinished) {
+ if (mWindowToken == null) {
+ Slog.w(TAG, "WakeUp was called before the dream was attached.");
+ } else {
+ try {
+ mSandman.finishSelf(mWindowToken, false /*immediate*/);
+ } catch (RemoteException ex) {
+ // system server died
+ }
+ }
+ }
+ }
}
/** {@inheritDoc} */
@@ -763,10 +834,10 @@ public class DreamService extends Service implements Window.Callback {
Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
return;
}
- if (mFinished) {
+ if (mFinished || mWaking) {
Slog.w(TAG, "attach() called after dream already finished");
try {
- mSandman.finishSelf(windowToken);
+ mSandman.finishSelf(windowToken, true /*immediate*/);
} catch (RemoteException ex) {
// system server died
}
@@ -837,37 +908,6 @@ public class DreamService extends Service implements Window.Callback {
});
}
- private void safelyFinish() {
- if (mDebug) Slog.v(TAG, "safelyFinish()");
-
- finish();
-
- if (!mFinished) {
- Slog.w(TAG, "Bad dream, did not call super.finish()");
- finishInternal();
- }
- }
-
- private void finishInternal() {
- if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
-
- if (!mFinished) {
- mFinished = true;
-
- if (mWindowToken == null) {
- Slog.w(TAG, "Finish was called before the dream was attached.");
- } else {
- try {
- mSandman.finishSelf(mWindowToken);
- } catch (RemoteException ex) {
- // system server died
- }
- }
-
- stopSelf(); // if launched via any other means
- }
- }
-
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
}
@@ -946,6 +986,15 @@ public class DreamService extends Service implements Window.Callback {
}
});
}
- }
+ @Override
+ public void wakeUp() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ DreamService.this.wakeUp(true /*fromSystem*/);
+ }
+ });
+ }
+ }
}
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 2718e31..9608a4d 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -31,7 +31,7 @@ interface IDreamManager {
ComponentName getDefaultDreamComponent();
void testDream(in ComponentName componentName);
boolean isDreaming();
- void finishSelf(in IBinder token);
+ void finishSelf(in IBinder token, boolean immediate);
void startDozing(in IBinder token);
void stopDozing(in IBinder token);
IDozeHardware getDozeHardware(in IBinder token);
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index bd58f1d..9bb1804 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -22,4 +22,5 @@ package android.service.dreams;
oneway interface IDreamService {
void attach(IBinder windowToken, boolean canDoze);
void detach();
+ void wakeUp();
}