Dream manager improvements.

- add reason for startDream(), which is logged and helpful for debugging
- consolidate attributes about the current dream into a dream record
  class
- update wake lock tags to use correct format

Bug: 252796782
Test: verified logs on device
Test: verified dreams still work correctly
Change-Id: Idad15d8e70764b4054aeaa72739069fa72cc868c
This commit is contained in:
Darrell Shi
2022-10-05 00:22:51 +00:00
parent 576b93c7fe
commit 402cb85a6f
2 changed files with 128 additions and 103 deletions

View File

@@ -118,7 +118,7 @@ final class DreamController {
public void startDream(Binder token, ComponentName name,
boolean isPreviewMode, boolean canDoze, int userId, PowerManager.WakeLock wakeLock,
ComponentName overlayComponentName) {
ComponentName overlayComponentName, String reason) {
stopDream(true /*immediate*/, "starting new dream");
Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
@@ -128,7 +128,7 @@ final class DreamController {
Slog.i(TAG, "Starting dream: name=" + name
+ ", isPreviewMode=" + isPreviewMode + ", canDoze=" + canDoze
+ ", userId=" + userId);
+ ", userId=" + userId + ", reason='" + reason + "'");
mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock);

View File

@@ -60,6 +60,7 @@ import android.util.Slog;
import android.view.Display;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.DumpUtils;
@@ -84,6 +85,9 @@ public final class DreamManagerService extends SystemService {
private static final boolean DEBUG = false;
private static final String TAG = "DreamManagerService";
private static final String DOZE_WAKE_LOCK_TAG = "dream:doze";
private static final String DREAM_WAKE_LOCK_TAG = "dream:dream";
private final Object mLock = new Object();
private final Context mContext;
@@ -98,17 +102,11 @@ public final class DreamManagerService extends SystemService {
private final ComponentName mAmbientDisplayComponent;
private final boolean mDismissDreamOnActivityStart;
private Binder mCurrentDreamToken;
private ComponentName mCurrentDreamName;
private int mCurrentDreamUserId;
private boolean mCurrentDreamIsPreview;
private boolean mCurrentDreamCanDoze;
private boolean mCurrentDreamIsDozing;
private boolean mCurrentDreamIsWaking;
@GuardedBy("mLock")
private DreamRecord mCurrentDream;
private boolean mForceAmbientDisplayEnabled;
private boolean mDreamsOnlyEnabledForSystemUser;
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
private final boolean mDreamsOnlyEnabledForSystemUser;
// A temporary dream component that, when present, takes precedence over user configured dream
// component.
@@ -116,7 +114,7 @@ public final class DreamManagerService extends SystemService {
private ComponentName mDreamOverlayServiceName;
private AmbientDisplayConfiguration mDozeConfig;
private final AmbientDisplayConfiguration mDozeConfig;
private final ActivityInterceptorCallback mActivityInterceptorCallback =
new ActivityInterceptorCallback() {
@Nullable
@@ -132,8 +130,14 @@ public final class DreamManagerService extends SystemService {
final boolean activityAllowed = activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_DREAM
|| activityType == ACTIVITY_TYPE_ASSISTANT;
if (mCurrentDreamToken != null && !mCurrentDreamIsWaking
&& !mCurrentDreamIsDozing && !activityAllowed) {
boolean shouldRequestAwaken;
synchronized (mLock) {
shouldRequestAwaken = mCurrentDream != null && !mCurrentDream.isWaking
&& !mCurrentDream.isDozing && !activityAllowed;
}
if (shouldRequestAwaken) {
requestAwakenInternal(
"stopping dream due to activity start: " + activityInfo.name);
}
@@ -149,7 +153,7 @@ public final class DreamManagerService extends SystemService {
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, DOZE_WAKE_LOCK_TAG);
mDozeConfig = new AmbientDisplayConfiguration(mContext);
mUiEventLogger = new UiEventLoggerImpl();
mDreamUiEventLogger = new DreamUiEventLoggerImpl(
@@ -197,43 +201,38 @@ public final class DreamManagerService extends SystemService {
}
private void dumpInternal(PrintWriter pw) {
pw.println("DREAM MANAGER (dumpsys dreams)");
pw.println();
pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
pw.println("mCurrentDreamName=" + mCurrentDreamName);
pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
pw.println("mCurrentDreamIsPreview=" + mCurrentDreamIsPreview);
pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking);
pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
pw.println("mCurrentDreamDozeScreenState="
+ Display.stateToString(mCurrentDreamDozeScreenState));
pw.println("mCurrentDreamDozeScreenBrightness=" + mCurrentDreamDozeScreenBrightness);
pw.println("getDozeComponent()=" + getDozeComponent());
pw.println();
synchronized (mLock) {
pw.println("DREAM MANAGER (dumpsys dreams)");
pw.println();
pw.println("mCurrentDream=" + mCurrentDream);
pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
pw.println("getDozeComponent()=" + getDozeComponent());
pw.println();
DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
@Override
public void dump(PrintWriter pw, String prefix) {
mController.dump(pw);
}
}, pw, "", 200);
DumpUtils.dumpAsync(mHandler, (pw1, prefix) -> mController.dump(pw1), pw, "", 200);
}
}
/** Whether a real dream is occurring. */
private boolean isDreamingInternal() {
synchronized (mLock) {
return mCurrentDreamToken != null && !mCurrentDreamIsPreview
&& !mCurrentDreamIsWaking;
return mCurrentDream != null && !mCurrentDream.isPreview
&& !mCurrentDream.isWaking;
}
}
/** Whether a doze is occurring. */
private boolean isDozingInternal() {
synchronized (mLock) {
return mCurrentDream != null && mCurrentDream.isDozing;
}
}
/** Whether a real dream, or a dream preview is occurring. */
private boolean isDreamingOrInPreviewInternal() {
synchronized (mLock) {
return mCurrentDreamToken != null && !mCurrentDreamIsWaking;
return mCurrentDream != null && !mCurrentDream.isWaking;
}
}
@@ -273,7 +272,7 @@ public final class DreamManagerService extends SystemService {
// locks are held and the user activity timeout has expired then the
// device may simply go to sleep.
synchronized (mLock) {
if (mCurrentDreamToken == token) {
if (mCurrentDream != null && mCurrentDream.token == token) {
stopDreamLocked(immediate, "finished self");
}
}
@@ -281,16 +280,17 @@ public final class DreamManagerService extends SystemService {
private void testDreamInternal(ComponentName dream, int userId) {
synchronized (mLock) {
startDreamLocked(dream, true /*isPreviewMode*/, false /*canDoze*/, userId);
startDreamLocked(dream, true /*isPreviewMode*/, false /*canDoze*/, userId,
"test dream" /*reason*/);
}
}
private void startDreamInternal(boolean doze) {
private void startDreamInternal(boolean doze, String reason) {
final int userId = ActivityManager.getCurrentUser();
final ComponentName dream = chooseDreamForUser(doze, userId);
if (dream != null) {
synchronized (mLock) {
startDreamLocked(dream, false /*isPreviewMode*/, doze, userId);
startDreamLocked(dream, false /*isPreviewMode*/, doze, userId, reason);
}
}
}
@@ -314,13 +314,13 @@ public final class DreamManagerService extends SystemService {
}
synchronized (mLock) {
if (mCurrentDreamToken == token && mCurrentDreamCanDoze) {
mCurrentDreamDozeScreenState = screenState;
mCurrentDreamDozeScreenBrightness = screenBrightness;
if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) {
mCurrentDream.dozeScreenState = screenState;
mCurrentDream.dozeScreenBrightness = screenBrightness;
mPowerManagerInternal.setDozeOverrideFromDreamManager(
screenState, screenBrightness);
if (!mCurrentDreamIsDozing) {
mCurrentDreamIsDozing = true;
if (!mCurrentDream.isDozing) {
mCurrentDream.isDozing = true;
mDozeWakeLock.acquire();
}
}
@@ -333,8 +333,8 @@ public final class DreamManagerService extends SystemService {
}
synchronized (mLock) {
if (mCurrentDreamToken == token && mCurrentDreamIsDozing) {
mCurrentDreamIsDozing = false;
if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.isDozing) {
mCurrentDream.isDozing = false;
mDozeWakeLock.release();
mPowerManagerInternal.setDozeOverrideFromDreamManager(
Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT);
@@ -403,7 +403,7 @@ public final class DreamManagerService extends SystemService {
ComponentName[] components = componentsFromString(names);
// first, ensure components point to valid services
List<ComponentName> validComponents = new ArrayList<ComponentName>();
List<ComponentName> validComponents = new ArrayList<>();
if (components != null) {
for (ComponentName component : components) {
if (validateDream(component)) {
@@ -439,8 +439,9 @@ public final class DreamManagerService extends SystemService {
mSystemDreamComponent = componentName;
// Switch dream if currently dreaming and not dozing.
if (isDreamingInternal() && !mCurrentDreamIsDozing) {
startDreamInternal(false);
if (isDreamingInternal() && !isDozingInternal()) {
startDreamInternal(false /*doze*/, (mSystemDreamComponent == null ? "clear" : "set")
+ " system dream component" /*reason*/);
}
}
}
@@ -478,13 +479,16 @@ public final class DreamManagerService extends SystemService {
}
}
@GuardedBy("mLock")
private void startDreamLocked(final ComponentName name,
final boolean isPreviewMode, final boolean canDoze, final int userId) {
if (!mCurrentDreamIsWaking
&& Objects.equals(mCurrentDreamName, name)
&& mCurrentDreamIsPreview == isPreviewMode
&& mCurrentDreamCanDoze == canDoze
&& mCurrentDreamUserId == userId) {
final boolean isPreviewMode, final boolean canDoze, final int userId,
final String reason) {
if (mCurrentDream != null
&& !mCurrentDream.isWaking
&& Objects.equals(mCurrentDream.name, name)
&& mCurrentDream.isPreview == isPreviewMode
&& mCurrentDream.canDoze == canDoze
&& mCurrentDream.userId == userId) {
Slog.i(TAG, "Already in target dream.");
return;
}
@@ -493,73 +497,60 @@ public final class DreamManagerService extends SystemService {
Slog.i(TAG, "Entering dreamland.");
final Binder newToken = new Binder();
mCurrentDreamToken = newToken;
mCurrentDreamName = name;
mCurrentDreamIsPreview = isPreviewMode;
mCurrentDreamCanDoze = canDoze;
mCurrentDreamUserId = userId;
mCurrentDream = new DreamRecord(name, userId, isPreviewMode, canDoze);
if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
// TODO(b/213906448): Remove when metrics based on new atom are fully rolled out.
mUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START);
mDreamUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START,
mCurrentDreamName.flattenToString());
mCurrentDream.name.flattenToString());
}
PowerManager.WakeLock wakeLock = mPowerManager
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DREAM_WAKE_LOCK_TAG);
final Binder dreamToken = mCurrentDream.token;
mHandler.post(wakeLock.wrap(() -> {
mAtmInternal.notifyDreamStateChanged(true);
mController.startDream(newToken, name, isPreviewMode, canDoze, userId, wakeLock,
mDreamOverlayServiceName);
mController.startDream(dreamToken, name, isPreviewMode, canDoze, userId, wakeLock,
mDreamOverlayServiceName, reason);
}));
}
@GuardedBy("mLock")
private void stopDreamLocked(final boolean immediate, String reason) {
if (mCurrentDreamToken != null) {
if (mCurrentDream != null) {
if (immediate) {
Slog.i(TAG, "Leaving dreamland.");
cleanupDreamLocked();
} else if (mCurrentDreamIsWaking) {
} else if (mCurrentDream.isWaking) {
return; // already waking
} else {
Slog.i(TAG, "Gently waking up from dream.");
mCurrentDreamIsWaking = true;
mCurrentDream.isWaking = true;
}
mHandler.post(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Performing gentle wake from dream.");
mController.stopDream(immediate, reason);
}
});
mHandler.post(() -> mController.stopDream(immediate, reason));
}
}
@GuardedBy("mLock")
private void cleanupDreamLocked() {
if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
mHandler.post(() -> mAtmInternal.notifyDreamStateChanged(false /*dreaming*/));
if (mCurrentDream == null) {
return;
}
if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
// TODO(b/213906448): Remove when metrics based on new atom are fully rolled out.
mUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_STOP);
mDreamUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_STOP,
mCurrentDreamName.flattenToString());
mCurrentDream.name.flattenToString());
}
mCurrentDreamToken = null;
mCurrentDreamName = null;
mCurrentDreamIsPreview = false;
mCurrentDreamCanDoze = false;
mCurrentDreamUserId = 0;
mCurrentDreamIsWaking = false;
if (mCurrentDreamIsDozing) {
mCurrentDreamIsDozing = false;
if (mCurrentDream.isDozing) {
mDozeWakeLock.release();
}
mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
mHandler.post(() -> {
mAtmInternal.notifyDreamStateChanged(false);
});
mCurrentDream = null;
}
private void checkPermission(String permission) {
@@ -606,7 +597,7 @@ public final class DreamManagerService extends SystemService {
@Override
public void onDreamStopped(Binder token) {
synchronized (mLock) {
if (mCurrentDreamToken == token) {
if (mCurrentDream != null && mCurrentDream.token == token) {
cleanupDreamLocked();
}
}
@@ -624,7 +615,7 @@ public final class DreamManagerService extends SystemService {
* Handler for asynchronous operations performed by the dream manager.
* Ensures operations to {@link DreamController} are single-threaded.
*/
private final class DreamHandler extends Handler {
private static final class DreamHandler extends Handler {
public DreamHandler(Looper looper) {
super(looper, null, true /*async*/);
}
@@ -866,12 +857,12 @@ public final class DreamManagerService extends SystemService {
private final class LocalService extends DreamManagerInternal {
@Override
public void startDream(boolean doze) {
startDreamInternal(doze);
startDreamInternal(doze, "dream manager request" /*reason*/);
}
@Override
public void stopDream(boolean immediate) {
stopDreamInternal(immediate, "requested stopDream");
stopDreamInternal(immediate, "dream manager request" /*reason*/);
}
@Override
@@ -890,13 +881,47 @@ public final class DreamManagerService extends SystemService {
}
}
private static final class DreamRecord {
public final Binder token = new Binder();
public final ComponentName name;
public final int userId;
public final boolean isPreview;
public final boolean canDoze;
public boolean isDozing = false;
public boolean isWaking = false;
public int dozeScreenState = Display.STATE_UNKNOWN;
public int dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
DreamRecord(ComponentName name, int userId, boolean isPreview, boolean canDoze) {
this.name = name;
this.userId = userId;
this.isPreview = isPreview;
this.canDoze = canDoze;
}
@Override
public String toString() {
return "DreamRecord{"
+ "token=" + token
+ ", name=" + name
+ ", userId=" + userId
+ ", isPreview=" + isPreview
+ ", canDoze=" + canDoze
+ ", isDozing=" + isDozing
+ ", isWaking=" + isWaking
+ ", dozeScreenState=" + dozeScreenState
+ ", dozeScreenBrightness=" + dozeScreenBrightness
+ '}';
}
}
private final Runnable mSystemPropertiesChanged = new Runnable() {
@Override
public void run() {
if (DEBUG) Slog.d(TAG, "System properties changed");
synchronized (mLock) {
if (mCurrentDreamName != null && mCurrentDreamCanDoze
&& !mCurrentDreamName.equals(getDozeComponent())) {
if (mCurrentDream != null && mCurrentDream.name != null && mCurrentDream.canDoze
&& !mCurrentDream.name.equals(getDozeComponent())) {
// May have updated the doze component, wake up
mPowerManager.wakeUp(SystemClock.uptimeMillis(),
"android.server.dreams:SYSPROP");