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