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
50f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Context mContext;
5162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final Handler mHandler;
52f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Listener mListener;
5362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final IWindowManager mIWindowManager;
54f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
55be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
5662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
57be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
5862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
59f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
60591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock    private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
61591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
6262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private DreamRecord mCurrentDream;
63f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
64006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
65006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        @Override
66006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public void run() {
67006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
68006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                Slog.w(TAG, "Bound dream did not connect in the time allotted");
69006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                stopDream();
70006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            }
71006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        }
72006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    };
73006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
7462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public DreamController(Context context, Handler handler, Listener listener) {
75f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext = context;
7662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler = handler;
77f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mListener = listener;
78f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
79f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
80f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
81f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void dump(PrintWriter pw) {
8262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("Dreamland:");
8362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream != null) {
8462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream:");
8562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mToken=" + mCurrentDream.mToken);
8662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mName=" + mCurrentDream.mName);
8762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
8862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mUserId=" + mCurrentDream.mUserId);
8962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mBound=" + mCurrentDream.mBound);
9062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mService=" + mCurrentDream.mService);
9162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
9262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } else {
9362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream: null");
94f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
95f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
96f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
9762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
9862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        stopDream();
99f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
100cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani        // Close the notification shade. Don't need to send to all, but better to be explicit.
101cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani        mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
102591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
10362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);
104f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
10562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream = new DreamRecord(token, name, isTest, userId);
106f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
107f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
10862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
10962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
11062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "Unable to add window token for dream.", ex);
11162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            stopDream();
112f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
113f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
114f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
115be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn        Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
11662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        intent.setComponent(name);
11762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
11862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
11927b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            if (!mContext.bindServiceAsUser(intent, mCurrentDream,
12027b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    Context.BIND_AUTO_CREATE, new UserHandle(userId))) {
12162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                Slog.e(TAG, "Unable to bind dream service: " + intent);
12262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                stopDream();
12362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                return;
12462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
12562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (SecurityException ex) {
12662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
12762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            stopDream();
128f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
129f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
130f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
13162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mBound = true;
132006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
13362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
134f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
13562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public void stopDream() {
13662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream == null) {
137f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
138f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
139f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
14062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final DreamRecord oldDream = mCurrentDream;
14162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream = null;
14262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
14362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                + ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);
14462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
145006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
146006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
14762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mSentStartBroadcast) {
148cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
149f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
150f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
15162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mService != null) {
1522d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // Tell the dream that it's being stopped so that
1532d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // it can shut down nicely before we yank its window token out from
1542d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            // under it.
1552d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            try {
1562d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler                oldDream.mService.detach();
1572d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            } catch (RemoteException ex) {
1582d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler                // we don't care; this thing is on the way out
1592d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            }
1602d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler
16162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            try {
16262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
16362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            } catch (NoSuchElementException ex) {
16462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                // don't care
16562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
16662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            oldDream.mService = null;
16762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
168f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
16962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (oldDream.mBound) {
17062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mContext.unbindService(oldDream);
17162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
172f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
17362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
17462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIWindowManager.removeWindowToken(oldDream.mToken);
17562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
17662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.w(TAG, "Error removing window token for dream.", ex);
177f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
17862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
17962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler.post(new Runnable() {
18062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            @Override
18162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            public void run() {
18262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                mListener.onDreamStopped(oldDream.mToken);
18362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
18462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        });
18562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
18662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
18762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void attach(IDreamService service) {
18862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
18962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            service.asBinder().linkToDeath(mCurrentDream, 0);
19062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            service.attach(mCurrentDream.mToken);
19162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
19262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "The dream service died unexpectedly.", ex);
19362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            stopDream();
19462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
195f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
196f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
19762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mService = service;
198f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
19962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (!mCurrentDream.mIsTest) {
200cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
20162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mCurrentDream.mSentStartBroadcast = true;
202f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
203f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
204f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
20562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
20662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Callback interface to be implemented by the {@link DreamManagerService}.
20762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
20862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public interface Listener {
20962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        void onDreamStopped(Binder token);
210f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
211f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
21262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final class DreamRecord implements DeathRecipient, ServiceConnection {
21362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final Binder mToken;
21462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final ComponentName mName;
21562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final boolean mIsTest;
21662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final int mUserId;
21762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
21862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mBound;
219006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public boolean mConnected;
22062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public IDreamService mService;
22162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mSentStartBroadcast;
22262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
22362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public DreamRecord(Binder token, ComponentName name,
22462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                boolean isTest, int userId) {
22562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mToken = token;
22662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mName = name;
22762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIsTest = isTest;
22862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mUserId  = userId;
229f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
230f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
23162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
23262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
23362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void binderDied() {
23462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
23562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
23662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
23762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
23862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
23962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                        stopDream();
24062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
24162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
24262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
243f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
244f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
24562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
24662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
24762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceConnected(ComponentName name, final IBinder service) {
24862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
24962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
25062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
251006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                    mConnected = true;
25262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this && mService == null) {
25362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                        attach(IDreamService.Stub.asInterface(service));
25462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
25562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
25662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
257f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
258f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
25962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
26062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
26162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceDisconnected(ComponentName name) {
26262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
26362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
26462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
26562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
26662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
26762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                        stopDream();
26862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
26962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
27062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
27162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
27262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
273f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock}