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
1962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport com.android.internal.util.DumpUtils;
20f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
2162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport android.app.ActivityManager;
22f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.BroadcastReceiver;
23f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.ComponentName;
24f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Context;
25f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.Intent;
26f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.IntentFilter;
27f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.content.pm.PackageManager;
28f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Binder;
29f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.Handler;
30f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.IBinder;
3162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport android.os.Looper;
3262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport android.os.PowerManager;
3362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport android.os.SystemClock;
34f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.os.UserHandle;
35f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.provider.Settings;
36f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.service.dreams.IDreamManager;
37f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport android.util.Slog;
38f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
39f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.io.FileDescriptor;
40f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlockimport java.io.PrintWriter;
41f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
4262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownimport libcore.util.Objects;
4362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
44f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock/**
45f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * Service api for managing dreams.
46f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock *
47f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock * @hide
48f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock */
4962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brownpublic final class DreamManagerService extends IDreamManager.Stub {
50f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private static final boolean DEBUG = true;
5162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private static final String TAG = "DreamManagerService";
52f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
53f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private final Object mLock = new Object();
54f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
5562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final Context mContext;
5662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final DreamHandler mHandler;
5762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final DreamController mController;
5862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final PowerManager mPowerManager;
59f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
6062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private Binder mCurrentDreamToken;
6162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private ComponentName mCurrentDreamName;
6262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private int mCurrentDreamUserId;
6362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private boolean mCurrentDreamIsTest;
64f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
6562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public DreamManagerService(Context context, Handler mainHandler) {
66f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext = context;
6762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler = new DreamHandler(mainHandler.getLooper());
6862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mController = new DreamController(context, mHandler, mControllerListener);
6962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
7062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
71f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
72f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
73f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void systemReady() {
7462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
7562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            @Override
7662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            public void onReceive(Context context, Intent intent) {
7762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                synchronized (mLock) {
7862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    stopDreamLocked();
7962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
8062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
8162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
82f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
83f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
84f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    @Override
85f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
86f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
87f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
8862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("DREAM MANAGER (dumpsys dreams)");
8962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println();
9062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
9162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
9262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("mCurrentDreamName=" + mCurrentDreamName);
9362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
9462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
9562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        pw.println();
9662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
9762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
9862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            @Override
9962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            public void dump(PrintWriter pw) {
10062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                mController.dump(pw);
10162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
10262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }, pw, 200);
103f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
104f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
10562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
106f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public ComponentName[] getDreamComponents() {
107f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
108f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
10962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final int userId = UserHandle.getCallingUserId();
110f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
111f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
112f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return getDreamComponentsForUser(userId);
113f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
114f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
115f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
116f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
117f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
11862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
119f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void setDreamComponents(ComponentName[] componentNames) {
120f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
121f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
12262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final int userId = UserHandle.getCallingUserId();
123f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
124f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
125f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Settings.Secure.putStringForUser(mContext.getContentResolver(),
12662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    Settings.Secure.SCREENSAVER_COMPONENTS,
127f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                    componentsToString(componentNames),
128f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                    userId);
129f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
130f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
131f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
132f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
133f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
13462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
135f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public ComponentName getDefaultDreamComponent() {
136f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
137f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
13862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final int userId = UserHandle.getCallingUserId();
139f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
140f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
141f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
14262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
143f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                    userId);
144f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            return name == null ? null : ComponentName.unflattenFromString(name);
145f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
146f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
147f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
148f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
149f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
15062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
151f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public boolean isDreaming() {
152f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
153f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
15462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        synchronized (mLock) {
15562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return mCurrentDreamToken != null && !mCurrentDreamIsTest;
15662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
157f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
158f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
15962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
160f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void dream() {
161f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
162f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
163f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
164f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
16562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // Ask the power manager to nap.  It will eventually call back into
16662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // startDream() if/when it is appropriate to start dreaming.
16762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // Because napping could cause the screen to turn off immediately if the dream
16862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // cannot be started, we keep one eye open and gently poke user activity.
16962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            long time = SystemClock.uptimeMillis();
17062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mPowerManager.userActivity(time, true /*noChangeLights*/);
17162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mPowerManager.nap(time);
172f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
173f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
174f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
175f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
176f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
17762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
178f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void testDream(ComponentName dream) {
179f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
180f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
18162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (dream == null) {
18262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            throw new IllegalArgumentException("dream must not be null");
18362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
18462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
18562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final int callingUserId = UserHandle.getCallingUserId();
18662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final int currentUserId = ActivityManager.getCurrentUser();
18762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (callingUserId != currentUserId) {
18862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // This check is inherently prone to races but at least it's something.
18962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.w(TAG, "Aborted attempt to start a test dream while a different "
19062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    + " user is active: callingUserId=" + callingUserId
19162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    + ", currentUserId=" + currentUserId);
19262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
19362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
194f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
195f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
19662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            synchronized (mLock) {
19762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                startDreamLocked(dream, true /*isTest*/, callingUserId);
198f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            }
199f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
200f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
201f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
202f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
203f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
20462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
205f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    public void awaken() {
206f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
207f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
208f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
209f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
21062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // Treat an explicit request to awaken as user activity so that the
21162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // device doesn't immediately go to sleep if the timeout expired,
21262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // for example when being undocked.
21362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            long time = SystemClock.uptimeMillis();
21462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mPowerManager.userActivity(time, false /*noChangeLights*/);
21562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            stopDream();
216f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
217f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
218f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
219f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
220f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
22162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    @Override // Binder call
22262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public void finishSelf(IBinder token) {
22362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        // Requires no permission, called by Dream from an arbitrary process.
22462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (token == null) {
22562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            throw new IllegalArgumentException("token must not be null");
22662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
227f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
228f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        final long ident = Binder.clearCallingIdentity();
229f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        try {
23062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            if (DEBUG) {
23162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                Slog.d(TAG, "Dream finished: " + token);
23262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
23362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
23462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // Note that a dream finishing and self-terminating is not
23562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // itself considered user activity.  If the dream is ending because
23662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // the user interacted with the device then user activity will already
23762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // have been poked so the device will stay awake a bit longer.
23862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // If the dream is ending on its own for other reasons and no wake
23962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // locks are held and the user activity timeout has expired then the
24062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            // device may simply go to sleep.
24162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            synchronized (mLock) {
24262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                if (mCurrentDreamToken == token) {
24362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    stopDreamLocked();
24462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
245f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            }
246f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        } finally {
247f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            Binder.restoreCallingIdentity(ident);
248f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
249f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
250f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
25162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
25262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Called by the power manager to start a dream.
25362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
25462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public void startDream() {
25562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        int userId = ActivityManager.getCurrentUser();
25662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        ComponentName dream = chooseDreamForUser(userId);
25762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (dream != null) {
25862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            synchronized (mLock) {
25962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                startDreamLocked(dream, false /*isTest*/, userId);
26062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
26162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
262f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
263f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
26462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    /**
26562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     * Called by the power manager to stop a dream.
26662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown     */
26762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    public void stopDream() {
26862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        synchronized (mLock) {
26962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            stopDreamLocked();
270f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
271f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
272f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
27362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private ComponentName chooseDreamForUser(int userId) {
27462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        ComponentName[] dreams = getDreamComponentsForUser(userId);
27562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        return dreams != null && dreams.length != 0 ? dreams[0] : null;
276f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
277f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
278f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private ComponentName[] getDreamComponentsForUser(int userId) {
279f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
28062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                Settings.Secure.SCREENSAVER_COMPONENTS,
281f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                userId);
282f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        return names == null ? null : componentsFromString(names);
283f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
284f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
28562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void startDreamLocked(final ComponentName name,
28662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            final boolean isTest, final int userId) {
28762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (Objects.equal(mCurrentDreamName, name)
28862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                && mCurrentDreamIsTest == isTest
28962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                && mCurrentDreamUserId == userId) {
29062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            return;
29162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
29262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
29362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        stopDreamLocked();
29462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
29562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        Slog.i(TAG, "Entering dreamland.");
29662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
29762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        final Binder newToken = new Binder();
29862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamToken = newToken;
29962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamName = name;
30062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamIsTest = isTest;
30162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamUserId = userId;
30262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
30362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mHandler.post(new Runnable() {
30462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            @Override
30562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            public void run() {
30662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                mController.startDream(newToken, name, isTest, userId);
30762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            }
30862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        });
30962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
31062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
31162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void stopDreamLocked() {
31262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mCurrentDreamToken != null) {
31362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            Slog.i(TAG, "Leaving dreamland.");
31462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
31562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            cleanupDreamLocked();
31662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
31762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            mHandler.post(new Runnable() {
31862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                @Override
31962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                public void run() {
32062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    mController.stopDream();
32162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                }
32262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            });
32362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
32462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
32562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
32662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void cleanupDreamLocked() {
32762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamToken = null;
32862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamName = null;
32962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamIsTest = false;
33062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        mCurrentDreamUserId = 0;
33162c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
33262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
33362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private void checkPermission(String permission) {
33462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        if (mContext.checkCallingOrSelfPermission(permission)
33562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                != PackageManager.PERMISSION_GRANTED) {
33662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
33762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    + ", must have permission " + permission);
33862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        }
33962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    }
34062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown
341f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private static String componentsToString(ComponentName[] componentNames) {
342f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        StringBuilder names = new StringBuilder();
343f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        if (componentNames != null) {
344f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            for (ComponentName componentName : componentNames) {
345f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                if (names.length() > 0) {
346f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                    names.append(',');
347f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                }
348f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                names.append(componentName.flattenToString());
349f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            }
350f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
351f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        return names.toString();
352f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
353f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
354f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    private static ComponentName[] componentsFromString(String names) {
355f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        String[] namesArray = names.split(",");
356f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        ComponentName[] componentNames = new ComponentName[namesArray.length];
357f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        for (int i = 0; i < namesArray.length; i++) {
358f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
359f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
360f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        return componentNames;
361f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
362f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
36362c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final DreamController.Listener mControllerListener = new DreamController.Listener() {
36462c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        @Override
36562c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public void onDreamStopped(Binder token) {
36662c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            synchronized (mLock) {
36762c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                if (mCurrentDreamToken == token) {
36862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown                    cleanupDreamLocked();
369f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock                }
370f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock            }
371f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
37262c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    };
373f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock
374f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    /**
375f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock     * Handler for asynchronous operations performed by the dream manager.
376f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock     * Ensures operations to {@link DreamController} are single-threaded.
377f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock     */
37862c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown    private final class DreamHandler extends Handler {
37962c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown        public DreamHandler(Looper looper) {
38062c82e4d92cc0b856059f905d81885f7808a0e7dJeff Brown            super(looper, null, true /*async*/);
381f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock        }
382f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock    }
383f4f6b4c8b0fcf77d46567f13b409255948fe107bJohn Spurlock}
384