From 567f7ca424280ae957b04d4f3df690055f2d41df Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Thu, 30 Jan 2014 23:38:03 -0800 Subject: [PATCH] Refactor dream manager to new pattern. Change-Id: I99ab4bd98d56a290368dc4b24e5bb24e0656b522 --- .../service/dreams/DreamManagerInternal.java | 39 +++ .../android/server/dreams/DreamManagerService.java | 378 ++++++++++++--------- .../android/server/power/PowerManagerService.java | 12 +- services/java/com/android/server/SystemServer.java | 26 +- 4 files changed, 274 insertions(+), 181 deletions(-) create mode 100644 core/java/android/service/dreams/DreamManagerInternal.java diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java new file mode 100644 index 000000000000..17ea996b38c9 --- /dev/null +++ b/core/java/android/service/dreams/DreamManagerInternal.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.dreams; + +/** + * Dream manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class DreamManagerInternal { + /** + * Called by the power manager to start a dream. + */ + public abstract void startDream(); + + /** + * Called by the power manager to stop a dream. + */ + public abstract void stopDream(); + + /** + * Called by the power manager to determine whether a dream is running. + */ + public abstract boolean isDreaming(); +} diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index f5acc4c067af..ffb113cb6ab7 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -18,7 +18,9 @@ package com.android.server.dreams; import com.android.internal.util.DumpUtils; import com.android.server.FgThread; +import com.android.server.SystemService; +import android.Manifest; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -35,6 +37,8 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.service.dreams.DreamManagerInternal; +import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.util.Slog; @@ -50,7 +54,7 @@ import libcore.util.Objects; * * @hide */ -public final class DreamManagerService extends IDreamManager.Stub { +public final class DreamManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "DreamManagerService"; @@ -67,6 +71,7 @@ public final class DreamManagerService extends IDreamManager.Stub { private boolean mCurrentDreamIsTest; public DreamManagerService(Context context) { + super(context); mContext = context; mHandler = new DreamHandler(FgThread.get().getLooper()); mController = new DreamController(context, mHandler, mControllerListener); @@ -74,27 +79,27 @@ public final class DreamManagerService extends IDreamManager.Stub { mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); } - public void systemRunning() { - mContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - synchronized (mLock) { - stopDreamLocked(); - } - } - }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); + @Override + public void onStart() { + publishBinderService(DreamService.DREAM_SERVICE, new BinderService()); + publishLocalService(DreamManagerInternal.class, new LocalService()); } @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DreamManager from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + synchronized (mLock) { + stopDreamLocked(); + } + } + }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); } + } + private void dumpInternal(PrintWriter pw) { pw.println("DREAM MANAGER (dumpsys dreams)"); pw.println(); @@ -112,156 +117,57 @@ public final class DreamManagerService extends IDreamManager.Stub { }, pw, 200); } - @Override // Binder call - public ComponentName[] getDreamComponents() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - return getDreamComponentsForUser(userId); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void setDreamComponents(ComponentName[] componentNames) { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.SCREENSAVER_COMPONENTS, - componentsToString(componentNames), - userId); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public ComponentName getDefaultDreamComponent() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - - final int userId = UserHandle.getCallingUserId(); - final long ident = Binder.clearCallingIdentity(); - try { - String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), - Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, - userId); - return name == null ? null : ComponentName.unflattenFromString(name); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public boolean isDreaming() { - checkPermission(android.Manifest.permission.READ_DREAM_STATE); - + private boolean isDreamingInternal() { synchronized (mLock) { return mCurrentDreamToken != null && !mCurrentDreamIsTest; } } - @Override // Binder call - public void dream() { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final long ident = Binder.clearCallingIdentity(); - try { - // Ask the power manager to nap. It will eventually call back into - // startDream() if/when it is appropriate to start dreaming. - // Because napping could cause the screen to turn off immediately if the dream - // cannot be started, we keep one eye open and gently poke user activity. - long time = SystemClock.uptimeMillis(); - mPowerManager.userActivity(time, true /*noChangeLights*/); - mPowerManager.nap(time); - } finally { - Binder.restoreCallingIdentity(ident); - } + private void requestDreamInternal() { + // Ask the power manager to nap. It will eventually call back into + // startDream() if/when it is appropriate to start dreaming. + // Because napping could cause the screen to turn off immediately if the dream + // cannot be started, we keep one eye open and gently poke user activity. + long time = SystemClock.uptimeMillis(); + mPowerManager.userActivity(time, true /*noChangeLights*/); + mPowerManager.nap(time); } - @Override // Binder call - public void testDream(ComponentName dream) { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + private void requestAwakenInternal() { + // Treat an explicit request to awaken as user activity so that the + // device doesn't immediately go to sleep if the timeout expired, + // for example when being undocked. + long time = SystemClock.uptimeMillis(); + mPowerManager.userActivity(time, false /*noChangeLights*/); + stopDreamInternal(); + } - if (dream == null) { - throw new IllegalArgumentException("dream must not be null"); + private void finishSelfInternal(IBinder token) { + if (DEBUG) { + Slog.d(TAG, "Dream finished: " + token); } - final int callingUserId = UserHandle.getCallingUserId(); - final int currentUserId = ActivityManager.getCurrentUser(); - if (callingUserId != currentUserId) { - // This check is inherently prone to races but at least it's something. - Slog.w(TAG, "Aborted attempt to start a test dream while a different " - + " user is active: callingUserId=" + callingUserId - + ", currentUserId=" + currentUserId); - return; - } - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - startDreamLocked(dream, true /*isTest*/, callingUserId); + // Note that a dream finishing and self-terminating is not + // itself considered user activity. If the dream is ending because + // the user interacted with the device then user activity will already + // have been poked so the device will stay awake a bit longer. + // If the dream is ending on its own for other reasons and no wake + // locks are held and the user activity timeout has expired then the + // device may simply go to sleep. + synchronized (mLock) { + if (mCurrentDreamToken == token) { + stopDreamLocked(); } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override // Binder call - public void awaken() { - checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); - - final long ident = Binder.clearCallingIdentity(); - try { - // Treat an explicit request to awaken as user activity so that the - // device doesn't immediately go to sleep if the timeout expired, - // for example when being undocked. - long time = SystemClock.uptimeMillis(); - mPowerManager.userActivity(time, false /*noChangeLights*/); - stopDream(); - } finally { - Binder.restoreCallingIdentity(ident); } } - @Override // Binder call - public void finishSelf(IBinder token) { - // Requires no permission, called by Dream from an arbitrary process. - if (token == null) { - throw new IllegalArgumentException("token must not be null"); - } - - final long ident = Binder.clearCallingIdentity(); - try { - if (DEBUG) { - Slog.d(TAG, "Dream finished: " + token); - } - - // Note that a dream finishing and self-terminating is not - // itself considered user activity. If the dream is ending because - // the user interacted with the device then user activity will already - // have been poked so the device will stay awake a bit longer. - // If the dream is ending on its own for other reasons and no wake - // locks are held and the user activity timeout has expired then the - // device may simply go to sleep. - synchronized (mLock) { - if (mCurrentDreamToken == token) { - stopDreamLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(ident); + private void testDreamInternal(ComponentName dream, int userId) { + synchronized (mLock) { + startDreamLocked(dream, true /*isTest*/, userId); } } - /** - * Called by the power manager to start a dream. - */ - public void startDream() { + private void startDreamInternal() { int userId = ActivityManager.getCurrentUser(); ComponentName dream = chooseDreamForUser(userId); if (dream != null) { @@ -271,10 +177,7 @@ public final class DreamManagerService extends IDreamManager.Stub { } } - /** - * Called by the power manager to stop a dream. - */ - public void stopDream() { + private void stopDreamInternal() { synchronized (mLock) { stopDreamLocked(); } @@ -305,7 +208,7 @@ public final class DreamManagerService extends IDreamManager.Stub { // fallback to the default dream component if necessary if (validComponents.isEmpty()) { - ComponentName defaultDream = getDefaultDreamComponent(); + ComponentName defaultDream = getDefaultDreamComponentForUser(userId); if (defaultDream != null) { Slog.w(TAG, "Falling back to default dream " + defaultDream); validComponents.add(defaultDream); @@ -314,6 +217,20 @@ public final class DreamManagerService extends IDreamManager.Stub { return validComponents.toArray(new ComponentName[validComponents.size()]); } + private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.SCREENSAVER_COMPONENTS, + componentsToString(componentNames), + userId); + } + + private ComponentName getDefaultDreamComponentForUser(int userId) { + String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), + Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, + userId); + return name == null ? null : ComponentName.unflattenFromString(name); + } + private boolean serviceExists(ComponentName name) { try { return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null; @@ -423,4 +340,155 @@ public final class DreamManagerService extends IDreamManager.Stub { super(looper, null, true /*async*/); } } + + private final class BinderService extends IDreamManager.Stub { + @Override // Binder call + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DreamManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public ComponentName[] getDreamComponents() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + return getDreamComponentsForUser(userId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void setDreamComponents(ComponentName[] componentNames) { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + setDreamComponentsForUser(userId, componentNames); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public ComponentName getDefaultDreamComponent() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final int userId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + return getDefaultDreamComponentForUser(userId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public boolean isDreaming() { + checkPermission(android.Manifest.permission.READ_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + return isDreamingInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void dream() { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + requestDreamInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void testDream(ComponentName dream) { + if (dream == null) { + throw new IllegalArgumentException("dream must not be null"); + } + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final int callingUserId = UserHandle.getCallingUserId(); + final int currentUserId = ActivityManager.getCurrentUser(); + if (callingUserId != currentUserId) { + // This check is inherently prone to races but at least it's something. + Slog.w(TAG, "Aborted attempt to start a test dream while a different " + + " user is active: callingUserId=" + callingUserId + + ", currentUserId=" + currentUserId); + return; + } + final long ident = Binder.clearCallingIdentity(); + try { + testDreamInternal(dream, callingUserId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void awaken() { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + requestAwakenInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public void finishSelf(IBinder token) { + // Requires no permission, called by Dream from an arbitrary process. + if (token == null) { + throw new IllegalArgumentException("token must not be null"); + } + + final long ident = Binder.clearCallingIdentity(); + try { + finishSelfInternal(token); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + private final class LocalService extends DreamManagerInternal { + @Override + public void startDream() { + startDreamInternal(); + } + + @Override + public void stopDream() { + stopDreamInternal(); + } + + @Override + public boolean isDreaming() { + return isDreamingInternal(); + } + } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9606baa8d1f5..3dec23471ce4 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -20,12 +20,12 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.server.BatteryService; import com.android.server.EventLogTags; +import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.lights.Light; import com.android.server.lights.LightsManager; import com.android.server.twilight.TwilightManager; import com.android.server.Watchdog; -import com.android.server.dreams.DreamManagerService; import android.Manifest; import android.content.BroadcastReceiver; @@ -57,6 +57,7 @@ import android.os.SystemService; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; +import android.service.dreams.DreamManagerInternal; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -181,7 +182,7 @@ public final class PowerManagerService extends com.android.server.SystemService private DisplayPowerController mDisplayPowerController; private WirelessChargerDetector mWirelessChargerDetector; private SettingsObserver mSettingsObserver; - private DreamManagerService mDreamManager; + private DreamManagerInternal mDreamManager; private Light mAttentionLight; private final Object mLock = new Object(); @@ -433,10 +434,10 @@ public final class PowerManagerService extends com.android.server.SystemService } } - public void systemReady(TwilightManager twilight, DreamManagerService dreamManager) { + public void systemReady() { synchronized (mLock) { mSystemReady = true; - mDreamManager = dreamManager; + mDreamManager = LocalServices.getService(DreamManagerInternal.class); PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting(); @@ -454,7 +455,8 @@ public final class PowerManagerService extends com.android.server.SystemService // The display power controller runs on the power manager service's // own handler thread to ensure timely operation. mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(), - mContext, mNotifier, mLightsManager, twilight, sensorManager, + mContext, mNotifier, mLightsManager, + LocalServices.getService(TwilightManager.class), sensorManager, mDisplaySuspendBlocker, mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f941ffeb502a..dfcdb9a8c931 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -75,7 +75,6 @@ import com.android.server.power.ShutdownThread; import com.android.server.search.SearchManagerService; import com.android.server.statusbar.StatusBarManagerService; import com.android.server.storage.DeviceStorageMonitorService; -import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightService; import com.android.server.usb.UsbService; import com.android.server.wallpaper.WallpaperManagerService; @@ -307,7 +306,6 @@ public final class SystemServer { DockObserver dock = null; UsbService usb = null; SerialService serial = null; - TwilightManager twilight = null; RecognitionManagerService recognition = null; NetworkTimeUpdateService networkTimeUpdater = null; CommonTimeManagementService commonTimeMgmtService = null; @@ -464,7 +462,6 @@ public final class SystemServer { CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; LockSettingsService lockSettings = null; - DreamManagerService dreamy = null; AssetAtlasService atlas = null; MediaRouterService mediaRouter = null; @@ -783,7 +780,6 @@ public final class SystemServer { } mSystemServiceManager.startService(TwilightService.class); - twilight = LocalServices.getService(TwilightManager.class); mSystemServiceManager.startService(UiModeManagerService.class); @@ -859,16 +855,10 @@ public final class SystemServer { } } - if (!disableNonCoreServices && - context.getResources().getBoolean(R.bool.config_dreamsSupported)) { - try { - Slog.i(TAG, "Dreams Service"); - // Dreams (interactive idle-time views, a/k/a screen savers) - dreamy = new DreamManagerService(context); - ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy); - } catch (Throwable e) { - reportWtf("starting DreamManagerService", e); - } + if (!disableNonCoreServices + && context.getResources().getBoolean(R.bool.config_dreamsSupported)) { + // Dreams (interactive idle-time views, a/k/a screen savers) + mSystemServiceManager.startService(DreamManagerService.class); } if (!disableNonCoreServices) { @@ -963,7 +953,7 @@ public final class SystemServer { try { // TODO: use boot phase - mPowerManagerService.systemReady(twilight, dreamy); + mPowerManagerService.systemReady(); } catch (Throwable e) { reportWtf("making Power Manager Service ready", e); } @@ -1000,7 +990,6 @@ public final class SystemServer { final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService; final TextServicesManagerService textServiceManagerServiceF = tsms; final StatusBarManagerService statusBarF = statusBar; - final DreamManagerService dreamyF = dreamy; final AssetAtlasService atlasF = atlas; final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; @@ -1113,11 +1102,6 @@ public final class SystemServer { reportWtf("Notifying TextServicesManagerService running", e); } try { - if (dreamyF != null) dreamyF.systemRunning(); - } catch (Throwable e) { - reportWtf("Notifying DreamManagerService running", e); - } - try { if (atlasF != null) atlasF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying AssetAtlasService running", e); -- 2.11.0