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

Commit f5e2b2c2 authored by Daniel Sandler's avatar Daniel Sandler Committed by Android (Google) Code Review
Browse files

Merge "DreamService API revisions." into jb-mr1-dev

parents a07b1fff 2d784902
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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);
+3 −2
Original line number Diff line number Diff line
@@ -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);
+0 −23
Original line number Diff line number Diff line
/**
 * 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 {
}
+154 −68
Original line number Diff line number Diff line
@@ -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;
        }
@@ -130,7 +152,7 @@ public class DreamService extends Service implements Window.Callback {
    @Override
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        if (!mInteractive) {
            if (DEBUG) Slog.v(TAG, "Finishing on keyShortcutEvent");
            if (mDebug) Slog.v(TAG, "Finishing on keyShortcutEvent");
            safelyFinish();
            return true;
        }
@@ -143,7 +165,7 @@ 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 (DEBUG) Slog.v(TAG, "Finishing on touchEvent");
            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;
        }
@@ -165,7 +187,7 @@ public class DreamService extends Service implements Window.Callback {
    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        if (!mInteractive) {
            if (DEBUG) Slog.v(TAG, "Finishing on genericMotionEvent");
            if (mDebug) Slog.v(TAG, "Finishing on genericMotionEvent");
            safelyFinish();
            return true;
        }
@@ -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;
        }

        if (DEBUG) Slog.v(TAG, "Removing window");
        try {
            onDreamingStopped();
        } catch (Throwable t) {
            Slog.w(TAG, "Crashed in onDreamingStopped()", t);
            // we were going to stop anyway
        }

        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,16 +580,12 @@ 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());
        if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
        try {
            applySystemUiVisibilityFlags(
                    (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
@@ -545,16 +600,15 @@ public class DreamService extends Service implements Window.Callback {

        // start it up
        try {
                    onStart();
            onDreamingStarted();
        } catch (Throwable t) {
                    Slog.w("Crashed in onStart()", 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,10 +670,42 @@ 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) {
        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();
                }
            });
        }
    }

}
+1 −0
Original line number Diff line number Diff line
@@ -21,4 +21,5 @@ package android.service.dreams;
 */
oneway interface IDreamService {
    void attach(IBinder windowToken);
    void detach();
}
Loading