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;
20383db5ebcc3a4a615faf249bf4f126f42e80b82eTamas Berghammerimport com.android.internal.logging.nano.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;
279ede1d260284bbf0b47ca6f0315e943058624520Adrian Roosimport android.os.Bundle;
28f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Handler;
29f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder;
309ede1d260284bbf0b47ca6f0315e943058624520Adrian Roosimport android.os.IRemoteCallback;
317445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roosimport android.os.PowerManager;
32f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.RemoteException;
33f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder.DeathRecipient;
349bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wrenimport android.os.SystemClock;
353edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brownimport android.os.Trace;
36cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasaniimport android.os.UserHandle;
37be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackbornimport android.service.dreams.DreamService;
38f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.service.dreams.IDreamService;
39f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.util.Slog;
40f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.IWindowManager;
41f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManager;
42f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.view.WindowManagerGlobal;
43f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
44f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.io.PrintWriter;
45f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.util.NoSuchElementException;
46f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
47ac2561e8206ac42921bb6ddbb0a5972fb360e394Wale Ogunwaleimport static android.view.Display.DEFAULT_DISPLAY;
48ac2561e8206ac42921bb6ddbb0a5972fb360e394Wale Ogunwaleimport static android.view.WindowManager.LayoutParams.TYPE_DREAM;
49ac2561e8206ac42921bb6ddbb0a5972fb360e394Wale Ogunwale
50f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock/**
51f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Internal controller for starting and stopping the current dream and managing related state.
52f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
5362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown * Assumes all operations are called from the dream handler thread.
54f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock */
55f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockfinal class DreamController {
5662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private static final String TAG = "DreamController";
57f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
58006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    // How long we wait for a newly bound dream to create the service connection
59006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000;
60006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
61f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    // Time to allow the dream to perform an exit transition when waking up.
62f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private static final int DREAM_FINISH_TIMEOUT = 5 * 1000;
63f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
64f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Context mContext;
6562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final Handler mHandler;
66f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Listener mListener;
6762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final IWindowManager mIWindowManager;
689bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren    private long mDreamStartTime;
69f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
70be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
7162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
72be87e2f5885b28145a788fd31d1fb5ae88a71100Dianne Hackborn    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
7362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
74f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
7557dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn    private final Intent mCloseNotificationShadeIntent;
76591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
7762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private DreamRecord mCurrentDream;
78f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
79006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
80006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        @Override
81006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public void run() {
82006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
83006f567c214d67752cc7c2b6446c328744f40af7John Spurlock                Slog.w(TAG, "Bound dream did not connect in the time allotted");
84f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
85006f567c214d67752cc7c2b6446c328744f40af7John Spurlock            }
86006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        }
87006f567c214d67752cc7c2b6446c328744f40af7John Spurlock    };
88006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
89f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    private final Runnable mStopStubbornDreamRunnable = new Runnable() {
90f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        @Override
91f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public void run() {
92f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
93f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
94f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        }
95f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    };
96f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
9762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public DreamController(Context context, Handler handler, Listener listener) {
98f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext = context;
9962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler = handler;
100f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mListener = listener;
101f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
10257dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn        mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
10357dd737443a174379eb638450e4888500d8e4a23Dianne Hackborn        mCloseNotificationShadeIntent.putExtra("reason", "dream");
104f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
105f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
106f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void dump(PrintWriter pw) {
10762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("Dreamland:");
10862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream != null) {
10962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream:");
11062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mToken=" + mCurrentDream.mToken);
11162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mName=" + mCurrentDream.mName);
11262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
1132687550272ba061448f5d5b914700dc335299ee7Jeff Brown            pw.println("    mCanDoze=" + mCurrentDream.mCanDoze);
11462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mUserId=" + mCurrentDream.mUserId);
11562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mBound=" + mCurrentDream.mBound);
11662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mService=" + mCurrentDream.mService);
11762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
118f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            pw.println("    mWakingGently=" + mCurrentDream.mWakingGently);
11962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } else {
12062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            pw.println("  mCurrentDream: null");
121f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
122f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
123f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1242687550272ba061448f5d5b914700dc335299ee7Jeff Brown    public void startDream(Binder token, ComponentName name,
1257445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
126f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        stopDream(true /*immediate*/);
127f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1283edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
1293edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        try {
1307445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            // Close the notification shade. No need to send to all, but better to be explicit.
1313edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
132591a9e8d6ef2cab3ab3a701bd6279b6c12e6e4c6John Spurlock
1333edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Slog.i(TAG, "Starting dream: name=" + name
1343edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", isTest=" + isTest + ", canDoze=" + canDoze
1353edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", userId=" + userId);
136f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1377445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId, wakeLock);
138f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1399bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            mDreamStartTime = SystemClock.elapsedRealtime();
1409bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.visible(mContext,
141f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren                    mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
1429bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren
1433edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
144ac2561e8206ac42921bb6ddbb0a5972fb360e394Wale Ogunwale                mIWindowManager.addWindowToken(token, TYPE_DREAM, DEFAULT_DISPLAY);
1453edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (RemoteException ex) {
1463edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.e(TAG, "Unable to add window token for dream.", ex);
1473edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                stopDream(true /*immediate*/);
1483edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                return;
1493edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
150f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1513edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
1523edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            intent.setComponent(name);
1533edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1543edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
1553edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (!mContext.bindServiceAsUser(intent, mCurrentDream,
156d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
157d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                        new UserHandle(userId))) {
1583edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    Slog.e(TAG, "Unable to bind dream service: " + intent);
1593edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    stopDream(true /*immediate*/);
1603edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    return;
1613edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
1623edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (SecurityException ex) {
1633edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
164f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                stopDream(true /*immediate*/);
16562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                return;
16662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
167f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1683edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mCurrentDream.mBound = true;
1693edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
1703edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        } finally {
1713edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Trace.traceEnd(Trace.TRACE_TAG_POWER);
1723edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        }
17362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
174f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
175f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown    public void stopDream(boolean immediate) {
17662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDream == null) {
177f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return;
178f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
179f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
1803edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        Trace.traceBegin(Trace.TRACE_TAG_POWER, "stopDream");
1813edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        try {
1823edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (!immediate) {
1833edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (mCurrentDream.mWakingGently) {
1843edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    return; // already waking gently
1853edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
186f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
1873edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                if (mCurrentDream.mService != null) {
1883edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // Give the dream a moment to wake up and finish itself gently.
1893edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    mCurrentDream.mWakingGently = true;
1903edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    try {
1913edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        mCurrentDream.mService.wakeUp();
1923edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT);
1933edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        return;
1943edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    } catch (RemoteException ex) {
1953edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                        // oh well, we tried, finish immediately instead
1963edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    }
197f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                }
198f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            }
199f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
2003edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            final DreamRecord oldDream = mCurrentDream;
2013edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mCurrentDream = null;
2023edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
2033edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
2043edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    + ", userId=" + oldDream.mUserId);
2059bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.hidden(mContext,
206f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren                    oldDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
2079bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren            MetricsLogger.histogram(mContext,
2089bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren                    oldDream.mCanDoze ? "dozing_minutes" : "dreaming_minutes" ,
2099bb290bcc36fe11f96312feb40aaf3323a96ebaeChris Wren                    (int) ((SystemClock.elapsedRealtime() - mDreamStartTime) / (1000L * 60L)));
21062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
2113edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
2123edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.removeCallbacks(mStopStubbornDreamRunnable);
213006f567c214d67752cc7c2b6446c328744f40af7John Spurlock
2143edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mSentStartBroadcast) {
2153edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
2163edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
217f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2183edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mService != null) {
2193edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // Tell the dream that it's being stopped so that
2203edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // it can shut down nicely before we yank its window token out from
2213edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                // under it.
2223edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                try {
2233edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    oldDream.mService.detach();
2243edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                } catch (RemoteException ex) {
2253edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // we don't care; this thing is on the way out
2263edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2273edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown
2283edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                try {
2293edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
2303edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                } catch (NoSuchElementException ex) {
2313edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    // don't care
2323edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2333edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                oldDream.mService = null;
2342d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler            }
2352d78490292090eeab84694330978c9ad7fad2d37Daniel Sandler
2363edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            if (oldDream.mBound) {
2373edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                mContext.unbindService(oldDream);
23862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
2397445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            oldDream.releaseWakeLockIfNeeded();
240f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2413edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            try {
242ac2561e8206ac42921bb6ddbb0a5972fb360e394Wale Ogunwale                mIWindowManager.removeWindowToken(oldDream.mToken, DEFAULT_DISPLAY);
2433edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            } catch (RemoteException ex) {
2443edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                Slog.w(TAG, "Error removing window token for dream.", ex);
2453edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            }
246f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2473edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            mHandler.post(new Runnable() {
2483edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                @Override
2493edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                public void run() {
2503edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                    mListener.onDreamStopped(oldDream.mToken);
2513edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown                }
2523edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            });
2533edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown        } finally {
2543edf5272fb2185403dfe64b9722b9fc9b9de80f8Jeff Brown            Trace.traceEnd(Trace.TRACE_TAG_POWER);
255f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
25662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
25762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
25862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void attach(IDreamService service) {
25962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        try {
26062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            service.asBinder().linkToDeath(mCurrentDream, 0);
2619ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
2629ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                    mCurrentDream.mDreamingStartedCallback);
26362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        } catch (RemoteException ex) {
26462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.e(TAG, "The dream service died unexpectedly.", ex);
265f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown            stopDream(true /*immediate*/);
26662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
267f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
268f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
26962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDream.mService = service;
270f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
27162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (!mCurrentDream.mIsTest) {
272cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
27362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mCurrentDream.mSentStartBroadcast = true;
274f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
275f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
276f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
27762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
27862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Callback interface to be implemented by the {@link DreamManagerService}.
27962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
28062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public interface Listener {
28162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        void onDreamStopped(Binder token);
282f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
283f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
28462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final class DreamRecord implements DeathRecipient, ServiceConnection {
28562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final Binder mToken;
28662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final ComponentName mName;
28762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final boolean mIsTest;
2882687550272ba061448f5d5b914700dc335299ee7Jeff Brown        public final boolean mCanDoze;
28962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public final int mUserId;
29062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
2917445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos        public PowerManager.WakeLock mWakeLock;
29262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mBound;
293006f567c214d67752cc7c2b6446c328744f40af7John Spurlock        public boolean mConnected;
29462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public IDreamService mService;
29562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public boolean mSentStartBroadcast;
29662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
297f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown        public boolean mWakingGently;
298f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown
29962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public DreamRecord(Binder token, ComponentName name,
3007445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos                boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
30162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mToken = token;
30262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mName = name;
30362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mIsTest = isTest;
3042687550272ba061448f5d5b914700dc335299ee7Jeff Brown            mCanDoze = canDoze;
30562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mUserId  = userId;
3067445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            mWakeLock = wakeLock;
3079ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            // Hold the lock while we're waiting for the service to connect and start dreaming.
3089ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            // Released after the service has started dreaming, we stop dreaming, or it timed out.
3097445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos            mWakeLock.acquire();
3109ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            mHandler.postDelayed(mReleaseWakeLockIfNeeded, 10000);
311f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
312f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
31362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
31462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
31562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void binderDied() {
31662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
31762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
31862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
31962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
32062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
321f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                        stopDream(true /*immediate*/);
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 onServiceConnected(ComponentName name, final IBinder service) {
33062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
33162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
33262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
3339ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                    mConnected = true;
3349ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                    if (mCurrentDream == DreamRecord.this && mService == null) {
3359ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                        attach(IDreamService.Stub.asInterface(service));
3369ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                        // Wake lock will be released once dreaming starts.
3379ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                    } else {
3387445c0bb86c57172eb88a4e37183634abce2e37bAdrian Roos                        releaseWakeLockIfNeeded();
33962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
34062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
34162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
342f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
343f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
34462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // May be called on any thread.
34562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
34662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onServiceDisconnected(ComponentName name) {
34762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
34862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
34962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
35062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mService = null;
35162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    if (mCurrentDream == DreamRecord.this) {
352f6d466895b74d620d646abbec1c8911f3a0ce0bbJeff Brown                        stopDream(true /*immediate*/);
35362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    }
35462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
35562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
35662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
3579ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos
3589ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos        void releaseWakeLockIfNeeded() {
3599ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            if (mWakeLock != null) {
3609ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                mWakeLock.release();
3619ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                mWakeLock = null;
3629ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                mHandler.removeCallbacks(mReleaseWakeLockIfNeeded);
3639ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            }
3649ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos        }
3659ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos
3669ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos        final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;
3679ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos
3689ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos        final IRemoteCallback mDreamingStartedCallback = new IRemoteCallback.Stub() {
3699ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            // May be called on any thread.
3709ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            @Override
3719ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            public void sendResult(Bundle data) throws RemoteException {
3729ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos                mHandler.post(mReleaseWakeLockIfNeeded);
3739ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos            }
3749ede1d260284bbf0b47ca6f0315e943058624520Adrian Roos        };
37562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
376f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock}