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}