am 8a4c2bb1: am 567f7ca4: Refactor dream manager to new pattern.

* commit '8a4c2bb1f07cf1d971290a7310d7b71aceb71590':
  Refactor dream manager to new pattern.
This commit is contained in:
Jeff Brown
2014-02-14 09:41:38 +00:00
committed by Android Git Automerger
4 changed files with 274 additions and 181 deletions

View File

@ -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();
}

View File

@ -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);
private void testDreamInternal(ComponentName dream, int userId) {
synchronized (mLock) {
startDreamLocked(dream, true /*isTest*/, userId);
}
}
@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);
}
}
/**
* 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();
}
}
}

View File

@ -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);

View File

@ -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;
@ -1112,11 +1101,6 @@ public final class SystemServer {
} catch (Throwable e) {
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) {