Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22505501 authored by John Spurlock's avatar John Spurlock Committed by Android (Google) Code Review
Browse files

Merge "Additions to Dream public api." into jb-mr1-dev

parents 3ed6f945 d5c582c4
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -20274,8 +20274,11 @@ package android.service.dreams {
    method public void finish();
    method public android.view.Window getWindow();
    method public android.view.WindowManager getWindowManager();
    method public boolean isFullscreen();
    method public boolean isInteractive();
    method protected void lightsOut();
    method public boolean isLowProfile();
    method public boolean isScreenBright();
    method protected deprecated void lightsOut();
    method public void onActionModeFinished(android.view.ActionMode);
    method public void onActionModeStarted(android.view.ActionMode);
    method public void onAttachedToWindow();
@@ -20296,11 +20299,14 @@ package android.service.dreams {
    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 setFullscreen(boolean);
    method public void setInteractive(boolean);
    method public void setLowProfile(boolean);
    method public void setScreenBright(boolean);
    field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
    field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
    field public static final java.lang.String CATEGORY_DREAM = "android.intent.category.DREAM";
    field public static final java.lang.String METADATA_NAME_CONFIG_ACTIVITY = "android.service.dreams.config_activity";
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.Dream";
  }
}
+222 −64
Original line number Diff line number Diff line
@@ -44,22 +44,47 @@ import com.android.internal.policy.PolicyManager;
 * <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>
 * <pre>
 * {@code
 * <service
 *     android:name=".MyDream"
 *     android:exported="true"
 *     android:icon="@drawable/my_icon"
 *     android:label="@string/my_dream_label" >
 *
 *     <intent-filter>
 *         <action android:name="android.intent.action.MAIN" />
 *         <category android:name="android.intent.category.DREAM" />
 *     </intent-filter>
 *
 *     <!-- Point to configuration activity for this dream (optional) -->
 *     <meta-data
 *         android:name="android.service.dreams.config_activity"
 *         android:value="com.example.mypackage/com.example.mypackage.MyDreamSettingsActivity" />
 * </service>
 * }
 * </pre>
 */
public class Dream extends Service implements Window.Callback {
    private final static boolean DEBUG = true;
    private final String TAG = Dream.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";

    /**
     * The {@link Intent} that must be declared as handled by the service.
     * To be supported, the service must also require the
     * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
     * that other applications can not abuse it.
     * Used with {@link #ACTION_MAIN} to declare the necessary intent-filter for a dream.
     *
     * @see Dream
     */
    @SdkConstant(SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE =
            "android.service.dreams.Dream";
    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_DREAM =
            "android.intent.category.DREAM";

    /** Service meta-data key for declaring an optional configuration activity. */
    /**
     * Service meta-data key for declaring an optional configuration activity.
     *
     * @see Dream
     * */
    public static final String METADATA_NAME_CONFIG_ACTIVITY =
            "android.service.dreams.config_activity";

@@ -86,10 +111,14 @@ public class Dream extends Service implements Window.Callback {
    private Window mWindow;
    private WindowManager mWindowManager;
    private IDreamManager mSandman;
    private boolean mInteractive;
    private boolean mInteractive = false;
    private boolean mLowProfile = true;
    private boolean mFullscreen = false;
    private boolean mScreenBright = false;
    private boolean mFinished;

    // begin Window.Callback methods
    /** {@inheritDoc} */
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
@@ -105,6 +134,7 @@ public class Dream extends Service implements Window.Callback {
        return mWindow.superDispatchKeyEvent(event);
    }

    /** {@inheritDoc} */
    @Override
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        if (!mInteractive) { 
@@ -115,6 +145,7 @@ public class Dream extends Service implements Window.Callback {
        return mWindow.superDispatchKeyShortcutEvent(event);
    }

    /** {@inheritDoc} */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        // TODO: create more flexible version of mInteractive that allows clicks 
@@ -127,6 +158,7 @@ public class Dream extends Service implements Window.Callback {
        return mWindow.superDispatchTouchEvent(event);
    }

    /** {@inheritDoc} */
    @Override
    public boolean dispatchTrackballEvent(MotionEvent event) {
        if (!mInteractive) {
@@ -137,6 +169,7 @@ public class Dream extends Service implements Window.Callback {
        return mWindow.superDispatchTrackballEvent(event);
    }

    /** {@inheritDoc} */
    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        if (!mInteractive) { 
@@ -147,86 +180,112 @@ public class Dream extends Service implements Window.Callback {
        return mWindow.superDispatchGenericMotionEvent(event);
    }

    /** {@inheritDoc} */
    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public View onCreatePanelView(int featureId) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean onCreatePanelMenu(int featureId, Menu menu) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean onPreparePanel(int featureId, View view, Menu menu) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public void onWindowAttributesChanged(LayoutParams attrs) {

    }

    /** {@inheritDoc} */
    @Override
    public void onContentChanged() {

    }

    /** {@inheritDoc} */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {

    }

    /** {@inheritDoc} */
    @Override
    public void onAttachedToWindow() {
    }

    /** {@inheritDoc} */
    @Override
    public void onDetachedFromWindow() {
    }

    /** {@inheritDoc} */
    @Override
    public void onPanelClosed(int featureId, Menu menu) {
    }

    /** {@inheritDoc} */
    @Override
    public boolean onSearchRequested() {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public void onActionModeStarted(ActionMode mode) {
    }

    /** {@inheritDoc} */
    @Override
    public void onActionModeFinished(ActionMode mode) {
    }
    // end Window.Callback methods

    // begin public api
    /**
     * Retrieves the current {@link android.view.WindowManager} for the dream.
     * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
     *
     * @return The current window manager, or null if the dream is not started.
     */
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

    /**
     * Retrieves the current {@link android.view.Window} for the dream.
     * Behaves similarly to {@link android.app.Activity#getWindow()}.
     *
     * @return The current window, or null if the dream is not started.
     */
    public Window getWindow() {
        return mWindow;
    }
@@ -235,6 +294,8 @@ public class Dream extends Service implements Window.Callback {
     * Inflates a layout resource and set it to be the content view for this Dream.
     * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
     *
     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
     *
     * @param layoutResID Resource ID to be inflated.
     * 
     * @see #setContentView(android.view.View)
@@ -249,6 +310,7 @@ public class Dream extends Service implements Window.Callback {
     * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
     * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
     *
     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
     * @param view The desired content to display.
     *
     * @see #setContentView(int)
@@ -263,6 +325,8 @@ public class Dream extends Service implements Window.Callback {
     * 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>
     *
     * @param view The desired content to display.
     * @param params Layout parameters for the view.
     *
@@ -276,6 +340,8 @@ public class Dream extends Service implements Window.Callback {
    /**
     * Adds a view to the Dream's window, leaving other content views in place.
     *
     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
     *
     * @param view The desired content to display.
     * @param params Layout parameters for the view.
     */
@@ -283,6 +349,25 @@ public class Dream extends Service implements Window.Callback {
        getWindow().addContentView(view, params);
    }

    /**
     * Finds a view that was identified by the id attribute from the XML that
     * was processed in {@link #onCreate}.
     *
     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
     *
     * @return The view if found or null otherwise.
     */
    public View findViewById(int id) {
        return getWindow().findViewById(id);
    }

    /** FIXME remove once platform dreams are updated */
    @Deprecated
    protected void lightsOut() {
        setLowProfile(true);
        setFullscreen(true);
    }

    /**
     * Marks this dream as interactive to receive input events.
     *
@@ -297,36 +382,79 @@ public class Dream extends Service implements Window.Callback {
    }

    /**
     * Returns whether or not this dream is interactive.
     * Returns whether or not this dream is interactive.  Defaults to false.
     *
     * @see #setInteractive(boolean)
     */
    public boolean isInteractive() {
        return mInteractive;
    }

    /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */
    protected void lightsOut() {
        // turn the lights down low
        final View v = mWindow.getDecorView();
        if (v != null) {
            v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE 
                                  | View.SYSTEM_UI_FLAG_FULLSCREEN);
    /**
     * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
     *
     * @param lightsOut True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
     */
    public void setLowProfile(boolean 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.
     *
     * @see #setLowProfile(boolean)
     */
    public boolean isLowProfile() {
        return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
    }

    /**
     * Finds a view that was identified by the id attribute from the XML that
     * was processed in {@link #onCreate}.
     * Sets View.SYSTEM_UI_FLAG_FULLSCREEN on the content view.
     *
     * @return The view if found or null otherwise.
     * @param fullscreen True to set View.SYSTEM_UI_FLAG_FULLSCREEN
     */
    public View findViewById(int id) {
        return getWindow().findViewById(id);
    public void setFullscreen(boolean fullscreen) {
        mFullscreen = fullscreen;
        int flag = View.SYSTEM_UI_FLAG_FULLSCREEN;
        applySystemUiVisibilityFlags(mFullscreen ? flag : 0, flag);
    }

    /**
     * Returns whether or not this dream is in fullscreen mode. Defaults to false.
     *
     * @see #setFullscreen(boolean)
     */
    public boolean isFullscreen() {
        return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_FULLSCREEN, mFullscreen);
    }

    /**
     * Marks this dream as keeping the screen bright while dreaming.
     *
     * @param screenBright True to keep the screen bright while dreaming.
     */
    public void setScreenBright(boolean 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.
     *
     * @see #setScreenBright(boolean)
     */
    public boolean isScreenBright() {
        return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
    }

    /**
     * Called when this Dream is constructed. Place your initialization here.
     *
     * Subclasses must call through to the superclass implementation.
     * <p>Subclasses must call through to the superclass implementation.</p>
     */
    @Override
    public void onCreate() {
@@ -336,23 +464,51 @@ public class Dream extends Service implements Window.Callback {
    }

    /**
     * Called when this Dream is started.
     * Called when this Dream is started.  The window is created and visible at this point.
     */
    public void onStart() {
        if (DEBUG) Slog.v(TAG, "onStart()");
        // hook for subclasses
        Slog.v(TAG, "called Dream.onStart()");
    }

    private void loadSandman() {
        mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
    /** {@inheritDoc} */
    @Override
    public final IBinder onBind(Intent intent) {
        if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
        return new DreamServiceWrapper();
    }

    /**
     * Creates a new dream window, attaches the current content view, and shows it.
     * Stops the dream, detaches from the window, and wakes up.
     *
     * <p>Subclasses must call through to the superclass implementation.</p>
     *
     * @param windowToken Binder to attach to the window to allow access to the correct window type.
     * @hide
     * <p>After this method is called, the service will be stopped.</p>
     */
    public void finish() {
        if (DEBUG) Slog.v(TAG, "finish()");
        finishInternal();
    }

    /** {@inheritDoc} */
    @Override
    public void onDestroy() {
        if (DEBUG) Slog.v(TAG, "onDestroy()");
        super.onDestroy();

        if (DEBUG) Slog.v(TAG, "Removing window");
        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("dreams"));
    }

    private final void attach(IBinder windowToken) {
        if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());

@@ -376,6 +532,7 @@ public class Dream extends Service implements Window.Callback {
        lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
                    | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
                    );
        mWindow.setAttributes(lp);

@@ -389,8 +546,11 @@ public class Dream extends Service implements Window.Callback {
            @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);
@@ -424,18 +584,6 @@ public class Dream extends Service implements Window.Callback {
        }
    }

    /**
     * Stops the dream, detaches from the window, and wakes up.
     *
     * Subclasses must call through to the superclass implementation.
     *
     * <p>After this method is called, the service will be stopped.</p>
     */
    public void finish() {
        if (DEBUG) Slog.v(TAG, "finish()");
        finishInternal();
    }

    private void finishInternal() {
        if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
        if (mFinished) return;
@@ -454,23 +602,33 @@ public class Dream extends Service implements Window.Callback {
        }
    }

    @Override
    public void onDestroy() {
        if (DEBUG) Slog.v(TAG, "onDestroy()");
        super.onDestroy();
    private boolean getWindowFlagValue(int flag, boolean defaultValue) {
        return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
    }

        if (DEBUG) Slog.v(TAG, "Removing window");
        try {
            mWindowManager.removeView(mWindow.getDecorView());
        } catch (Throwable t) {
            Slog.w(TAG, "Crashed removing window view", t);
    private void applyWindowFlags(int flags, int mask) {
        if (mWindow != null) {
            WindowManager.LayoutParams lp = mWindow.getAttributes();
            lp.flags = applyFlags(lp.flags, flags, mask);
            mWindow.setAttributes(lp);
            mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
        }
    }

    @Override
    public final IBinder onBind(Intent intent) {
        if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
        return new DreamServiceWrapper();
    private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
        View v = mWindow == null ? null : mWindow.getDecorView();
        return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
    }

    private void applySystemUiVisibilityFlags(int flags, int mask) {
        View v = mWindow == null ? null : mWindow.getDecorView();
        if (v != null) {
            v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
        }
    }

    private int applyFlags(int oldFlags, int flags, int mask) {
        return (oldFlags&~mask) | (flags&mask);
    }

    private class DreamServiceWrapper extends IDreamService.Stub {