DreamController.java revision f6d466895b74d620d646abbec1c8911f3a0ce0bb
1f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock/*
2f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Copyright (C) 2012 The Android Open Source Project
3f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
4f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * you may not use this file except in compliance with the License.
6f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * You may obtain a copy of the License at
7f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
8f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
10f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * See the License for the specific language governing permissions and
14f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * limitations under the License.
15f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock */
16f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
17cef440f2a2bb8b6e8d082d12a67dc21f2ee65e3cJeff Brownpackage com.android.server.dreams;
18f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
19f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.ComponentName;
20f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Context;
21f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Intent;
22f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.ServiceConnection;
23f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Binder;
24f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Handler;
25f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder;
26f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.RemoteException;
27f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder.DeathRecipient;
28cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasaniimport android.os.UserHandle;
29be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackbornimport android.service.dreams.DreamService;
30f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.service.dreams.IDreamService;
31f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.util.Slog;
32f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.IWindowManager;
33f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManager;
34f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManagerGlobal;
35f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
36f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.io.PrintWriter;
37f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.util.NoSuchElementException;
38f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
39f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock/**
40f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Internal controller for starting and stopping the current dream and managing related state.
41f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
4262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown * Assumes all operations are called from the dream handler thread.
43f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock */
44f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockfinal class DreamController {
4562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private static final String TAG = "DreamController";
46f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
47006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    // How long we wait for a newly bound dream to create the service connection
48006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000;
49006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
50f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    // Time to allow the dream to perform an exit transition when waking up.
51f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private static final int DREAM_FINISH_TIMEOUT = 5 * 1000;
52f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
53f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Context mContext;
5462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final Handler mHandler;
55f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Listener mListener;
5662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final IWindowManager mIWindowManager;
57f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
58be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
5962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
60be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
6162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
62f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
63591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock    private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
64591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
6562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private DreamRecord mCurrentDream;
66f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
67006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
68006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        @Override
69006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public void run() {
70006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
71006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                Slog.w(TAG, "Bound dream did not connect in the time allotted");
72f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
73006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            }
74006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        }
75006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    };
76006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
77f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private final Runnable mStopStubbornDreamRunnable = new Runnable() {
78f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        @Override
79f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public void run() {
80f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
81f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
82f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        }
83f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    };
84f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
8562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public DreamController(Context context, Handler handler, Listener listener) {
86f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext = context;
8762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler = handler;
88f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mListener = listener;
89f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
90f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
91f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
92f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void dump(PrintWriter pw) {
9362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("Dreamland:");
9462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream != null) {
9562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream:");
9662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mToken=" + mCurrentDream.mToken);
9762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mName=" + mCurrentDream.mName);
9862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
992687550272ba061448f5d5b914700dc335299ee7Jeff Brown            pw.println("    mCanDoze=" + mCurrentDream.mCanDoze);
10062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mUserId=" + mCurrentDream.mUserId);
10162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mBound=" + mCurrentDream.mBound);
10262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mService=" + mCurrentDream.mService);
10362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
104f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            pw.println("    mWakingGently=" + mCurrentDream.mWakingGently);
10562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } else {
10662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream: null");
107f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
108f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
109f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1102687550272ba061448f5d5b914700dc335299ee7Jeff Brown    public void startDream(Binder token, ComponentName name,
1112687550272ba061448f5d5b914700dc335299ee7Jeff Brown            boolean isTest, boolean canDoze, int userId) {
112f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        stopDream(true /*immediate*/);
113f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
114cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani        // Close the notification shade. Don't need to send to all, but better to be explicit.
115cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani        mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
116591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
1172687550272ba061448f5d5b914700dc335299ee7Jeff Brown        Slog.i(TAG, "Starting dream: name=" + name
1182687550272ba061448f5d5b914700dc335299ee7Jeff Brown                + ", isTest=" + isTest + ", canDoze=" + canDoze
1192687550272ba061448f5d5b914700dc335299ee7Jeff Brown                + ", userId=" + userId);
120f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1212687550272ba061448f5d5b914700dc335299ee7Jeff Brown        mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId);
122f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
123f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
12462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
12562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
12662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "Unable to add window token for dream.", ex);
127f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
128f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
129f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
130f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
131be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn        Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
13262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        intent.setComponent(name);
13362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
13462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
13527b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            if (!mContext.bindServiceAsUser(intent, mCurrentDream,
13627b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    Context.BIND_AUTO_CREATE, new UserHandle(userId))) {
13762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                Slog.e(TAG, "Unable to bind dream service: " + intent);
138f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
13962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                return;
14062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
14162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (SecurityException ex) {
14262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
143f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
144f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
145f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
146f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
14762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mBound = true;
148006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
14962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
150f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
151f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    public void stopDream(boolean immediate) {
15262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream == null) {
153f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
154f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
155f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
156f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        if (!immediate) {
157f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            if (mCurrentDream.mWakingGently) {
158f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                return; // already waking gently
159f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            }
160f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
161f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            if (mCurrentDream.mService != null) {
162f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                // Give the dream a moment to wake up and finish itself gently.
163f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                mCurrentDream.mWakingGently = true;
164f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                try {
165f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                    mCurrentDream.mService.wakeUp();
166f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                    mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT);
167f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                    return;
168f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                } catch (RemoteException ex) {
169f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                    // oh well, we tried, finish immediately instead
170f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                }
171f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            }
172f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        }
173f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
17462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final DreamRecord oldDream = mCurrentDream;
17562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream = null;
17662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
1772687550272ba061448f5d5b914700dc335299ee7Jeff Brown                + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
1782687550272ba061448f5d5b914700dc335299ee7Jeff Brown                + ", userId=" + oldDream.mUserId);
17962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
180006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
181f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        mHandler.removeCallbacks(mStopStubbornDreamRunnable);
182006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
18362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mSentStartBroadcast) {
184cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
185f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
186f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
18762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mService != null) {
1882d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // Tell the dream that it's being stopped so that
1892d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // it can shut down nicely before we yank its window token out from
1902d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // under it.
1912d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            try {
1922d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler                oldDream.mService.detach();
1932d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            } catch (RemoteException ex) {
1942d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler                // we don't care; this thing is on the way out
1952d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            }
1962d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler
19762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            try {
19862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
19962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            } catch (NoSuchElementException ex) {
20062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                // don't care
20162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
20262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            oldDream.mService = null;
20362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
204f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
20562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mBound) {
20662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mContext.unbindService(oldDream);
20762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
208f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
20962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
21062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIWindowManager.removeWindowToken(oldDream.mToken);
21162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
21262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.w(TAG, "Error removing window token for dream.", ex);
213f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
21462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
21562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler.post(new Runnable() {
21662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            @Override
21762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            public void run() {
21862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                mListener.onDreamStopped(oldDream.mToken);
21962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
22062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        });
22162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
22262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
22362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void attach(IDreamService service) {
22462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
22562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            service.asBinder().linkToDeath(mCurrentDream, 0);
2262687550272ba061448f5d5b914700dc335299ee7Jeff Brown            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
22762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
22862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "The dream service died unexpectedly.", ex);
229f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
23062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
231f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
232f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
23362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mService = service;
234f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
23562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (!mCurrentDream.mIsTest) {
236cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
23762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mCurrentDream.mSentStartBroadcast = true;
238f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
239f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
240f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
24162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
24262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Callback interface to be implemented by the {@link DreamManagerService}.
24362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
24462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public interface Listener {
24562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        void onDreamStopped(Binder token);
246f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
247f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
24862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final class DreamRecord implements DeathRecipient, ServiceConnection {
24962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final Binder mToken;
25062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final ComponentName mName;
25162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final boolean mIsTest;
2522687550272ba061448f5d5b914700dc335299ee7Jeff Brown        public final boolean mCanDoze;
25362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final int mUserId;
25462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
25562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mBound;
256006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public boolean mConnected;
25762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public IDreamService mService;
25862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mSentStartBroadcast;
25962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
260f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public boolean mWakingGently;
261f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
26262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public DreamRecord(Binder token, ComponentName name,
2632687550272ba061448f5d5b914700dc335299ee7Jeff Brown                boolean isTest, boolean canDoze, int userId) {
26462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mToken = token;
26562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mName = name;
26662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIsTest = isTest;
2672687550272ba061448f5d5b914700dc335299ee7Jeff Brown            mCanDoze = canDoze;
26862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mUserId  = userId;
269f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
270f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
27162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
27262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
27362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void binderDied() {
27462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
27562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
27662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
27762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
27862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
279f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                        stopDream(true /*immediate*/);
28062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
28162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
28262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
283f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
284f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
28562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
28662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
28762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceConnected(ComponentName name, final IBinder service) {
28862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
28962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
29062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
291006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                    mConnected = true;
29262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this && mService == null) {
29362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                        attach(IDreamService.Stub.asInterface(service));
29462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
29562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
29662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
297f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
298f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
29962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
30062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
30162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceDisconnected(ComponentName name) {
30262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
30362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
30462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
30562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
30662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
307f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                        stopDream(true /*immediate*/);
30862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
30962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
31062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
31162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
31262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
313f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock}