summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2012-10-04 20:56:07 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-10-04 20:56:08 -0700
commitf5e2b2c26c37d839e6559319d311b62598c6dade (patch)
treed9447574a8a87358ca19ecb370ed04c67362aecc
parenta07b1fffbe7c43485b35ba83c9083a59ff328df1 (diff)
parent2d78490292090eeab84694330978c9ad7fad2d37 (diff)
downloadframeworks_base-f5e2b2c26c37d839e6559319d311b62598c6dade.zip
frameworks_base-f5e2b2c26c37d839e6559319d311b62598c6dade.tar.gz
frameworks_base-f5e2b2c26c37d839e6559319d311b62598c6dade.tar.bz2
Merge "DreamService API revisions." into jb-mr1-dev
-rw-r--r--api/17.txt5
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/service/dreams/Dream.java23
-rw-r--r--core/java/android/service/dreams/DreamService.java222
-rw-r--r--core/java/android/service/dreams/IDreamService.aidl1
-rw-r--r--packages/SystemUI/src/com/android/systemui/BeanBagDream.java16
-rw-r--r--services/java/com/android/server/dreams/DreamController.java11
7 files changed, 178 insertions, 105 deletions
diff --git a/api/17.txt b/api/17.txt
index 00e84db..91dc71f 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -20342,7 +20342,7 @@ package android.service.dreams {
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 final void finish();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
method public boolean isFullscreen();
@@ -20357,12 +20357,13 @@ package android.service.dreams {
method public boolean onCreatePanelMenu(int, android.view.Menu);
method public android.view.View onCreatePanelView(int);
method public void onDetachedFromWindow();
+ method public void onDreamingStarted();
+ method public void onDreamingStopped();
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 void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
diff --git a/api/current.txt b/api/current.txt
index 00e84db..91dc71f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20342,7 +20342,7 @@ package android.service.dreams {
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 final void finish();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
method public boolean isFullscreen();
@@ -20357,12 +20357,13 @@ package android.service.dreams {
method public boolean onCreatePanelMenu(int, android.view.Menu);
method public android.view.View onCreatePanelView(int);
method public void onDetachedFromWindow();
+ method public void onDreamingStarted();
+ method public void onDreamingStopped();
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 void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
deleted file mode 100644
index 4e8b05b..0000000
--- a/core/java/android/service/dreams/Dream.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * 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;
-
-/**
- * @hide
- * Temporarily needed to not break existing apps.
- */
-public class Dream extends DreamService {
-}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 03b685b..dd51764 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,6 +15,9 @@
*/
package android.service.dreams;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
@@ -39,13 +42,24 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.policy.PolicyManager;
/**
- * Extend this class to implement a custom Dream.
+ * Extend this class to implement a custom Dream (displayed to the user as a "Sleep Mode").
*
* <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
* desk dock. Dreams provide another modality for apps to express themselves, tailored for
* an exhibition/lean-back experience.</p>
*
- * <p>Dreams should be declared in the manifest as follows:</p>
+ * <p>The Dream lifecycle is as follows:</p>
+ * <ul>
+ * <li>onAttachedToWindow</li>
+ * <li>onDreamingStarted</li>
+ * <li>onDreamingStopped</li>
+ * <li>onDetachedFromWindow</li>
+ * </ul>
+ *
+ * <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but
+ * initialization and teardown should be done by overriding the hooks above.</p>
+ *
+ * <p>To be available to the system, Dreams should be declared in the manifest as follows:</p>
* <pre>
* &lt;service
* android:name=".MyDream"
@@ -74,7 +88,6 @@ import com.android.internal.policy.PolicyManager;
* </pre>
*/
public class DreamService extends Service implements Window.Callback {
- private final static boolean DEBUG = true;
private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
/**
@@ -109,17 +122,26 @@ public class DreamService extends Service implements Window.Callback {
private boolean mScreenBright = false;
private boolean mFinished;
+ private boolean mDebug = false;
+
+ /**
+ * @hide
+ */
+ public void setDebug(boolean dbg) {
+ mDebug = dbg;
+ }
+
// begin Window.Callback methods
/** {@inheritDoc} */
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on keyEvent");
+ if (mDebug) Slog.v(TAG, "Finishing on keyEvent");
safelyFinish();
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- if (DEBUG) Slog.v(TAG, "Finishing on back key");
+ if (mDebug) Slog.v(TAG, "Finishing on back key");
safelyFinish();
return true;
}
@@ -129,8 +151,8 @@ public class DreamService extends Service implements Window.Callback {
/** {@inheritDoc} */
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on keyShortcutEvent");
+ if (!mInteractive) {
+ if (mDebug) Slog.v(TAG, "Finishing on keyShortcutEvent");
safelyFinish();
return true;
}
@@ -140,10 +162,10 @@ public class DreamService extends Service implements Window.Callback {
/** {@inheritDoc} */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
- // TODO: create more flexible version of mInteractive that allows clicks
+ // TODO: create more flexible version of mInteractive that allows clicks
// but finish()es on any other kind of activity
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on touchEvent");
+ if (!mInteractive) {
+ if (mDebug) Slog.v(TAG, "Finishing on touchEvent");
safelyFinish();
return true;
}
@@ -154,7 +176,7 @@ public class DreamService extends Service implements Window.Callback {
@Override
public boolean dispatchTrackballEvent(MotionEvent event) {
if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on trackballEvent");
+ if (mDebug) Slog.v(TAG, "Finishing on trackballEvent");
safelyFinish();
return true;
}
@@ -164,8 +186,8 @@ public class DreamService extends Service implements Window.Callback {
/** {@inheritDoc} */
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event) {
- if (!mInteractive) {
- if (DEBUG) Slog.v(TAG, "Finishing on genericMotionEvent");
+ if (!mInteractive) {
+ if (mDebug) Slog.v(TAG, "Finishing on genericMotionEvent");
safelyFinish();
return true;
}
@@ -289,7 +311,7 @@ public class DreamService extends Service implements Window.Callback {
* <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
*
* @param layoutResID Resource ID to be inflated.
- *
+ *
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
@@ -314,7 +336,7 @@ public class DreamService extends Service implements Window.Callback {
/**
* Sets a view to be the content view for this Dream.
- * Behaves similarly to
+ * Behaves similarly to
* {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}.
*
* <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
@@ -437,68 +459,105 @@ public class DreamService extends Service implements Window.Callback {
}
/**
- * Called when this Dream is constructed. Place your initialization here.
- *
- * <p>Subclasses must call through to the superclass implementation.</p>
+ * Called when this Dream is constructed.
*/
@Override
public void onCreate() {
- if (DEBUG) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId());
+ if (mDebug) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId());
super.onCreate();
- loadSandman();
}
/**
- * Called when this Dream is started. The window is created and visible at this point.
+ * Called when the dream's window has been created and is visible and animation may now begin.
+ */
+ public void onDreamingStarted() {
+ if (mDebug) Slog.v(TAG, "onDreamingStarted()");
+ // hook for subclasses
+ }
+
+ /**
+ * Called when this Dream is stopped, either by external request or by calling finish(),
+ * before the window has been removed.
*/
- public void onStart() {
- if (DEBUG) Slog.v(TAG, "onStart()");
+ public void onDreamingStopped() {
+ if (mDebug) Slog.v(TAG, "onDreamingStopped()");
// hook for subclasses
}
/** {@inheritDoc} */
@Override
public final IBinder onBind(Intent intent) {
- if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+ if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
return new DreamServiceWrapper();
}
/**
* Stops the dream, detaches from the window, and wakes up.
- *
- * <p>Subclasses must call through to the superclass implementation.</p>
- *
- * <p>After this method is called, the service will be stopped.</p>
*/
- public void finish() {
- if (DEBUG) Slog.v(TAG, "finish()");
+ public final void finish() {
+ if (mDebug) Slog.v(TAG, "finish()");
finishInternal();
}
/** {@inheritDoc} */
@Override
public void onDestroy() {
- if (DEBUG) Slog.v(TAG, "onDestroy()");
+ if (mDebug) Slog.v(TAG, "onDestroy()");
super.onDestroy();
+ // hook for subclasses
+ }
+
+ // end public api
+
+ private void loadSandman() {
+ mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ }
+
+ /**
+ * Called when the Dream is about to be unbound and destroyed.
+ *
+ * Must run on mHandler.
+ */
+ private final void detach() {
+ if (mWindow == null) {
+ Slog.e(TAG, "detach() called when not attached");
+ return;
+ }
+
+ try {
+ onDreamingStopped();
+ } catch (Throwable t) {
+ Slog.w(TAG, "Crashed in onDreamingStopped()", t);
+ // we were going to stop anyway
+ }
- if (DEBUG) Slog.v(TAG, "Removing window");
+ if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
try {
mWindowManager.removeView(mWindow.getDecorView());
} catch (Throwable t) {
Slog.w(TAG, "Crashed removing window view", t);
}
- }
- // end public api
- private void loadSandman() {
- mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ mWindow = null;
+ mWindowToken = null;
}
+ /**
+ * Called when the Dream is ready to be shown.
+ *
+ * Must run on mHandler.
+ *
+ * @param windowToken A window token that will allow a window to be created in the correct layer.
+ */
private final void attach(IBinder windowToken) {
- if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
+ if (mWindowToken != null) {
+ Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
+ return;
+ }
+
+ if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
if (mSandman == null) {
- Slog.w(TAG, "No dream manager found, super.onCreate may not have been called");
loadSandman();
}
mWindowToken = windowToken;
@@ -507,7 +566,7 @@ public class DreamService extends Service implements Window.Callback {
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
- if (DEBUG) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
+ if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
windowToken, WindowManager.LayoutParams.TYPE_DREAM));
WindowManager.LayoutParams lp = mWindow.getAttributes();
@@ -521,40 +580,35 @@ public class DreamService extends Service implements Window.Callback {
);
mWindow.setAttributes(lp);
- if (DEBUG) Slog.v(TAG, "Created and attached window: " + mWindow);
+ if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow);
mWindow.setWindowManager(null, windowToken, "dream", true);
mWindowManager = mWindow.getWindowManager();
- // now make it visible (on the ui thread)
- mHandler.post(new Runnable(){
- @Override
- public void run() {
- if (DEBUG) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
- try {
- applySystemUiVisibilityFlags(
- (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
- | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0),
- View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN);
- getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
- } catch (Throwable t) {
- Slog.w("Crashed adding window view", t);
- safelyFinish();
- return;
- }
+ if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
+ try {
+ applySystemUiVisibilityFlags(
+ (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
+ | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0),
+ View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN);
+ getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+ } catch (Throwable t) {
+ Slog.w("Crashed adding window view", t);
+ safelyFinish();
+ return;
+ }
- // start it up
- try {
- onStart();
- } catch (Throwable t) {
- Slog.w("Crashed in onStart()", t);
- safelyFinish();
- }
- }});
+ // start it up
+ try {
+ onDreamingStarted();
+ } catch (Throwable t) {
+ Slog.w("Crashed in onDreamingStarted()", t);
+ safelyFinish();
+ }
}
private void safelyFinish() {
- if (DEBUG) Slog.v(TAG, "safelyFinish()");
+ if (mDebug) Slog.v(TAG, "safelyFinish()");
try {
finish();
} catch (Throwable t) {
@@ -570,7 +624,7 @@ public class DreamService extends Service implements Window.Callback {
}
private void finishInternal() {
- if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
+ if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
if (mFinished) return;
try {
mFinished = true;
@@ -616,9 +670,41 @@ public class DreamService extends Service implements Window.Callback {
return (oldFlags&~mask) | (flags&mask);
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ super.dump(fd, pw, args);
+
+ pw.print(TAG + ": ");
+ if (mWindowToken == null) {
+ pw.println("stopped");
+ } else {
+ pw.println("running (token=" + mWindowToken + ")");
+ }
+ pw.println(" window: " + mWindow);
+ pw.print(" flags:");
+ if (isInteractive()) pw.print(" interactive");
+ if (isLowProfile()) pw.print(" lowprofile");
+ if (isFullscreen()) pw.print(" fullscreen");
+ if (isScreenBright()) pw.print(" bright");
+ pw.println();
+ }
+
private class DreamServiceWrapper extends IDreamService.Stub {
- public void attach(IBinder windowToken) {
- DreamService.this.attach(windowToken);
+ public void attach(final IBinder windowToken) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ DreamService.this.attach(windowToken);
+ }
+ });
+ }
+ public void detach() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ DreamService.this.detach();
+ }
+ });
}
}
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index 1bb241a..99dc0b7 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -21,4 +21,5 @@ package android.service.dreams;
*/
oneway interface IDreamService {
void attach(IBinder windowToken);
+ void detach();
}
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
index 3bb808f..a367367 100644
--- a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
+++ b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
@@ -9,23 +9,23 @@ public class BeanBagDream extends DreamService {
private Board mBoard;
@Override
- public void onStart() {
- super.onStart();
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
setInteractive(true);
+ setFullscreen(true);
mBoard = new Board(this, null);
+ setContentView(mBoard);
}
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- setContentView(mBoard);
- setFullscreen(true);
+ public void onDreamingStarted() {
+ super.onDreamingStarted();
mBoard.startAnimation();
}
@Override
- public void finish() {
+ public void onDreamingStopped() {
mBoard.stopAnimation();
- super.finish();
+ super.onDreamingStopped();
}
}
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/java/com/android/server/dreams/DreamController.java
index 6db495a..bfb60bb 100644
--- a/services/java/com/android/server/dreams/DreamController.java
+++ b/services/java/com/android/server/dreams/DreamController.java
@@ -132,8 +132,15 @@ final class DreamController {
}
if (oldDream.mService != null) {
- // TODO: It would be nice to tell the dream that it's being stopped so that
- // it can shut down nicely before we yank its window token out from under it.
+ // Tell the dream that it's being stopped so that
+ // it can shut down nicely before we yank its window token out from
+ // under it.
+ try {
+ oldDream.mService.detach();
+ } catch (RemoteException ex) {
+ // we don't care; this thing is on the way out
+ }
+
try {
oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
} catch (NoSuchElementException ex) {