diff options
author | Daniel Sandler <dsandler@android.com> | 2012-10-04 20:56:07 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-10-04 20:56:08 -0700 |
commit | f5e2b2c26c37d839e6559319d311b62598c6dade (patch) | |
tree | d9447574a8a87358ca19ecb370ed04c67362aecc | |
parent | a07b1fffbe7c43485b35ba83c9083a59ff328df1 (diff) | |
parent | 2d78490292090eeab84694330978c9ad7fad2d37 (diff) | |
download | frameworks_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.txt | 5 | ||||
-rw-r--r-- | api/current.txt | 5 | ||||
-rw-r--r-- | core/java/android/service/dreams/Dream.java | 23 | ||||
-rw-r--r-- | core/java/android/service/dreams/DreamService.java | 222 | ||||
-rw-r--r-- | core/java/android/service/dreams/IDreamService.aidl | 1 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/BeanBagDream.java | 16 | ||||
-rw-r--r-- | services/java/com/android/server/dreams/DreamController.java | 11 |
7 files changed, 178 insertions, 105 deletions
@@ -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> * <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) { |