FileDocCategorySizeDatePackage
DreamController.javaAPI DocAndroid 5.1 API11879Thu Mar 12 22:22:42 GMT 2015com.android.server.dreams

DreamController

public final class DreamController extends Object
Internal controller for starting and stopping the current dream and managing related state. Assumes all operations are called from the dream handler thread.

Fields Summary
private static final String
TAG
private static final int
DREAM_CONNECTION_TIMEOUT
private static final int
DREAM_FINISH_TIMEOUT
private final android.content.Context
mContext
private final android.os.Handler
mHandler
private final Listener
mListener
private final android.view.IWindowManager
mIWindowManager
private final android.content.Intent
mDreamingStartedIntent
private final android.content.Intent
mDreamingStoppedIntent
private final android.content.Intent
mCloseNotificationShadeIntent
private DreamRecord
mCurrentDream
private final Runnable
mStopUnconnectedDreamRunnable
private final Runnable
mStopStubbornDreamRunnable
Constructors Summary
public DreamController(android.content.Context context, android.os.Handler handler, Listener listener)


           
        mContext = context;
        mHandler = handler;
        mListener = listener;
        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
    
Methods Summary
private voidattach(android.service.dreams.IDreamService service)

        try {
            service.asBinder().linkToDeath(mCurrentDream, 0);
            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
        } catch (RemoteException ex) {
            Slog.e(TAG, "The dream service died unexpectedly.", ex);
            stopDream(true /*immediate*/);
            return;
        }

        mCurrentDream.mService = service;

        if (!mCurrentDream.mIsTest) {
            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
            mCurrentDream.mSentStartBroadcast = true;
        }
    
public voiddump(java.io.PrintWriter pw)

        pw.println("Dreamland:");
        if (mCurrentDream != null) {
            pw.println("  mCurrentDream:");
            pw.println("    mToken=" + mCurrentDream.mToken);
            pw.println("    mName=" + mCurrentDream.mName);
            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
            pw.println("    mCanDoze=" + mCurrentDream.mCanDoze);
            pw.println("    mUserId=" + mCurrentDream.mUserId);
            pw.println("    mBound=" + mCurrentDream.mBound);
            pw.println("    mService=" + mCurrentDream.mService);
            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
            pw.println("    mWakingGently=" + mCurrentDream.mWakingGently);
        } else {
            pw.println("  mCurrentDream: null");
        }
    
public voidstartDream(android.os.Binder token, android.content.ComponentName name, boolean isTest, boolean canDoze, int userId)

        stopDream(true /*immediate*/);

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
        try {
            // Close the notification shade. Don't need to send to all, but better to be explicit.
            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);

            Slog.i(TAG, "Starting dream: name=" + name
                    + ", isTest=" + isTest + ", canDoze=" + canDoze
                    + ", userId=" + userId);

            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId);

            try {
                mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
            } catch (RemoteException ex) {
                Slog.e(TAG, "Unable to add window token for dream.", ex);
                stopDream(true /*immediate*/);
                return;
            }

            Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
            intent.setComponent(name);
            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            try {
                if (!mContext.bindServiceAsUser(intent, mCurrentDream,
                        Context.BIND_AUTO_CREATE, new UserHandle(userId))) {
                    Slog.e(TAG, "Unable to bind dream service: " + intent);
                    stopDream(true /*immediate*/);
                    return;
                }
            } catch (SecurityException ex) {
                Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
                stopDream(true /*immediate*/);
                return;
            }

            mCurrentDream.mBound = true;
            mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    
public voidstopDream(boolean immediate)

        if (mCurrentDream == null) {
            return;
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "stopDream");
        try {
            if (!immediate) {
                if (mCurrentDream.mWakingGently) {
                    return; // already waking gently
                }

                if (mCurrentDream.mService != null) {
                    // Give the dream a moment to wake up and finish itself gently.
                    mCurrentDream.mWakingGently = true;
                    try {
                        mCurrentDream.mService.wakeUp();
                        mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT);
                        return;
                    } catch (RemoteException ex) {
                        // oh well, we tried, finish immediately instead
                    }
                }
            }

            final DreamRecord oldDream = mCurrentDream;
            mCurrentDream = null;
            Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
                    + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
                    + ", userId=" + oldDream.mUserId);

            mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
            mHandler.removeCallbacks(mStopStubbornDreamRunnable);

            if (oldDream.mSentStartBroadcast) {
                mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
            }

            if (oldDream.mService != null) {
                // 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) {
                    // don't care
                }
                oldDream.mService = null;
            }

            if (oldDream.mBound) {
                mContext.unbindService(oldDream);
            }

            try {
                mIWindowManager.removeWindowToken(oldDream.mToken);
            } catch (RemoteException ex) {
                Slog.w(TAG, "Error removing window token for dream.", ex);
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onDreamStopped(oldDream.mToken);
                }
            });
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }