DreamController.java revision f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21f
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
199bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wrenimport com.android.internal.logging.MetricsLogger;
20f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent;
219bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren
22f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.ComponentName;
23f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Context;
24f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Intent;
25f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.ServiceConnection;
26f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Binder;
27f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Handler;
28f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder;
29f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.RemoteException;
30f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder.DeathRecipient;
319bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wrenimport android.os.SystemClock;
323edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brownimport android.os.Trace;
33cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasaniimport android.os.UserHandle;
34be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackbornimport android.service.dreams.DreamService;
35f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.service.dreams.IDreamService;
36f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.util.Slog;
37f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.IWindowManager;
38f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManager;
39f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManagerGlobal;
40f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
41f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.io.PrintWriter;
42f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.util.NoSuchElementException;
43f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
44f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock/**
45f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Internal controller for starting and stopping the current dream and managing related state.
46f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
4762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown * Assumes all operations are called from the dream handler thread.
48f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock */
49f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockfinal class DreamController {
5062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private static final String TAG = "DreamController";
51f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
52006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    // How long we wait for a newly bound dream to create the service connection
53006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000;
54006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
55f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    // Time to allow the dream to perform an exit transition when waking up.
56f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private static final int DREAM_FINISH_TIMEOUT = 5 * 1000;
57f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
58f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Context mContext;
5962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final Handler mHandler;
60f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Listener mListener;
6162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final IWindowManager mIWindowManager;
629bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren    private long mDreamStartTime;
63f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
64be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
6562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
66be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
6762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
68f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
6957dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn    private final Intent mCloseNotificationShadeIntent;
70591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
7162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private DreamRecord mCurrentDream;
72f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
73006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
74006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        @Override
75006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public void run() {
76006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
77006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                Slog.w(TAG, "Bound dream did not connect in the time allotted");
78f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
79006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            }
80006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        }
81006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    };
82006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
83f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private final Runnable mStopStubbornDreamRunnable = new Runnable() {
84f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        @Override
85f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public void run() {
86f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
87f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
88f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        }
89f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    };
90f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
9162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public DreamController(Context context, Handler handler, Listener listener) {
92f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext = context;
9362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler = handler;
94f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mListener = listener;
95f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
9657dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn        mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
9757dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn        mCloseNotificationShadeIntent.putExtra("reason", "dream");
98f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
99f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
100f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void dump(PrintWriter pw) {
10162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("Dreamland:");
10262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream != null) {
10362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream:");
10462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mToken=" + mCurrentDream.mToken);
10562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mName=" + mCurrentDream.mName);
10662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
1072687550272ba061448f5d5b914700dc335299ee7Jeff Brown            pw.println("    mCanDoze=" + mCurrentDream.mCanDoze);
10862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mUserId=" + mCurrentDream.mUserId);
10962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mBound=" + mCurrentDream.mBound);
11062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mService=" + mCurrentDream.mService);
11162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
112f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            pw.println("    mWakingGently=" + mCurrentDream.mWakingGently);
11362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } else {
11462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream: null");
115f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
116f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
117f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1182687550272ba061448f5d5b914700dc335299ee7Jeff Brown    public void startDream(Binder token, ComponentName name,
1192687550272ba061448f5d5b914700dc335299ee7Jeff Brown            boolean isTest, boolean canDoze, int userId) {
120f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        stopDream(true /*immediate*/);
121f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1223edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
1233edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        try {
1243edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            // Close the notification shade. Don't need to send to all, but better to be explicit.
1253edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
126591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
1273edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Slog.i(TAG, "Starting dream: name=" + name
1283edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", isTest=" + isTest + ", canDoze=" + canDoze
1293edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", userId=" + userId);
130f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1313edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId);
132f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1339bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            mDreamStartTime = SystemClock.elapsedRealtime();
1349bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.visible(mContext,
135f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren                    mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
1369bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren
1373edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
1383edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
1393edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (RemoteException ex) {
1403edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.e(TAG, "Unable to add window token for dream.", ex);
1413edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                stopDream(true /*immediate*/);
1423edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                return;
1433edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
144f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1453edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
1463edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            intent.setComponent(name);
1473edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1483edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
1493edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (!mContext.bindServiceAsUser(intent, mCurrentDream,
150d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
151d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                        new UserHandle(userId))) {
1523edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    Slog.e(TAG, "Unable to bind dream service: " + intent);
1533edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    stopDream(true /*immediate*/);
1543edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    return;
1553edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
1563edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (SecurityException ex) {
1573edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
158f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
15962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                return;
16062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
161f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1623edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mCurrentDream.mBound = true;
1633edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
1643edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        } finally {
1653edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Trace.traceEnd(Trace.TRACE_TAG_POWER);
1663edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        }
16762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
168f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
169f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    public void stopDream(boolean immediate) {
17062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream == null) {
171f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
172f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
173f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1743edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        Trace.traceBegin(Trace.TRACE_TAG_POWER, "stopDream");
1753edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        try {
1763edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (!immediate) {
1773edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (mCurrentDream.mWakingGently) {
1783edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    return; // already waking gently
1793edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
180f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
1813edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (mCurrentDream.mService != null) {
1823edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // Give the dream a moment to wake up and finish itself gently.
1833edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    mCurrentDream.mWakingGently = true;
1843edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    try {
1853edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        mCurrentDream.mService.wakeUp();
1863edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT);
1873edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        return;
1883edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    } catch (RemoteException ex) {
1893edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        // oh well, we tried, finish immediately instead
1903edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    }
191f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                }
192f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            }
193f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
1943edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            final DreamRecord oldDream = mCurrentDream;
1953edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mCurrentDream = null;
1963edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
1973edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
1983edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", userId=" + oldDream.mUserId);
1999bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.hidden(mContext,
200f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren                    oldDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
2019bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.histogram(mContext,
2029bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren                    oldDream.mCanDoze ? "dozing_minutes" : "dreaming_minutes" ,
2039bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren                    (int) ((SystemClock.elapsedRealtime() - mDreamStartTime) / (1000L * 60L)));
20462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
2053edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
2063edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.removeCallbacks(mStopStubbornDreamRunnable);
207006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
2083edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mSentStartBroadcast) {
2093edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
2103edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
211f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2123edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mService != null) {
2133edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // Tell the dream that it's being stopped so that
2143edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // it can shut down nicely before we yank its window token out from
2153edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // under it.
2163edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                try {
2173edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    oldDream.mService.detach();
2183edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                } catch (RemoteException ex) {
2193edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // we don't care; this thing is on the way out
2203edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2213edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown
2223edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                try {
2233edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
2243edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                } catch (NoSuchElementException ex) {
2253edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // don't care
2263edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2273edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                oldDream.mService = null;
2282d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            }
2292d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler
2303edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mBound) {
2313edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mContext.unbindService(oldDream);
23262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
233f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2343edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
2353edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mIWindowManager.removeWindowToken(oldDream.mToken);
2363edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (RemoteException ex) {
2373edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.w(TAG, "Error removing window token for dream.", ex);
2383edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
239f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2403edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.post(new Runnable() {
2413edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                @Override
2423edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                public void run() {
2433edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    mListener.onDreamStopped(oldDream.mToken);
2443edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2453edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            });
2463edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        } finally {
2473edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Trace.traceEnd(Trace.TRACE_TAG_POWER);
248f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
24962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
25062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
25162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void attach(IDreamService service) {
25262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
25362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            service.asBinder().linkToDeath(mCurrentDream, 0);
2542687550272ba061448f5d5b914700dc335299ee7Jeff Brown            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
25562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
25662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "The dream service died unexpectedly.", ex);
257f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
25862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
259f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
260f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
26162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mService = service;
262f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
26362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (!mCurrentDream.mIsTest) {
264cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
26562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mCurrentDream.mSentStartBroadcast = true;
266f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
267f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
268f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
26962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
27062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Callback interface to be implemented by the {@link DreamManagerService}.
27162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
27262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public interface Listener {
27362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        void onDreamStopped(Binder token);
274f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
275f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
27662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final class DreamRecord implements DeathRecipient, ServiceConnection {
27762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final Binder mToken;
27862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final ComponentName mName;
27962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final boolean mIsTest;
2802687550272ba061448f5d5b914700dc335299ee7Jeff Brown        public final boolean mCanDoze;
28162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final int mUserId;
28262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
28362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mBound;
284006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public boolean mConnected;
28562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public IDreamService mService;
28662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mSentStartBroadcast;
28762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
288f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public boolean mWakingGently;
289f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
29062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public DreamRecord(Binder token, ComponentName name,
2912687550272ba061448f5d5b914700dc335299ee7Jeff Brown                boolean isTest, boolean canDoze, int userId) {
29262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mToken = token;
29362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mName = name;
29462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIsTest = isTest;
2952687550272ba061448f5d5b914700dc335299ee7Jeff Brown            mCanDoze = canDoze;
29662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mUserId  = userId;
297f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
298f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
29962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
30062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
30162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void binderDied() {
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            });
311f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
312f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
31362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
31462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
31562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceConnected(ComponentName name, final IBinder service) {
31662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
31762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
31862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
319006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                    mConnected = true;
32062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this && mService == null) {
32162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                        attach(IDreamService.Stub.asInterface(service));
32262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
32362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
32462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
325f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
326f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
32762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
32862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
32962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceDisconnected(ComponentName name) {
33062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
33162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
33262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
33362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
33462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
335f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                        stopDream(true /*immediate*/);
33662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
33762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
33862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
33962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
34062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
341f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock}