summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java20
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java20
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java6
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java6
-rw-r--r--services/companion/java/com/android/server/companion/association/AssociationDiskStore.java42
-rw-r--r--services/companion/java/com/android/server/companion/association/AssociationStore.java12
-rw-r--r--services/companion/java/com/android/server/companion/association/DisassociationProcessor.java21
-rw-r--r--services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java5
-rw-r--r--services/core/java/com/android/server/am/OWNERS4
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java26
-rw-r--r--services/core/java/com/android/server/am/ProcessStateRecord.java3
-rw-r--r--services/core/java/com/android/server/am/flags.aconfig7
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java18
-rw-r--r--services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java3
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java13
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig11
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java3
-rw-r--r--services/core/java/com/android/server/input/InputGestureManager.java5
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java2
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java25
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java56
-rw-r--r--services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java13
-rw-r--r--services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java6
-rw-r--r--services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java15
-rw-r--r--services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java9
-rw-r--r--services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java6
-rw-r--r--services/core/java/com/android/server/power/stats/processor/MultiStateStats.java5
-rw-r--r--services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java8
-rw-r--r--services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java8
-rw-r--r--services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java6
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java157
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java20
-rw-r--r--services/core/java/com/android/server/wm/PresentationController.java10
-rw-r--r--services/core/java/com/android/server/wm/Task.java12
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java3
-rw-r--r--services/core/java/com/android/server/wm/TrustedPresentationListenerController.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java39
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java9
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java107
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java2
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java13
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java13
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java102
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java5
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java5
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java106
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java7
58 files changed, 875 insertions, 322 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index 4fa0d506f09e..aa82df493f84 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -101,8 +101,15 @@ public class AutoclickController extends BaseEventStreamTransformation {
}
@Override
- public void toggleAutoclickPause() {
- // TODO(b/388872274): allows users to pause the autoclick.
+ public void toggleAutoclickPause(boolean paused) {
+ if (paused) {
+ if (mClickScheduler != null) {
+ mClickScheduler.cancel();
+ }
+ if (mAutoclickIndicatorScheduler != null) {
+ mAutoclickIndicatorScheduler.cancel();
+ }
+ }
}
};
@@ -133,7 +140,9 @@ public class AutoclickController extends BaseEventStreamTransformation {
mAutoclickIndicatorScheduler);
}
- handleMouseMotion(event, policyFlags);
+ if (!isPaused()) {
+ handleMouseMotion(event, policyFlags);
+ }
} else if (mClickScheduler != null) {
mClickScheduler.cancel();
}
@@ -216,6 +225,11 @@ public class AutoclickController extends BaseEventStreamTransformation {
}
}
+ private boolean isPaused() {
+ // TODO (b/397460424): Unpause when hovering over panel.
+ return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused();
+ }
+
/**
* Observes autoclick setting values, and updates ClickScheduler delay and indicator size
* whenever the setting value changes.
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
index 23c5cc4111f6..ba3e3d14b9c6 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
@@ -79,11 +79,20 @@ public class AutoclickTypePanel {
// An interface exposed to {@link AutoclickController) to handle different actions on the panel,
// including changing autoclick type, pausing/resuming autoclick.
public interface ClickPanelControllerInterface {
- // Allows users to change a different autoclick type.
+ /**
+ * Allows users to change a different autoclick type.
+ *
+ * @param clickType The new autoclick type to use. Should be one of the values defined in
+ * {@link AutoclickType}.
+ */
void handleAutoclickTypeChange(@AutoclickType int clickType);
- // Allows users to pause/resume the autoclick.
- void toggleAutoclickPause();
+ /**
+ * Allows users to pause or resume autoclick.
+ *
+ * @param paused {@code true} to pause autoclick, {@code false} to resume.
+ */
+ void toggleAutoclickPause(boolean paused);
}
private final Context mContext;
@@ -211,6 +220,10 @@ public class AutoclickTypePanel {
mWindowManager.removeView(mContentView);
}
+ public boolean isPaused() {
+ return mPaused;
+ }
+
/** Toggles the panel expanded or collapsed state. */
private void togglePanelExpansion(@AutoclickType int clickType) {
final LinearLayout button = getButtonFromClickType(clickType);
@@ -234,6 +247,7 @@ public class AutoclickTypePanel {
private void togglePause() {
mPaused = !mPaused;
+ mClickPanelController.toggleAutoclickPause(mPaused);
ImageButton imageButton = (ImageButton) mPauseButton.getChildAt(/* index= */ 0);
if (mPaused) {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 05301fdd8385..4f56483f487e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -31,6 +31,8 @@ import static android.os.UserHandle.getCallingUserId;
import static com.android.internal.util.CollectionUtils.any;
import static com.android.internal.util.Preconditions.checkState;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_API;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_PKG_DATA_CLEARED;
import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature;
import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed;
import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage;
@@ -250,7 +252,7 @@ public class CompanionDeviceManagerService extends SystemService {
+ packageName + "]. Cleaning up CDM data...");
for (AssociationInfo association : associationsForPackage) {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED);
}
mCompanionAppBinder.onPackageChanged(userId);
@@ -426,7 +428,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void disassociate(int associationId) {
- mDisassociationProcessor.disassociate(associationId);
+ mDisassociationProcessor.disassociate(associationId, REASON_API);
}
@Override
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index e7d1460aa66a..c5ac7c31b5c3 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -18,6 +18,8 @@ package com.android.server.companion;
import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_SHELL;
+
import android.companion.AssociationInfo;
import android.companion.ContextSyncMessage;
import android.companion.Flags;
@@ -122,7 +124,7 @@ class CompanionDeviceShellCommand extends ShellCommand {
if (association == null) {
out.println("Association doesn't exist.");
} else {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL);
}
}
break;
@@ -132,7 +134,7 @@ class CompanionDeviceShellCommand extends ShellCommand {
final List<AssociationInfo> userAssociations =
mAssociationStore.getAssociationsByUser(userId);
for (AssociationInfo association : userAssociations) {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL);
}
}
break;
diff --git a/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java b/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
index f2d019bde703..ce7dcd0fa1d4 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
@@ -58,6 +58,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@@ -164,6 +165,7 @@ public final class AssociationDiskStore {
private static final String FILE_NAME_LEGACY = "companion_device_manager_associations.xml";
private static final String FILE_NAME = "companion_device_manager.xml";
+ private static final String FILE_NAME_LAST_REMOVED_ASSOCIATION = "last_removed_association.txt";
private static final String XML_TAG_STATE = "state";
private static final String XML_TAG_ASSOCIATIONS = "associations";
@@ -268,6 +270,46 @@ public final class AssociationDiskStore {
}
}
+ /**
+ * Read the last removed association from disk.
+ */
+ public String readLastRemovedAssociation(@UserIdInt int userId) {
+ final AtomicFile file = createStorageFileForUser(
+ userId, FILE_NAME_LAST_REMOVED_ASSOCIATION);
+ StringBuilder sb = new StringBuilder();
+ int c;
+ try (FileInputStream fis = file.openRead()) {
+ while ((c = fis.read()) != -1) {
+ sb.append((char) c);
+ }
+ fis.close();
+ return sb.toString();
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "File " + file + " for user=" + userId + " doesn't exist.");
+ return null;
+ } catch (IOException e) {
+ Slog.e(TAG, "Can't read file " + file + " for user=" + userId);
+ return null;
+ }
+ }
+
+ /**
+ * Write the last removed association to disk.
+ */
+ public void writeLastRemovedAssociation(AssociationInfo association, String reason) {
+ Slog.i(TAG, "Writing last removed association=" + association.getId() + " to disk...");
+
+ final AtomicFile file = createStorageFileForUser(
+ association.getUserId(), FILE_NAME_LAST_REMOVED_ASSOCIATION);
+ writeToFileSafely(file, out -> {
+ out.write(String.valueOf(System.currentTimeMillis()).getBytes());
+ out.write(' ');
+ out.write(reason.getBytes());
+ out.write(' ');
+ out.write(association.toString().getBytes());
+ });
+ }
+
@NonNull
private static Associations readAssociationsFromFile(@UserIdInt int userId,
@NonNull AtomicFile file, @NonNull String rootTag) {
diff --git a/services/companion/java/com/android/server/companion/association/AssociationStore.java b/services/companion/java/com/android/server/companion/association/AssociationStore.java
index 757abd927ac8..f70c434e6b46 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationStore.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationStore.java
@@ -276,7 +276,7 @@ public class AssociationStore {
/**
* Remove an association.
*/
- public void removeAssociation(int id) {
+ public void removeAssociation(int id, String reason) {
Slog.i(TAG, "Removing association id=[" + id + "]...");
final AssociationInfo association;
@@ -291,6 +291,8 @@ public class AssociationStore {
writeCacheToDisk(association.getUserId());
+ mDiskStore.writeLastRemovedAssociation(association, reason);
+
Slog.i(TAG, "Done removing association.");
}
@@ -525,6 +527,14 @@ public class AssociationStore {
out.append(" ").append(a.toString()).append('\n');
}
}
+
+ out.append("Last Removed Association:\n");
+ for (UserInfo user : mUserManager.getAliveUsers()) {
+ String lastRemovedAssociation = mDiskStore.readLastRemovedAssociation(user.id);
+ if (lastRemovedAssociation != null) {
+ out.append(" ").append(lastRemovedAssociation).append('\n');
+ }
+ }
}
private void broadcastChange(@ChangeType int changeType, AssociationInfo association) {
diff --git a/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java b/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
index 150e8da5f614..248056f32a4f 100644
--- a/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
+++ b/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
@@ -47,6 +47,13 @@ import com.android.server.companion.transport.CompanionTransportManager;
@SuppressLint("LongLogTag")
public class DisassociationProcessor {
+ public static final String REASON_REVOKED = "revoked";
+ public static final String REASON_SELF_IDLE = "self-idle";
+ public static final String REASON_SHELL = "shell";
+ public static final String REASON_LEGACY = "legacy";
+ public static final String REASON_API = "api";
+ public static final String REASON_PKG_DATA_CLEARED = "pkg-data-cleared";
+
private static final String TAG = "CDM_DisassociationProcessor";
private static final String SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW =
@@ -94,7 +101,7 @@ public class DisassociationProcessor {
* Disassociate an association by id.
*/
// TODO: also revoke notification access
- public void disassociate(int id) {
+ public void disassociate(int id, String reason) {
Slog.i(TAG, "Disassociating id=[" + id + "]...");
final AssociationInfo association = mAssociationStore.getAssociationWithCallerChecks(id);
@@ -126,7 +133,7 @@ public class DisassociationProcessor {
// Association cleanup.
mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, id);
- mAssociationStore.removeAssociation(association.getId());
+ mAssociationStore.removeAssociation(association.getId(), reason);
// If role is not in use by other associations, revoke the role.
// Do not need to remove the system role since it was pre-granted by the system.
@@ -151,7 +158,7 @@ public class DisassociationProcessor {
}
/**
- * @deprecated Use {@link #disassociate(int)} instead.
+ * @deprecated Use {@link #disassociate(int, String)} instead.
*/
@Deprecated
public void disassociate(int userId, String packageName, String macAddress) {
@@ -165,7 +172,7 @@ public class DisassociationProcessor {
mAssociationStore.getAssociationWithCallerChecks(association.getId());
- disassociate(association.getId());
+ disassociate(association.getId(), REASON_LEGACY);
}
@SuppressLint("MissingPermission")
@@ -223,7 +230,7 @@ public class DisassociationProcessor {
Slog.i(TAG, "Removing inactive self-managed association=[" + association.toShortString()
+ "].");
- disassociate(id);
+ disassociate(id, REASON_SELF_IDLE);
}
}
@@ -234,7 +241,7 @@ public class DisassociationProcessor {
*
* Lastly remove the role holder for the revoked associations for the same packages.
*
- * @see #disassociate(int)
+ * @see #disassociate(int, String)
*/
private class OnPackageVisibilityChangeListener implements
ActivityManager.OnUidImportanceListener {
@@ -260,7 +267,7 @@ public class DisassociationProcessor {
int userId = UserHandle.getUserId(uid);
for (AssociationInfo association : mAssociationStore.getRevokedAssociations(userId,
packageName)) {
- disassociate(association.getId());
+ disassociate(association.getId(), REASON_REVOKED);
}
if (mAssociationStore.getRevokedAssociations().isEmpty()) {
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index d8e10f842665..7eb7072520de 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -365,7 +365,7 @@ public class ContextualSearchManagerService extends SystemService {
}
}
final ScreenshotHardwareBuffer shb = mWmInternal.takeContextualSearchScreenshot(
- (Flags.contextualSearchWindowLayer() ? csUid : -1));
+ (Flags.contextualSearchPreventSelfCapture() ? csUid : -1));
final Bitmap bm = shb != null ? shb.asBitmap() : null;
// Now that everything is fetched, putting it in the launchIntent.
if (bm != null) {
@@ -549,7 +549,7 @@ public class ContextualSearchManagerService extends SystemService {
Binder.withCleanCallingIdentity(() -> {
final ScreenshotHardwareBuffer shb =
mWmInternal.takeContextualSearchScreenshot(
- (Flags.contextualSearchWindowLayer() ? callingUid : -1));
+ (Flags.contextualSearchPreventSelfCapture() ? callingUid : -1));
final Bitmap bm = shb != null ? shb.asBitmap() : null;
if (bm != null) {
bundle.putParcelable(ContextualSearchManager.EXTRA_SCREENSHOT,
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index b677297dfef2..4bfee1d8398f 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1464,7 +1464,10 @@ public class CachedAppOptimizer {
void onProcessFrozen(ProcessRecord frozenProc) {
if (useCompaction()) {
synchronized (mProcLock) {
- compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false);
+ // only full-compact if process is cached
+ if (frozenProc.mState.getSetAdj() >= mCompactThrottleMinOomAdj) {
+ compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false);
+ }
}
}
frozenProc.onProcessFrozen();
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index cc6fabc8fd67..4b6d6bc955cc 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -68,7 +68,7 @@ per-file CarUserSwitchingDialog.java = file:platform/packages/services/Car:/OWNE
per-file ActivityManager* = file:/ACTIVITY_SECURITY_OWNERS
# Aconfig Flags
-per-file flags.aconfig = yamasani@google.com, bills@google.com, nalini@google.com
+per-file flags.aconfig = yamasani@google.com, nalini@google.com
# Londoners
michaelwr@google.com #{LAST_RESORT_SUGGESTION}
@@ -77,4 +77,4 @@ narayan@google.com #{LAST_RESORT_SUGGESTION}
# Default
yamasani@google.com
hackbod@google.com #{LAST_RESORT_SUGGESTION}
-omakoto@google.com #{LAST_RESORT_SUGGESTION} \ No newline at end of file
+omakoto@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 61c5501a7b5a..13d367a95942 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -446,6 +446,8 @@ public class OomAdjuster {
private static final int CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD =
Flags.raiseBoundUiServiceThreshold() ? SERVICE_ADJ : PERCEPTIBLE_APP_ADJ;
+ static final long PERCEPTIBLE_TASK_TIMEOUT_MILLIS = 5 * 60 * 1000;
+
@VisibleForTesting
public static class Injector {
boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1847,7 +1849,7 @@ public class OomAdjuster {
mHasVisibleActivities = false;
}
- void onOtherActivity() {
+ void onOtherActivity(long perceptibleTaskStoppedTimeMillis) {
if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
procState = PROCESS_STATE_CACHED_ACTIVITY;
mAdjType = "cch-act";
@@ -1856,6 +1858,28 @@ public class OomAdjuster {
"Raise procstate to cached activity: " + app);
}
}
+ if (Flags.perceptibleTasks() && adj > PERCEPTIBLE_MEDIUM_APP_ADJ) {
+ if (perceptibleTaskStoppedTimeMillis >= 0) {
+ final long now = mInjector.getUptimeMillis();
+ if (now - perceptibleTaskStoppedTimeMillis < PERCEPTIBLE_TASK_TIMEOUT_MILLIS) {
+ adj = PERCEPTIBLE_MEDIUM_APP_ADJ;
+ mAdjType = "perceptible-act";
+ if (procState > PROCESS_STATE_IMPORTANT_BACKGROUND) {
+ procState = PROCESS_STATE_IMPORTANT_BACKGROUND;
+ }
+
+ maybeSetProcessFollowUpUpdateLocked(app,
+ perceptibleTaskStoppedTimeMillis + PERCEPTIBLE_TASK_TIMEOUT_MILLIS,
+ now);
+ } else if (adj > PREVIOUS_APP_ADJ) {
+ adj = PREVIOUS_APP_ADJ;
+ mAdjType = "stale-perceptible-act";
+ if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+ procState = PROCESS_STATE_LAST_ACTIVITY;
+ }
+ }
+ }
+ }
mHasVisibleActivities = false;
}
}
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index b0f808b39053..25175e6bee5f 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -1120,7 +1120,8 @@ final class ProcessStateRecord {
} else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
callback.onStoppingActivity((flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0);
} else {
- callback.onOtherActivity();
+ final long ts = mApp.getWindowProcessController().getPerceptibleTaskStoppedTimeMillis();
+ callback.onOtherActivity(ts);
}
mCachedAdj = callback.adj;
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 27c384a22fb6..c8fedf3d1765 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -293,6 +293,13 @@ flag {
}
flag {
+ name: "perceptible_tasks"
+ namespace: "system_performance"
+ description: "Boost the oom_score_adj of activities in perceptible tasks"
+ bug: "370890207"
+}
+
+flag {
name: "expedite_activity_launch_on_cold_start"
namespace: "system_performance"
description: "Notify ActivityTaskManager of cold starts early to fix app launch behavior."
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 88f5c81231b8..c41b8db1ce75 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -333,7 +333,7 @@ public class AutomaticBrightnessController {
int ambientLightHorizonLong, float userLux, float userNits,
DisplayManagerFlags displayManagerFlags) {
mInjector = injector;
- mClock = injector.createClock(displayManagerFlags.offloadControlsDozeAutoBrightness());
+ mClock = injector.createClock();
mContext = context;
mCallbacks = callbacks;
mSensorManager = sensorManager;
@@ -1402,8 +1402,7 @@ public class AutomaticBrightnessController {
public void onSensorChanged(SensorEvent event) {
if (mLightSensorEnabled) {
// The time received from the sensor is in nano seconds, hence changing it to ms
- final long time = (mDisplayManagerFlags.offloadControlsDozeAutoBrightness())
- ? TimeUnit.NANOSECONDS.toMillis(event.timestamp) : mClock.uptimeMillis();
+ final long time = TimeUnit.NANOSECONDS.toMillis(event.timestamp);
final float lux = event.values[0];
handleLightSensorEvent(time, lux);
}
@@ -1616,20 +1615,13 @@ public class AutomaticBrightnessController {
}
private static class RealClock implements Clock {
- private final boolean mOffloadControlsDozeBrightness;
-
- RealClock(boolean offloadControlsDozeBrightness) {
- mOffloadControlsDozeBrightness = offloadControlsDozeBrightness;
- }
-
@Override
public long uptimeMillis() {
return SystemClock.uptimeMillis();
}
public long getSensorEventScaleTime() {
- return (mOffloadControlsDozeBrightness)
- ? SystemClock.elapsedRealtime() : uptimeMillis();
+ return SystemClock.elapsedRealtime();
}
}
@@ -1638,8 +1630,8 @@ public class AutomaticBrightnessController {
return BackgroundThread.getHandler();
}
- Clock createClock(boolean offloadControlsDozeBrightness) {
- return new RealClock(offloadControlsDozeBrightness);
+ Clock createClock() {
+ return new RealClock();
}
}
}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index 2c6f37448735..6510441ba28f 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -291,8 +291,7 @@ public class DisplayBrightnessStrategySelector {
void setAllowAutoBrightnessWhileDozing(
DisplayManagerInternal.DisplayOffloadSession displayOffloadSession) {
mAllowAutoBrightnessWhileDozing = mAllowAutoBrightnessWhileDozingConfig;
- if (mDisplayManagerFlags.offloadControlsDozeAutoBrightness()
- && mDisplayManagerFlags.isDisplayOffloadEnabled()
+ if (mDisplayManagerFlags.isDisplayOffloadEnabled()
&& displayOffloadSession != null) {
mAllowAutoBrightnessWhileDozing &= displayOffloadSession.allowAutoBrightnessInDoze();
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index e4b595ab7c55..c3057ded66eb 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -156,11 +156,6 @@ public class DisplayManagerFlags {
Flags.FLAG_DOZE_BRIGHTNESS_FLOAT,
Flags::dozeBrightnessFloat);
- private final FlagState mOffloadControlsDozeAutoBrightness = new FlagState(
- Flags.FLAG_OFFLOAD_CONTROLS_DOZE_AUTO_BRIGHTNESS,
- Flags::offloadControlsDozeAutoBrightness
- );
-
private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState(
Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT,
Flags::enablePeakRefreshRatePhysicalLimit
@@ -440,13 +435,6 @@ public class DisplayManagerFlags {
return mDozeBrightnessFloat.isEnabled();
}
- /**
- * @return Whether DisplayOffload should control auto-brightness in doze
- */
- public boolean offloadControlsDozeAutoBrightness() {
- return mOffloadControlsDozeAutoBrightness.isEnabled();
- }
-
public boolean isPeakRefreshRatePhysicalLimitEnabled() {
return mPeakRefreshRatePhysicalLimit.isEnabled();
}
@@ -647,7 +635,6 @@ public class DisplayManagerFlags {
pw.println(" " + mResolutionBackupRestore);
pw.println(" " + mUseFusionProxSensor);
pw.println(" " + mDozeBrightnessFloat);
- pw.println(" " + mOffloadControlsDozeAutoBrightness);
pw.println(" " + mPeakRefreshRatePhysicalLimit);
pw.println(" " + mIgnoreAppPreferredRefreshRate);
pw.println(" " + mSynthetic60hzModes);
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index acdc0e0cf891..f5451307afb7 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -255,17 +255,6 @@ flag {
}
flag {
- name: "offload_controls_doze_auto_brightness"
- namespace: "display_manager"
- description: "Allows the registered DisplayOffloader to control if auto-brightness is used in doze"
- bug: "327392714"
- is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "enable_peak_refresh_rate_physical_limit"
namespace: "display_manager"
description: "Flag for adding physical refresh rate limit if smooth display setting is on "
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 7e8bb28b6a37..2af74f620c95 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -569,7 +569,8 @@ public final class DreamManagerService extends SystemService {
}
private void requestDreamInternal() {
- if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()) {
+ if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()
+ && !isDozingInternal()) {
return;
}
diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java
index 977c029f3a29..d71c8a1056d9 100644
--- a/services/core/java/com/android/server/input/InputGestureManager.java
+++ b/services/core/java/com/android/server/input/InputGestureManager.java
@@ -146,11 +146,6 @@ final class InputGestureManager {
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL
),
createKeyGesture(
- KeyEvent.KEYCODE_N,
- KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES
- ),
- createKeyGesture(
KeyEvent.KEYCODE_S,
KeyEvent.META_META_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 508bc2f811e0..dfdd9e54fe2e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3485,7 +3485,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
|| (windowPerceptible != null && windowPerceptible == perceptible)) {
return;
}
- mFocusedWindowPerceptible.put(windowToken, windowPerceptible);
+ mFocusedWindowPerceptible.put(windowToken, perceptible);
updateSystemUiLocked(userId);
}
});
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 0fc182f3f1bb..fff812c038e7 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -42,6 +42,7 @@ import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_P
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+import static com.android.server.notification.PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE;
import static com.android.server.notification.PreferencesHelper.LockableAppFields.USER_LOCKED_PROMOTABLE;
import android.annotation.FlaggedApi;
@@ -286,7 +287,7 @@ public class PreferencesHelper implements RankingConfig {
if (!TAG_RANKING.equals(tag)) return;
final int xmlVersion = parser.getAttributeInt(null, ATT_VERSION, -1);
- boolean upgradeForBubbles = xmlVersion == XML_VERSION_BUBBLES_UPGRADE;
+ boolean upgradeForBubbles = xmlVersion >= XML_VERSION_BUBBLES_UPGRADE;
boolean migrateToPermission = (xmlVersion < XML_VERSION_NOTIF_PERMISSION);
if (mShowReviewPermissionsNotification
&& (xmlVersion < XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION)) {
@@ -337,15 +338,19 @@ public class PreferencesHelper implements RankingConfig {
}
boolean skipWarningLogged = false;
boolean skipGroupWarningLogged = false;
- boolean hasSAWPermission = false;
- if (upgradeForBubbles && uid != UNKNOWN_UID) {
- hasSAWPermission = mAppOps.noteOpNoThrow(
- OP_SYSTEM_ALERT_WINDOW, uid, name, null,
- "check-notif-bubble") == AppOpsManager.MODE_ALLOWED;
- }
- int bubblePref = hasSAWPermission
- ? BUBBLE_PREFERENCE_ALL
- : parser.getAttributeInt(null, ATT_ALLOW_BUBBLE, DEFAULT_BUBBLE_PREFERENCE);
+ int bubblePref = parser.getAttributeInt(null, ATT_ALLOW_BUBBLE,
+ DEFAULT_BUBBLE_PREFERENCE);
+ boolean bubbleLocked = (parser.getAttributeInt(null,
+ ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS) & USER_LOCKED_BUBBLE)
+ != 0;
+ if (!bubbleLocked
+ && upgradeForBubbles
+ && uid != UNKNOWN_UID
+ && mAppOps.noteOpNoThrow(OP_SYSTEM_ALERT_WINDOW, uid, name, null,
+ "check-notif-bubble") == AppOpsManager.MODE_ALLOWED) {
+ // User hasn't changed bubble pref & the app has SAW, so allow all bubbles.
+ bubblePref = BUBBLE_PREFERENCE_ALL;
+ }
int appImportance = parser.getAttributeInt(null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
// when data is loaded from disk it's loaded as USER_ALL, but restored data that
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 76c5240ab623..980fb155999e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1163,6 +1163,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private boolean shouldShowHub() {
+ final boolean hubEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
+ 1, mCurrentUserId) == 1;
+
+ return mUserManagerInternal != null && mUserManagerInternal.isUserUnlocked(mCurrentUserId)
+ && hubEnabled && mDreamManagerInternal.dreamConditionActive();
+ }
+
@VisibleForTesting
void powerPress(long eventTime, int count, int displayId) {
// SideFPS still needs to know about suppressed power buttons, in case it needs to block
@@ -1251,7 +1260,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
1, mCurrentUserId) == 1;
- if (mDreamManagerInternal.isDreaming() || isKeyguardShowing()) {
+ if ((mDreamManagerInternal != null && mDreamManagerInternal.isDreaming())
+ || isKeyguardShowing()) {
// If the device is already dreaming or on keyguard, go to sleep.
sleepDefaultDisplayFromPowerButton(eventTime, 0);
break;
@@ -1261,9 +1271,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// show hub.
boolean keyguardAvailable = !mLockPatternUtils.isLockScreenDisabled(
mCurrentUserId);
- if (mUserManagerInternal.isUserUnlocked(mCurrentUserId) && hubEnabled
- && keyguardAvailable && mDreamManagerInternal.dreamConditionActive()) {
- // If the hub can be launched, send a message to keyguard.
+ if (shouldShowHub() && keyguardAvailable) {
+ // If the hub can be launched, send a message to keyguard. We do not know if
+ // the hub is already running or not, keyguard handles turning screen off if
+ // it is.
Bundle options = new Bundle();
options.putBoolean(EXTRA_TRIGGER_HUB, true);
lockNow(options);
@@ -1324,14 +1335,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* @param isScreenOn Whether the screen is currently on.
* @param noDreamAction The action to perform if dreaming is not possible.
*/
- private void attemptToDreamFromShortPowerButtonPress(
+ private boolean attemptToDreamFromShortPowerButtonPress(
boolean isScreenOn, Runnable noDreamAction) {
if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP
&& mShortPressOnPowerBehavior != SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP) {
// If the power button behavior isn't one that should be able to trigger the dream, give
// up.
noDreamAction.run();
- return;
+ return false;
}
final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
@@ -1339,7 +1350,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
+ " press (isScreenOn=" + isScreenOn + ")");
noDreamAction.run();
- return;
+ return false;
}
synchronized (mLock) {
@@ -1350,6 +1361,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
dreamManagerInternal.requestDream();
+
+ return true;
}
/**
@@ -2327,6 +2340,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowWakeUpPolicy getWindowWakeUpPolicy() {
return new WindowWakeUpPolicy(mContext);
}
+
+ DreamManagerInternal getDreamManagerInternal() {
+ return LocalServices.getService(DreamManagerInternal.class);
+ }
}
/** {@inheritDoc} */
@@ -2345,7 +2362,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mInputManager = mContext.getSystemService(InputManager.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
+ mDreamManagerInternal = injector.getDreamManagerInternal();
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mSensorPrivacyManager = mContext.getSystemService(SensorPrivacyManager.class);
@@ -3701,15 +3718,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case KeyEvent.KEYCODE_N:
if (firstDown && event.isMetaPressed()) {
- if (event.isCtrlPressed()) {
- sendSystemKeyToStatusBarAsync(event);
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES);
- } else {
- toggleNotificationPanel();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
- }
+ toggleNotificationPanel();
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
return true;
}
break;
@@ -6398,6 +6409,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
event.getDisplayId(), event.getKeyCode(), "wakeUpFromWakeKey")) {
return;
}
+
+ if (!shouldShowHub()
+ && mShortPressOnPowerBehavior == SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP
+ && event.getKeyCode() == KEYCODE_POWER
+ && attemptToDreamFromShortPowerButtonPress(false, () -> {})) {
+ // In the case that we should wake to dream and successfully initiate dreaming, do not
+ // continue waking up. Doing so will exit the dream state and cause UI to react
+ // accordingly.
+ return;
+ }
+
wakeUpFromWakeKey(
event.getEventTime(),
event.getKeyCode(),
diff --git a/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
index 5eaaac9570d5..c89dddf45609 100644
--- a/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
@@ -274,12 +274,13 @@ abstract class BinaryStatePowerStatsProcessor extends PowerStatsProcessor {
int uid = uids.get(k);
if (stats.getUidStats(mTmpUidStatsArray, uid,
proportionalEstimate.stateValues)) {
- double power = intermediates.power
- * mStatsLayout.getUidUsageDuration(mTmpUidStatsArray)
- / intermediates.duration;
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues,
- mTmpUidStatsArray);
+ long duration = mStatsLayout.getUidUsageDuration(mTmpUidStatsArray);
+ if (duration != 0) {
+ double power = intermediates.power * duration / intermediates.duration;
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues,
+ mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
index 9e8b553dfe29..c1cd3acf1656 100644
--- a/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
@@ -299,8 +299,10 @@ class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
/ intermediates.txBytes;
}
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
index b442dc2655d4..ab2489c81449 100644
--- a/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
@@ -119,6 +119,8 @@ class CpuPowerStatsProcessor extends PowerStatsProcessor {
mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
mWakelockDescriptor = null;
+
+ initEnergyConsumerToPowerBracketMaps();
}
/**
@@ -157,9 +159,6 @@ class CpuPowerStatsProcessor extends PowerStatsProcessor {
if (mPlan == null) {
mPlan = new PowerEstimationPlan(stats.getConfig());
- if (mStatsLayout.getEnergyConsumerCount() != 0) {
- initEnergyConsumerToPowerBracketMaps();
- }
}
Intermediates intermediates = new Intermediates();
@@ -255,6 +254,10 @@ class CpuPowerStatsProcessor extends PowerStatsProcessor {
*/
private void initEnergyConsumerToPowerBracketMaps() {
int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+ if (energyConsumerCount == 0) {
+ return;
+ }
+
int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
mEnergyConsumerToCombinedEnergyConsumerMap = new int[energyConsumerCount];
@@ -545,8 +548,10 @@ class CpuPowerStatsProcessor extends PowerStatsProcessor {
power = Math.max(0, power - wakelockPowerEstimate);
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
index 05865e2074dd..76ea7e841106 100644
--- a/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
@@ -72,9 +72,12 @@ class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
int uid = uids.get(k);
if (stats.getUidStats(mTmpUidStatsArray, uid,
proportionalEstimate.stateValues)) {
- sLayout.setUidPowerEstimate(mTmpUidStatsArray,
- uCtoMah(sLayout.getUidConsumedEnergy(mTmpUidStatsArray, 0)));
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ double power = uCtoMah(sLayout.getUidConsumedEnergy(mTmpUidStatsArray, 0));
+ if (power != 0) {
+ sLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues,
+ mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
index c5db19bb3f32..a544daad82f1 100644
--- a/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
@@ -383,8 +383,10 @@ class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
/ intermediates.txPackets;
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
if (DEBUG) {
Slog.d(TAG, "UID: " + uid
diff --git a/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
index 28474a554b38..69325757c79d 100644
--- a/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
@@ -16,6 +16,7 @@
package com.android.server.power.stats.processor;
+import android.annotation.Nullable;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -333,9 +334,9 @@ class MultiStateStats {
/**
* Adds the delta to the metrics. The number of values must correspond to the dimension count
- * supplied to the Factory constructor
+ * supplied to the Factory constructor. Null values is equivalent to an array of zeros.
*/
- void increment(long[] values, long timestampMs) {
+ void increment(@Nullable long[] values, long timestampMs) {
mCounter.incrementValues(values, timestampMs);
mTracking = true;
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
index 33baad8cc441..f9b9da9171cb 100644
--- a/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
@@ -72,7 +72,6 @@ class PowerComponentAggregatedPowerStats {
private MultiStateStats mDeviceStats;
private final SparseArray<MultiStateStats> mStateStats = new SparseArray<>();
private final SparseArray<UidStats> mUidStats = new SparseArray<>();
- private long[] mZeroArray;
private static class UidStats {
public int[] states;
@@ -251,11 +250,8 @@ class PowerComponentAggregatedPowerStats {
for (int i = mUidStats.size() - 1; i >= 0; i--) {
PowerComponentAggregatedPowerStats.UidStats uidStats = mUidStats.valueAt(i);
if (!uidStats.updated && uidStats.stats != null) {
- if (mZeroArray == null
- || mZeroArray.length != mPowerStatsDescriptor.uidStatsArrayLength) {
- mZeroArray = new long[mPowerStatsDescriptor.uidStatsArrayLength];
- }
- uidStats.stats.increment(mZeroArray, timestampMs);
+ // Null stands for an array of zeros
+ uidStats.stats.increment(null, timestampMs);
}
uidStats.updated = false;
}
diff --git a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index 5a8e8b40bc3c..9df3d7eea27b 100644
--- a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -230,9 +230,11 @@ class ScreenPowerStatsProcessor extends PowerStatsProcessor {
int uid = uids.get(j);
if (stats.getUidStats(mTmpUidStatsArray, uid, uidStateValues)) {
long duration = mStatsLayout.getUidTopActivityDuration(mTmpUidStatsArray);
- double power = intermediates.power * duration / totalTopActivityDuration;
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, uidStateValues, mTmpUidStatsArray);
+ if (duration != 0) {
+ double power = intermediates.power * duration / totalTopActivityDuration;
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, uidStateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
index f1797bd2301d..8cc0b6eb6150 100644
--- a/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
@@ -375,8 +375,10 @@ class WifiPowerStatsProcessor extends PowerStatsProcessor {
/ intermediates.batchedScanDuration;
}
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
if (DEBUG) {
Slog.d(TAG, "UID: " + uid
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index f4da1bb332fb..75b1b202bcfd 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -61,6 +61,7 @@ import android.os.VibratorInfo;
import android.os.vibrator.Flags;
import android.os.vibrator.IVibrationSessionCallback;
import android.os.vibrator.PrebakedSegment;
+import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.os.vibrator.VibratorInfoFactory;
@@ -2672,7 +2673,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
CombinedVibration.ParallelCombination combination =
CombinedVibration.startParallel();
while ("-v".equals(getNextOption())) {
- int vibratorId = Integer.parseInt(getNextArgRequired());
+ int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
combination.addVibrator(vibratorId, nextEffect());
}
runVibrate(commonOptions, combination.combine());
@@ -2684,7 +2685,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
CombinedVibration.SequentialCombination combination =
CombinedVibration.startSequential();
while ("-v".equals(getNextOption())) {
- int vibratorId = Integer.parseInt(getNextArgRequired());
+ int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
combination.addNext(vibratorId, nextEffect());
}
runVibrate(commonOptions, combination.combine());
@@ -2709,7 +2710,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private int runHapticFeedback() {
CommonOptions commonOptions = new CommonOptions();
- int constant = Integer.parseInt(getNextArgRequired());
+ int constant = parseInt(getNextArgRequired(), "Expected haptic feedback constant id");
IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
: mShellCallbacksToken;
@@ -2757,12 +2758,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if ("-a".equals(nextOption)) {
hasAmplitude = true;
} else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
}
}
- long duration = Long.parseLong(getNextArgRequired());
- int amplitude = hasAmplitude ? Integer.parseInt(getNextArgRequired())
+ long duration = parseInt(getNextArgRequired(), "Expected one-shot duration millis");
+ int amplitude = hasAmplitude
+ ? parseInt(getNextArgRequired(), "Expected one-shot amplitude")
: VibrationEffect.DEFAULT_AMPLITUDE;
composition.addOffDuration(Duration.ofMillis(delay));
composition.addEffect(VibrationEffect.createOneShot(duration, amplitude));
@@ -2837,8 +2839,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
while ((nextOption = getNextOption()) != null) {
switch (nextOption) {
case "-a" -> isAdvanced = true;
- case "-i" -> initialSharpness = Float.parseFloat(getNextArgRequired());
- case "-r" -> repeat = Integer.parseInt(getNextArgRequired());
+ case "-i" -> initialSharpness = parseFloat(getNextArgRequired(),
+ "Expected initial sharpness after -i");
+ case "-r" -> repeat = parseInt(getNextArgRequired(),
+ "Expected repeat index after -r");
}
}
@@ -2864,8 +2868,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// nextArg is not a duration, finish reading.
break;
}
- intensity = Float.parseFloat(getNextArgRequired());
- sharpness = Float.parseFloat(getNextArgRequired());
+ intensity = parseFloat(getNextArgRequired(), "Expected envelope intensity");
+ sharpness = parseFloat(getNextArgRequired(), "Expected envelope sharpness");
builder.addControlPoint(intensity, sharpness, duration);
pos++;
}
@@ -2893,16 +2897,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
getNextArgRequired(); // consume "waveform"
String nextOption;
while ((nextOption = getNextOption()) != null) {
- if ("-a".equals(nextOption)) {
- hasAmplitudes = true;
- } else if ("-r".equals(nextOption)) {
- repeat = Integer.parseInt(getNextArgRequired());
- } else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
- } else if ("-f".equals(nextOption)) {
- hasFrequencies = true;
- } else if ("-c".equals(nextOption)) {
- isContinuous = true;
+ switch (nextOption) {
+ case "-a" -> hasAmplitudes = true;
+ case "-f" -> hasFrequencies = true;
+ case "-c" -> isContinuous = true;
+ case "-r" -> repeat = parseInt(getNextArgRequired(),
+ "Expected repeat index after -r");
+ case "-w" -> delay = parseInt(getNextArgRequired(),
+ "Expected delay millis after -w");
}
}
List<Integer> durations = new ArrayList<>();
@@ -2920,14 +2922,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
break;
}
if (hasAmplitudes) {
- amplitudes.add(
- Float.parseFloat(getNextArgRequired()) / VibrationEffect.MAX_AMPLITUDE);
+ int amplitude = parseInt(getNextArgRequired(), "Expected waveform amplitude");
+ amplitudes.add((float) amplitude / VibrationEffect.MAX_AMPLITUDE);
} else {
amplitudes.add(nextAmplitude);
nextAmplitude = 1 - nextAmplitude;
}
if (hasFrequencies) {
- frequencies.add(Float.parseFloat(getNextArgRequired()));
+ frequencies.add(
+ parseFloat(getNextArgRequired(), "Expected waveform frequency"));
}
}
@@ -2986,27 +2989,37 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if ("-b".equals(nextOption)) {
shouldFallback = true;
} else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
}
}
- int effectId = Integer.parseInt(getNextArgRequired());
+ int effectId = parseInt(getNextArgRequired(), "Expected prebaked effect id");
composition.addOffDuration(Duration.ofMillis(delay));
composition.addEffect(VibrationEffect.get(effectId, shouldFallback));
}
private void addPrimitivesToComposition(VibrationEffect.Composition composition) {
getNextArgRequired(); // consume "primitives"
- String nextArg;
- while ((nextArg = peekNextArg()) != null) {
+ while (peekNextArg() != null) {
int delay = 0;
- if ("-w".equals(nextArg)) {
- getNextArgRequired(); // consume "-w"
- delay = Integer.parseInt(getNextArgRequired());
- nextArg = peekNextArg();
+ float scale = 1f;
+ int delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
+
+ String nextOption;
+ while ((nextOption = getNextOption()) != null) {
+ if ("-s".equals(nextOption)) {
+ scale = parseFloat(getNextArgRequired(), "Expected scale after -s");
+ } else if ("-o".equals(nextOption)) {
+ delayType = VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET;
+ delay = parseInt(getNextArgRequired(), "Expected offset millis after -o");
+ } else if ("-w".equals(nextOption)) {
+ delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
+ }
}
try {
- composition.addPrimitive(Integer.parseInt(nextArg), /* scale= */ 1, delay);
+ String nextArg = peekNextArg(); // Just in case this is not a primitive.
+ composition.addPrimitive(Integer.parseInt(nextArg), scale, delay, delayType);
getNextArgRequired(); // consume the primitive id
} catch (NumberFormatException | NullPointerException e) {
// nextArg is not describing a primitive, leave it to be consumed by outer loops
@@ -3032,17 +3045,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
VibrationXmlParser.parseDocument(new StringReader(xml));
VibratorInfo combinedVibratorInfo = getCombinedVibratorInfo();
if (combinedVibratorInfo == null) {
- throw new IllegalStateException(
- "No combined vibrator info to parse vibration XML " + xml);
+ throw new IllegalStateException("No vibrator info available to parse XML");
}
VibrationEffect effect = parsedVibration.resolve(combinedVibratorInfo);
if (effect == null) {
- throw new IllegalArgumentException(
- "Parsed vibration cannot be resolved for vibration XML " + xml);
+ throw new IllegalArgumentException("Parsed XML cannot be resolved: " + xml);
}
return CombinedVibration.createParallel(effect);
} catch (IOException e) {
- throw new RuntimeException("Error parsing vibration XML " + xml, e);
+ throw new RuntimeException("Error parsing XML: " + xml, e);
}
}
@@ -3060,16 +3071,30 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
+ private static int parseInt(String text, String errorMessage) {
+ try {
+ return Integer.parseInt(text);
+ } catch (NumberFormatException | NullPointerException e) {
+ throw new IllegalArgumentException(errorMessage, e);
+ }
+ }
+
+ private static float parseFloat(String text, String errorMessage) {
+ try {
+ return Float.parseFloat(text);
+ } catch (NumberFormatException | NullPointerException e) {
+ throw new IllegalArgumentException(errorMessage, e);
+ }
+ }
+
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
pw.println("Vibrator Manager commands:");
pw.println(" help");
pw.println(" Prints this help text.");
- pw.println("");
pw.println(" list");
- pw.println(" Prints the id of device vibrators. This does not include any ");
- pw.println(" connected input device.");
+ pw.println(" Prints device vibrator ids; does not include input devices.");
pw.println(" synced [options] <effect>...");
pw.println(" Vibrates effect on all vibrators in sync.");
pw.println(" combined [options] (-v <vibrator-id> <effect>...)...");
@@ -3079,51 +3104,41 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
pw.println(" xml [options] <xml>");
pw.println(" Vibrates using combined vibration described in given XML string");
pw.println(" on all vibrators in sync. The XML could be:");
- pw.println(" XML containing a single effect, or");
- pw.println(" A vibration select XML containing multiple effects.");
- pw.println(" Vibrates using combined vibration described in given XML string.");
- pw.println(" XML containing a single effect it runs on all vibrators in sync.");
+ pw.println(" A single <vibration-effect>, or");
+ pw.println(" A <vibration-select> containing multiple effects.");
+ pw.println(" feedback [options] <constant>");
+ pw.println(" Performs a haptic feedback with the given constant.");
pw.println(" cancel");
pw.println(" Cancels any active vibration");
- pw.println(" feedback [-f] [-d <description>] <constant>");
- pw.println(" Performs a haptic feedback with the given constant.");
- pw.println(" The force (-f) option enables the `always` configuration, which");
- pw.println(" plays the haptic irrespective of the vibration intensity settings");
pw.println("");
pw.println("Effect commands:");
pw.println(" oneshot [-w delay] [-a] <duration> [<amplitude>]");
- pw.println(" Vibrates for duration milliseconds; ignored when device is on ");
- pw.println(" DND (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale amplitude.");
+ pw.println(" Vibrates for duration milliseconds.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -a is provided, the command accepts a second argument for ");
pw.println(" amplitude, in a scale of 1-255.");
pw.print(" waveform [-w delay] [-r index] [-a] [-f] [-c] ");
pw.println("(<duration> [<amplitude>] [<frequency>])...");
- pw.println(" Vibrates for durations and amplitudes in list; ignored when ");
- pw.println(" device is on DND (Do Not Disturb) mode; touch feedback strength ");
- pw.println(" user setting will be used to scale amplitude.");
+ pw.println(" Vibrates for durations and amplitudes in list.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -r is provided, the waveform loops back to the specified");
- pw.println(" index (e.g. 0 loops from the beginning)");
+ pw.println(" index (e.g. 0 loops from the beginning).");
pw.println(" If -a is provided, the command expects amplitude to follow each");
pw.println(" duration; otherwise, it accepts durations only and alternates");
- pw.println(" off/on");
+ pw.println(" off/on.");
pw.println(" If -f is provided, the command expects frequency to follow each");
- pw.println(" amplitude or duration; otherwise, it uses resonant frequency");
+ pw.println(" amplitude or duration; otherwise, it uses resonant frequency.");
pw.println(" If -c is provided, the waveform is continuous and will ramp");
pw.println(" between values; otherwise each entry is a fixed step.");
pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255;");
- pw.println(" frequency is an absolute value in hertz;");
+ pw.println(" frequency is an absolute value in hertz.");
pw.print(" envelope [-a] [-i initial sharpness] [-r index] ");
pw.println("[<duration1> <intensity1> <sharpness1>]...");
pw.println(" Generates a vibration pattern based on a series of duration, ");
pw.println(" intensity, and sharpness values. The total vibration time is ");
- pw.println(" the sum of all durations; Ignored when device is on ");
- pw.println(" DND (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale amplitude.");
+ pw.println(" the sum of all durations.");
pw.println(" If -a is provided, the waveform will use the advanced APIs to ");
pw.println(" generate the vibration pattern and the input parameters ");
pw.println(" become [<duration1> <amplitude1> <frequency1>].");
@@ -3132,19 +3147,20 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
pw.println(" If -r is provided, the waveform loops back to the specified index");
pw.println(" (e.g. 0 loops from the beginning).");
pw.println(" prebaked [-w delay] [-b] <effect-id>");
- pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale amplitude.");
+ pw.println(" Vibrates with prebaked effect.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -b is provided, the prebaked fallback effect will be played if");
pw.println(" the device doesn't support the given effect-id.");
- pw.println(" primitives ([-w delay] <primitive-id>)...");
- pw.println(" Vibrates with a composed effect; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale primitive intensities.");
+ pw.print(" primitives ([-w delay] [-o time] [-s scale]");
+ pw.println("<primitive-id> [<scale>])...");
+ pw.println(" Vibrates with a composed effect.");
pw.println(" If -w is provided, the next primitive will be played after the ");
pw.println(" specified wait time in milliseconds.");
+ pw.println(" If -o is provided, the next primitive will be played at the ");
+ pw.println(" specified start offset time in milliseconds.");
+ pw.println(" If -s is provided, the next primitive will be played with the");
+ pw.println(" specified amplitude scale, in a scale of [0,1].");
pw.println("");
pw.println("Common Options:");
pw.println(" -f");
@@ -3155,6 +3171,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
pw.println(" -d <description>");
pw.println(" Add description to the vibration.");
pw.println("");
+ pw.println("Notes");
+ pw.println(" Vibrations triggered by these commands will be ignored when");
+ pw.println(" device is on DND (Do Not Disturb) mode; notification strength");
+ pw.println(" user settings will be applied for scale.");
+ pw.println("");
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5b9dc654cc75..7b6d408fbe2c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -490,6 +490,7 @@ final class ActivityRecord extends WindowToken {
private long createTime = System.currentTimeMillis();
long lastVisibleTime; // last time this activity became visible
long pauseTime; // last time we started pausing the activity
+ long mStoppedTime; // last time we completely stopped the activity
long launchTickTime; // base time for launch tick messages
long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
// Last configuration reported to the activity in the client process.
@@ -6378,6 +6379,7 @@ final class ActivityRecord extends WindowToken {
Slog.w(TAG, "Exception thrown during pause", e);
// Just in case, assume it to be stopped.
mAppStopped = true;
+ mStoppedTime = SystemClock.uptimeMillis();
ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this);
setState(STOPPED, "stopIfPossible");
}
@@ -6411,6 +6413,7 @@ final class ActivityRecord extends WindowToken {
if (isStopping) {
ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this);
+ mStoppedTime = SystemClock.uptimeMillis();
setState(STOPPED, "activityStopped");
}
@@ -9572,7 +9575,18 @@ final class ActivityRecord extends WindowToken {
&& !mDisplayContent.isSleeping()) {
// Visibility of starting activities isn't calculated until pause-complete, so if
// this is not paused yet, don't consider it ready.
- return false;
+ // However, due to pip1 having an intermediate state, add a special exception here
+ // that skips waiting if the next activity is already visible.
+ final ActivityRecord toResume = isPip2ExperimentEnabled() ? null
+ : mDisplayContent.getActivity((r) -> !r.finishing
+ && r.isVisibleRequested()
+ && !r.isTaskOverlay()
+ && !r.isAlwaysOnTop());
+ if (toResume == null || !toResume.isVisible()) {
+ return false;
+ } else {
+ Slog.i(TAG, "Assuming sync-finish while pausing due to visible target");
+ }
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 37783781a901..6f83822ee97a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2130,6 +2130,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public boolean setTaskIsPerceptible(int taskId, boolean isPerceptible) {
+ enforceTaskPermission("setTaskIsPerceptible()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
+ MATCH_ATTACHED_TASK_ONLY);
+ if (task == null) {
+ Slog.w(TAG, "setTaskIsPerceptible: No task to set with id=" + taskId);
+ return false;
+ }
+ task.mIsPerceptible = isPerceptible;
+ }
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public boolean removeTask(int taskId) {
mAmInternal.enforceCallingPermission(REMOVE_TASKS, "removeTask()");
synchronized (mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/PresentationController.java b/services/core/java/com/android/server/wm/PresentationController.java
index 69463433827f..b3cff9c6cc3d 100644
--- a/services/core/java/com/android/server/wm/PresentationController.java
+++ b/services/core/java/com/android/server/wm/PresentationController.java
@@ -56,11 +56,6 @@ class PresentationController {
ProtoLog.v(WmProtoLogGroups.WM_DEBUG_PRESENTATION, "Presentation added to display %d: %s",
win.getDisplayId(), win);
mPresentingDisplayIds.add(win.getDisplayId());
- if (enablePresentationForConnectedDisplays()) {
- // A presentation hides all activities behind on the same display.
- win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
- /*notifyClients=*/ true);
- }
win.mWmService.mDisplayManagerInternal.onPresentation(displayId, /*isShown=*/ true);
}
@@ -76,11 +71,6 @@ class PresentationController {
if (displayIdIndex != -1) {
mPresentingDisplayIds.remove(displayIdIndex);
}
- if (enablePresentationForConnectedDisplays()) {
- // A presentation hides all activities behind on the same display.
- win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
- /*notifyClients=*/ true);
- }
win.mWmService.mDisplayManagerInternal.onPresentation(displayId, /*isShown=*/ false);
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bc4392e0dd0e..8e5e2f311489 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -503,6 +503,17 @@ class Task extends TaskFragment {
int mOffsetYForInsets;
/**
+ * When set to true, the task will be kept at a PERCEPTIBLE_APP_ADJ, and downgraded
+ * to PREVIOUS_APP_ADJ if not in foreground for a period of time.
+ * One example use case is for desktop form factors, where it is important keep tasks in the
+ * perceptible state (rather than cached where it may be frozen) when a user moves it to the
+ * foreground.
+ * On startup, restored Tasks will not be perceptible, until user actually interacts with it
+ * (i.e. brings it to the foreground)
+ */
+ boolean mIsPerceptible = false;
+
+ /**
* Whether the compatibility overrides that change the resizability of the app should be allowed
* for the specific app.
*/
@@ -3847,6 +3858,7 @@ class Task extends TaskFragment {
pw.print(ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
pw.print(" isResizeable="); pw.println(isResizeable());
+ pw.print(" isPerceptible="); pw.println(mIsPerceptible);
pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
pw.print(prefix); pw.println(" isTrimmable=" + mIsTrimmableFromRecents);
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 7854a4ada276..9d18d6c4cc89 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1884,7 +1884,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
if (!hasDirectChildActivities()) {
return false;
}
- if (mResumedActivity != null && mTransitionController.isTransientLaunch(mResumedActivity)) {
+ if (mResumedActivity != null && !mResumedActivity.finishing
+ && mTransitionController.isTransientLaunch(mResumedActivity)) {
// Even if the transient activity is occluded, defer pausing (addToStopping will still
// be called) it until the transient transition is done. So the current resuming
// activity won't need to wait for additional pause complete.
diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
index 242883612124..e612d8ec0ce6 100644
--- a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
+++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
@@ -20,6 +20,7 @@ import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_TPL;
@@ -35,6 +36,7 @@ import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Pair;
import android.util.Size;
+import android.util.SparseArray;
import android.view.InputWindowHandle;
import android.window.ITrustedPresentationListener;
import android.window.TrustedPresentationThresholds;
@@ -251,7 +253,7 @@ public class TrustedPresentationListenerController {
Rect tmpLogicalDisplaySize = new Rect();
Matrix tmpInverseMatrix = new Matrix();
float[] tmpMatrix = new float[9];
- Region coveredRegionsAbove = new Region();
+ SparseArray<Region> coveredRegionsAboveByDisplay = new SparseArray<>();
long currTimeMs = System.currentTimeMillis();
ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.first.length);
@@ -262,7 +264,7 @@ public class TrustedPresentationListenerController {
ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name);
continue;
}
- var displayFound = false;
+ int displayId = INVALID_DISPLAY;
tmpRectF.set(windowHandle.frame);
for (var displayHandle : mLastWindowHandles.second) {
if (displayHandle.mDisplayId == windowHandle.displayId) {
@@ -273,17 +275,18 @@ public class TrustedPresentationListenerController {
tmpLogicalDisplaySize.set(0, 0, displayHandle.mLogicalSize.getWidth(),
displayHandle.mLogicalSize.getHeight());
tmpRect.intersect(tmpLogicalDisplaySize);
- displayFound = true;
+ displayId = displayHandle.mDisplayId;
break;
}
}
- if (!displayFound) {
+ if (displayId == INVALID_DISPLAY) {
ProtoLog.v(WM_DEBUG_TPL, "Skipping %s, no associated display %d", windowHandle.name,
windowHandle.displayId);
continue;
}
+ Region coveredRegionsAbove = coveredRegionsAboveByDisplay.get(displayId, new Region());
var listeners = mRegisteredListeners.get(windowHandle.getWindowToken());
if (listeners != null) {
Region region = new Region();
@@ -304,6 +307,7 @@ public class TrustedPresentationListenerController {
}
coveredRegionsAbove.op(tmpRect, Region.Op.UNION);
+ coveredRegionsAboveByDisplay.put(displayId, coveredRegionsAbove);
ProtoLog.v(WM_DEBUG_TPL, "coveredRegionsAbove updated with %s frame:%s region:%s",
windowHandle.name, tmpRect.toShortString(), coveredRegionsAbove);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0b20911bcab2..8aed91b2dc66 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -157,6 +157,7 @@ import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY;
import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerServiceDumpProto.WINDOW_FRAMES_VALID;
import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.multiCrop;
import static com.android.window.flags.Flags.setScPropertiesInClient;
@@ -1820,8 +1821,28 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean hideSystemAlertWindows = shouldHideNonSystemOverlayWindow(win);
win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
- res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState,
- outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs);
+ // Only a presentation window needs a transition because its visibility affets the
+ // lifecycle of apps below (b/390481865).
+ if (enablePresentationForConnectedDisplays() && win.isPresentation()) {
+ Transition transition = null;
+ if (!win.mTransitionController.isCollecting()) {
+ transition = win.mTransitionController.createAndStartCollecting(TRANSIT_OPEN);
+ }
+ win.mTransitionController.collect(win.mToken);
+ res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState,
+ outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs);
+ // A presentation hides all activities behind on the same display.
+ win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
+ /*notifyClients=*/ true);
+ win.mTransitionController.getCollectingTransition().setReady(win.mToken, true);
+ if (transition != null) {
+ win.mTransitionController.requestStartTransition(transition, null,
+ null /* remoteTransition */, null /* displayChange */);
+ }
+ } else {
+ res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState,
+ outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs);
+ }
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 30dde543b9d4..b2d28a369edc 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -37,6 +37,7 @@ import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STARTED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
+import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
@@ -344,6 +345,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
*/
private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
+ /**
+ * The most recent timestamp of when one of this process's stopped activities in a
+ * perceptible task became stopped. Written by window manager and read by activity manager.
+ */
+ private volatile long mPerceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
+
public WindowProcessController(@NonNull ActivityTaskManagerService atm,
@NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
@NonNull WindowProcessListener listener) {
@@ -1228,6 +1235,17 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return mActivityStateFlags;
}
+ /**
+ * Returns the most recent timestamp when one of this process's stopped activities in a
+ * perceptible task became stopped. It should only be called if {@link #hasActivities}
+ * returns {@code true} and {@link #getActivityStateFlags} does not have any of
+ * the ACTIVITY_STATE_FLAG_IS_(VISIBLE|PAUSING_OR_PAUSED|STOPPING) bit set.
+ */
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
+ public long getPerceptibleTaskStoppedTimeMillis() {
+ return mPerceptibleTaskStoppedTimeMillis;
+ }
+
void computeProcessActivityState() {
// Since there could be more than one activities in a process record, we don't need to
// compute the OomAdj with each of them, just need to find out the activity with the
@@ -1239,6 +1257,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
int minTaskLayer = Integer.MAX_VALUE;
int stateFlags = 0;
int nonOccludedRatio = 0;
+ long perceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
final boolean wasResumed = hasResumedActivity();
final boolean wasAnyVisible = (mActivityStateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
@@ -1287,6 +1306,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
bestInvisibleState = STOPPING;
// Not "finishing" if any of activity isn't finishing.
allStoppingFinishing &= r.finishing;
+ } else if (bestInvisibleState == DESTROYED && r.isState(STOPPED)) {
+ if (task.mIsPerceptible) {
+ perceptibleTaskStoppedTimeMillis =
+ Long.max(r.mStoppedTime, perceptibleTaskStoppedTimeMillis);
+ }
}
}
}
@@ -1324,6 +1348,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
mActivityStateFlags = stateFlags;
+ mPerceptibleTaskStoppedTimeMillis = perceptibleTaskStoppedTimeMillis;
final boolean anyVisible = (stateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b13d510db159..bfedc90497ae 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -95,6 +95,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
+import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
@@ -182,6 +183,7 @@ import static com.android.server.wm.WindowStateProto.UNRESTRICTED_KEEP_CLEAR_ARE
import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.surfaceTrustedOverlay;
import android.annotation.CallSuper;
@@ -2286,11 +2288,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
dc.updateImeInputAndControlTarget(null);
}
- final int type = mAttrs.type;
-
- if (isPresentation()) {
- mWmService.mPresentationController.onPresentationRemoved(this);
- }
// Check if window provides non decor insets before clearing its provided insets.
final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
@@ -2431,11 +2428,33 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
- removeImmediately();
- mWmService.updateFocusedWindowLocked(isFocused()
- ? UPDATE_FOCUS_REMOVING_FOCUS
- : UPDATE_FOCUS_NORMAL,
- true /*updateInputWindows*/);
+ // Only a presentation window needs a transition because its visibility affets the
+ // lifecycle of apps below (b/390481865).
+ if (enablePresentationForConnectedDisplays() && isPresentation()) {
+ Transition transition = null;
+ if (!mTransitionController.isCollecting()) {
+ transition = mTransitionController.createAndStartCollecting(TRANSIT_CLOSE);
+ }
+ mTransitionController.collect(mToken);
+ mAnimatingExit = true;
+ mRemoveOnExit = true;
+ mToken.setVisibleRequested(false);
+ mWmService.mPresentationController.onPresentationRemoved(this);
+ // A presentation hides all activities behind on the same display.
+ mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
+ /*notifyClients=*/ true);
+ mTransitionController.getCollectingTransition().setReady(mToken, true);
+ if (transition != null) {
+ mTransitionController.requestStartTransition(transition, null,
+ null /* remoteTransition */, null /* displayChange */);
+ }
+ } else {
+ removeImmediately();
+ mWmService.updateFocusedWindowLocked(isFocused()
+ ? UPDATE_FOCUS_REMOVING_FOCUS
+ : UPDATE_FOCUS_NORMAL,
+ true /*updateInputWindows*/);
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 191c21e661d0..aee32a0473a3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -423,6 +423,7 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.hardware.usb.UsbManager;
+import android.health.connect.HealthConnectManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
@@ -2149,6 +2150,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
mBackgroundHandler = BackgroundThread.getHandler();
+ // Add the health permission to the list of restricted permissions.
+ if (android.permission.flags.Flags.replaceBodySensorPermissionEnabled()) {
+ Set<String> healthPermissions = HealthConnectManager.getHealthPermissions(mContext);
+ for (String permission : healthPermissions) {
+ SENSOR_PERMISSIONS.add(permission);
+ }
+ }
+
// Needed when mHasFeature == false, because it controls the certificate warning text.
mCertificateMonitor = new CertificateMonitor(this, mInjector, mBackgroundHandler);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 7d25acd7f5e7..a42116351c2d 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -152,7 +152,7 @@ public class AutomaticBrightnessControllerTest {
}
@Override
- AutomaticBrightnessController.Clock createClock(boolean isEnabled) {
+ AutomaticBrightnessController.Clock createClock() {
return new AutomaticBrightnessController.Clock() {
@Override
public long uptimeMillis() {
@@ -618,39 +618,46 @@ public class AutomaticBrightnessControllerTest {
long increment = 500;
// set autobrightness to low
// t = 0
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
// t = 500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
// t = 1000
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 1500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 2000
// ensure that our reading is at 0.
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 2500
// first 10000 lux sensor event reading
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 3000
// lux reading should still not yet be 10000.
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
@@ -659,45 +666,53 @@ public class AutomaticBrightnessControllerTest {
// lux has been high (10000) for 1000ms.
// lux reading should be 10000
// short horizon (ambient lux) is high, long horizon is still not high
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 4000
// stay high
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 4500
Mockito.clearInvocations(mBrightnessMappingStrategy);
mClock.fastForward(increment);
// short horizon is high, long horizon is high too
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
verify(mBrightnessMappingStrategy, times(1)).getBrightness(10000, null, -1);
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 5000
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 5500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 6000
mClock.fastForward(increment);
// ambient lux goes to 0
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// only the values within the horizon should be kept
assertArrayEquals(new float[] {10000, 10000, 0, 0, 0}, mController.getLastSensorValues(),
EPSILON);
- assertArrayEquals(new long[] {4000, 4500, 5000, 5500, 6000},
+ assertArrayEquals(new long[]{4000 + ANDROID_SLEEP_TIME, 4500 + ANDROID_SLEEP_TIME,
+ 5000 + ANDROID_SLEEP_TIME, 5500 + ANDROID_SLEEP_TIME,
+ 6000 + ANDROID_SLEEP_TIME},
mController.getLastSensorTimestamps());
}
@@ -793,7 +808,8 @@ public class AutomaticBrightnessControllerTest {
for (int i = 0; i < 1000; i++) {
lux += increment;
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment + 1);
@@ -807,17 +823,17 @@ public class AutomaticBrightnessControllerTest {
long sensorTimestamp = mClock.now();
for (int i = valuesCount - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
- assertEquals(sensorTimestamp, sensorTimestamps[i]);
+ assertEquals(sensorTimestamp + ANDROID_SLEEP_TIME, sensorTimestamps[i]);
lux -= increment;
sensorTimestamp -= increment;
}
assertEquals(lux, sensorValues[0], EPSILON);
- assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
+ assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG + ANDROID_SLEEP_TIME,
+ sensorTimestamps[0]);
}
@Test
public void testAmbientLuxBuffers_prunedBeyondLongHorizonExceptLatestValue() throws Exception {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
@@ -867,7 +883,8 @@ public class AutomaticBrightnessControllerTest {
for (int i = 0; i < 20; i++) {
lux += increment1;
mClock.fastForward(increment1);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment1 + 1);
@@ -877,7 +894,8 @@ public class AutomaticBrightnessControllerTest {
for (int i = 0; i < initialCapacity - valuesCount; i++) {
lux += increment2;
mClock.fastForward(increment2);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
float[] sensorValues = mController.getLastSensorValues();
@@ -890,7 +908,7 @@ public class AutomaticBrightnessControllerTest {
long sensorTimestamp = mClock.now();
for (int i = initialCapacity - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
- assertEquals(sensorTimestamp, sensorTimestamps[i]);
+ assertEquals(sensorTimestamp + ANDROID_SLEEP_TIME, sensorTimestamps[i]);
if (i >= valuesCount) {
lux -= increment2;
@@ -901,7 +919,8 @@ public class AutomaticBrightnessControllerTest {
}
}
assertEquals(lux, sensorValues[0], EPSILON);
- assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
+ assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG + ANDROID_SLEEP_TIME,
+ sensorTimestamps[0]);
}
@Test
@@ -951,25 +970,29 @@ public class AutomaticBrightnessControllerTest {
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1000
// Lux isn't steady yet
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux is steady now
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
}
@@ -992,25 +1015,29 @@ public class AutomaticBrightnessControllerTest {
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2000
// Lux isn't steady yet
mClock.fastForward(2000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 4500
// Lux is steady now
mClock.fastForward(2000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
}
@@ -1031,19 +1058,22 @@ public class AutomaticBrightnessControllerTest {
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1500
// Lux is steady now
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
}
@@ -1068,19 +1098,22 @@ public class AutomaticBrightnessControllerTest {
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 1000
// Lux isn't steady yet
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux is steady now
mClock.fastForward(1500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index aed1f9858660..db94958f769e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1066,7 +1066,6 @@ public final class DisplayPowerControllerTest {
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
@@ -1172,7 +1171,6 @@ public final class DisplayPowerControllerTest {
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(false);
mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index 2ebb6c2a3ce4..ef39167dbabc 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -240,7 +240,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void selectStrategyDoesNotSelectDozeStrategyWhenOffloadSessionAutoBrightnessIsEnabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -378,7 +377,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void selectStrategy_selectsAutomaticStrategyWhenValid() {
when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -409,7 +407,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void selectStrategy_doesNotSelectAutomaticStrategyWhenStylusInUse() {
when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -536,7 +533,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void setAllowAutoBrightnessWhileDozing_enabledWhenConfigAndOffloadSessionAreEnabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -550,7 +546,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void setAllowAutoBrightnessWhileDozing_disabledWhenOffloadSessionFlagIsDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(false);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -564,7 +559,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void setAllowAutoBrightnessWhileDozing_disabledWhenABWhileDozingConfigIsDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -588,7 +582,6 @@ public final class DisplayBrightnessStrategySelectorTest {
@Test
public void setAllowAutoBrightnessWhileDozing_EnabledWhenFlagsAreDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
true);
mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
@@ -600,11 +593,5 @@ public final class DisplayBrightnessStrategySelectorTest {
mDisplayBrightnessStrategySelector
.setAllowAutoBrightnessWhileDozing(mDisplayOffloadSession);
assertTrue(mDisplayBrightnessStrategySelector.isAllowAutoBrightnessWhileDozing());
-
- when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(false);
- mDisplayBrightnessStrategySelector
- .setAllowAutoBrightnessWhileDozing(mDisplayOffloadSession);
- assertTrue(mDisplayBrightnessStrategySelector.isAllowAutoBrightnessWhileDozing());
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index fa5847560782..4b53f1309337 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -23,18 +23,11 @@ import static com.android.server.am.ActivityManagerService.Injector;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal.FrozenProcessListener;
import android.content.ComponentName;
import android.content.Context;
@@ -44,14 +37,12 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.MessageQueue;
import android.os.Process;
-import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.internal.annotations.GuardedBy;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.modules.utils.testing.TestableDeviceConfig;
import com.android.server.LocalServices;
@@ -68,11 +59,9 @@ import org.mockito.Mock;
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -164,7 +153,7 @@ public final class CachedAppOptimizerTest {
app.info.uid = packageUid;
// Exact value does not mater, it can be any state for which compaction is allowed.
app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
- app.mState.setSetAdj(899);
+ app.mState.setSetAdj(940);
app.mState.setCurAdj(940);
return app;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 1ef758cf192e..340115a7d465 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -3337,6 +3337,108 @@ public class MockingOomAdjusterTests {
followUpTimeCaptor.capture());
}
+ /**
+ * For Perceptible Tasks adjustment, this solely unit-tests OomAdjuster -> onOtherActivity()
+ */
+ @SuppressWarnings("GuardedBy")
+ @Test
+ @EnableFlags(Flags.FLAG_PERCEPTIBLE_TASKS)
+ public void testPerceptibleAdjustment() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+
+ long now = mInjector.getUptimeMillis();
+
+ // GIVEN: perceptible adjustment is NOT enabled (perceptible stop time is not set)
+ // EXPECT: zero adjustment
+ // TLDR: App is not set as a perceptible task and hence no oom_adj boosting.
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(-1);
+ assertEquals(CACHED_APP_MIN_ADJ, mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+
+ // GIVEN: perceptible adjustment is enabled (perceptible stop time is set) and
+ // elapsed time < PERCEPTIBLE_TASK_TIMEOUT
+ // EXPECT: adjustment to PERCEPTIBLE_MEDIUM_APP_ADJ
+ // TLDR: App is a perceptible task (e.g. opened from launcher) and has oom_adj boosting.
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mInjector.reset();
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(now);
+ assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ,
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+
+ // GIVEN: perceptible adjustment is enabled (perceptible stop time is set) and
+ // elapsed time > PERCEPTIBLE_TASK_TIMEOUT
+ // EXPECT: adjustment to PREVIOUS_APP_ADJ
+ // TLDR: App is a perceptible task (e.g. opened from launcher) and has oom_adj boosting, but
+ // time has elapsed and has dropped to a lower boosting of PREVIOUS_APP_ADJ
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mInjector.jumpUptimeAheadTo(OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS + 1000);
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(0);
+ assertEquals(PREVIOUS_APP_ADJ, mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+ }
+
+ /**
+ * For Perceptible Tasks adjustment, this tests overall adjustment flow.
+ */
+ @SuppressWarnings("GuardedBy")
+ @Test
+ @EnableFlags(Flags.FLAG_PERCEPTIBLE_TASKS)
+ public void testUpdateOomAdjPerceptible() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ WindowProcessController wpc = app.getWindowProcessController();
+
+ // Set uptime to be at least the timeout time + buffer, so that we don't end up with
+ // negative stopTime in our test input
+ mInjector.jumpUptimeAheadTo(OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS + 60L * 1000L);
+ long now = mInjector.getUptimeMillis();
+ doReturn(true).when(wpc).hasActivities();
+
+ // GIVEN: perceptible adjustment is is enabled
+ // EXPECT: perceptible-act adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+ doReturn(now).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_IMPORTANT_BACKGROUND, PERCEPTIBLE_MEDIUM_APP_ADJ,
+ SCHED_GROUP_BACKGROUND, "perceptible-act");
+
+ // GIVEN: perceptible adjustment is is enabled and timeout has been reached
+ // EXPECT: stale-perceptible-act adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+
+ doReturn(now - OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS).when(
+ wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
+ SCHED_GROUP_BACKGROUND, "stale-perceptible-act");
+
+ // GIVEN: perceptible adjustment is is disabled
+ // EXPECT: no perceptible adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+ doReturn(Long.MIN_VALUE).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_CACHED_ACTIVITY, CACHED_APP_MIN_ADJ,
+ SCHED_GROUP_BACKGROUND, "cch-act");
+
+ // GIVEN: perceptible app is in foreground
+ // EXPECT: no perceptible adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_VISIBLE)
+ .when(wpc).getActivityStateFlags();
+ doReturn(now).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT, "vis-activity");
+ }
+
@SuppressWarnings("GuardedBy")
@Test
public void testUpdateOomAdj_DoAll_Multiple_Provider_Retention() {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
index 8fc8c9f677a6..6be9c6d4b80c 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
@@ -48,6 +48,7 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
@@ -121,7 +122,7 @@ public class BatteryUsageStatsProviderPerfTest {
}
@Test
- public void getBatteryUsageStats_accumulated() {
+ public void getBatteryUsageStats_accumulated() throws IOException {
BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
.setMaxStatsAgeMs(0)
.includePowerStateData()
@@ -155,6 +156,8 @@ public class BatteryUsageStatsProviderPerfTest {
// Verify that all iterations produce the same result
assertThat(cpuConsumedPower).isEqualTo(expectedCpuPower);
}
+ stats.close();
+
state.resumeTiming();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
index a232c0c7aec9..3b614bdb38ed 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
@@ -143,6 +143,8 @@ public class MultiStateStatsTest {
multiStateStats.increment(new long[]{200, 200}, 5000);
+ multiStateStats.increment(null, 6000); // No-op
+
long[] stats = new long[DIMENSION_COUNT];
multiStateStats.getStats(stats, new int[]{0, BatteryConsumer.PROCESS_STATE_FOREGROUND, 0});
// (400 - 100) * 0.5 + (600 - 400) * 0.5
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
index 7f60caaa569b..0745c68fd337 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.platform.test.annotations.DisableFlags;
@@ -400,6 +401,46 @@ public class AutoclickControllerTest {
.isNotEqualTo(initialScheduledTime);
}
+ @Test
+ @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+ public void pauseButton_flagOn_clickNotTriggeredWhenPaused() {
+ injectFakeMouseActionHoverMoveEvent();
+
+ // Pause autoclick.
+ AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(true);
+ mController.mAutoclickTypePanel = mockAutoclickTypePanel;
+
+ // Send hover move event.
+ MotionEvent hoverMove = MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 100,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 30f,
+ /* y= */ 0f,
+ /* metaState= */ 0);
+ hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+
+ // Verify there is not a pending click.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+
+ // Resume autoclick.
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(false);
+
+ // Send initial move event again. Because this is the first recorded move, a click won't be
+ // scheduled.
+ injectFakeMouseActionHoverMoveEvent();
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+
+ // Send move again to trigger click and verify there is now a pending click.
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1);
+ }
+
private void injectFakeMouseActionHoverMoveEvent() {
MotionEvent event = getFakeMotionHoverMoveEvent();
event.setSource(InputDevice.SOURCE_MOUSE);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
index f3016f4b17f9..ba672dcd299b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
@@ -68,6 +68,7 @@ public class AutoclickTypePanelTest {
private LinearLayout mPositionButton;
private @AutoclickType int mActiveClickType = AUTOCLICK_TYPE_LEFT_CLICK;
+ private boolean mPaused;
private final ClickPanelControllerInterface clickPanelController =
new ClickPanelControllerInterface() {
@@ -77,7 +78,9 @@ public class AutoclickTypePanelTest {
}
@Override
- public void toggleAutoclickPause() {}
+ public void toggleAutoclickPause(boolean paused) {
+ mPaused = paused;
+ }
};
@Before
@@ -199,6 +202,17 @@ public class AutoclickTypePanelTest {
}
}
+ @Test
+ public void pauseButton_onClick() {
+ mPauseButton.callOnClick();
+ assertThat(mPaused).isTrue();
+ assertThat(mAutoclickTypePanel.isPaused()).isTrue();
+
+ mPauseButton.callOnClick();
+ assertThat(mPaused).isFalse();
+ assertThat(mAutoclickTypePanel.isPaused()).isFalse();
+ }
+
private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) {
GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground();
assertThat(gradientDrawable.getColor().getDefaultColor())
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index e5fac7ac5e0c..00b0c558b4e3 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -263,6 +263,11 @@ public class DpmMockContext extends MockContext {
}
@Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
public PackageManager getPackageManager() {
return mMockSystemServices.packageManager;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 5dea44d6ebf4..67e85ff2445d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -4495,6 +4495,27 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testBubblePreference_sameVersionWithSAWPermission() throws Exception {
+ when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(),
+ anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED);
+
+ final String xml = "<ranking version=\"4\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\">\n"
+ + "<channel id=\"someId\" name=\"hi\""
+ + " importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertEquals(BUBBLE_PREFERENCE_ALL, mHelper.getBubblePreference(PKG_O, UID_O));
+ assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O));
+ }
+
+ @Test
public void testBubblePreference_upgradeWithSAWThenUserOverride() throws Exception {
when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(),
anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED);
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index 8e2cea7a8c78..6d8a48799112 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -244,9 +244,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
{"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyEvent.KEYCODE_L,
META_ON},
- {"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, KeyEvent.KEYCODE_N,
- META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN},
KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE,
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 32a3b7f2c9cc..22c86eb3a9b8 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -272,6 +272,19 @@ public class PhoneWindowManagerTests {
}
@Test
+ public void powerPress_withoutDreamManagerInternal_doesNotCrash() {
+ when(mDisplayPolicy.isAwake()).thenReturn(true);
+ mDreamManagerInternal = null;
+ initPhoneWindowManager();
+
+ // Power button pressed.
+ int eventTime = 0;
+ mPhoneWindowManager.powerPress(eventTime, 1, 0);
+
+ // verify no crash
+ }
+
+ @Test
public void powerPress_hubOrDreamOrSleep_hubAvailableLocks() {
when(mDisplayPolicy.isAwake()).thenReturn(true);
mContext.getTestablePermissions().setPermission(android.Manifest.permission.DEVICE_POWER,
@@ -352,5 +365,10 @@ public class PhoneWindowManagerTests {
WindowWakeUpPolicy getWindowWakeUpPolicy() {
return mock(WindowWakeUpPolicy.class);
}
+
+ @Override
+ DreamManagerInternal getDreamManagerInternal() {
+ return mDreamManagerInternal;
+ }
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
index db90c28ec7df..2d4101e40615 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
@@ -17,17 +17,21 @@
package com.android.server.wm;
import static android.view.Display.FLAG_PRESENTATION;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.window.flags.Flags.FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.os.UserHandle;
-import android.os.UserManager;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
@@ -41,6 +45,7 @@ import android.view.WindowManagerGlobal;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,35 +58,100 @@ import org.junit.runner.RunWith;
@RunWith(WindowTestRunner.class)
public class PresentationControllerTests extends WindowTestsBase {
+ TestTransitionPlayer mPlayer;
+
+ @Before
+ public void setUp() {
+ mPlayer = registerTestTransitionPlayer();
+ }
+
@EnableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
@Test
- public void testPresentationHidesActivitiesBehind() {
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.copyFrom(mDisplayInfo);
- displayInfo.flags = FLAG_PRESENTATION;
- final DisplayContent dc = createNewDisplay(displayInfo);
- final int displayId = dc.getDisplayId();
- doReturn(dc).when(mWm.mRoot).getDisplayContentOrCreate(displayId);
+ public void testPresentationShowAndHide() {
+ final DisplayContent dc = createPresentationDisplay();
final ActivityRecord activity = createActivityRecord(createTask(dc));
assertTrue(activity.isVisible());
- doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
- final int uid = 100000; // uid for non-system user
+ // Add a presentation window, which requests the activity to stop.
+ final WindowState window = addPresentationWindow(100000, dc.mDisplayId);
+ assertFalse(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+ final Transition addTransition = window.mTransitionController.getCollectingTransition();
+ assertEquals(TRANSIT_OPEN, addTransition.mType);
+ assertTrue(addTransition.isInTransition(window));
+ assertTrue(addTransition.isInTransition(activity));
+
+ // Completing the transition makes the activity invisible.
+ completeTransition(addTransition, /*abortSync=*/ true);
+ assertFalse(activity.isVisible());
+
+ // Remove a Presentation window, which requests the activity to be resumed back.
+ window.removeIfPossible();
+ final Transition removeTransition = window.mTransitionController.getCollectingTransition();
+ assertEquals(TRANSIT_CLOSE, removeTransition.mType);
+ assertTrue(removeTransition.isInTransition(window));
+ assertTrue(removeTransition.isInTransition(activity));
+ assertTrue(activity.isVisibleRequested());
+ assertFalse(activity.isVisible());
+
+ // Completing the transition makes the activity visible.
+ completeTransition(removeTransition, /*abortSync=*/ false);
+ assertTrue(activity.isVisible());
+ }
+
+ @DisableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
+ @Test
+ public void testPresentationShowAndHide_flagDisabled() {
+ final DisplayContent dc = createPresentationDisplay();
+ final ActivityRecord activity = createActivityRecord(createTask(dc));
+ assertTrue(activity.isVisible());
+
+ final WindowState window = addPresentationWindow(100000, dc.mDisplayId);
+ assertFalse(window.mTransitionController.isCollecting());
+ assertTrue(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+
+ window.removeIfPossible();
+ assertFalse(window.mTransitionController.isCollecting());
+ assertTrue(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+ assertFalse(window.isAttached());
+ }
+
+ private WindowState addPresentationWindow(int uid, int displayId) {
final Session session = createTestSession(mAtm, 1234 /* pid */, uid);
final int userId = UserHandle.getUserId(uid);
- doReturn(false).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
+ doReturn(true).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_PRESENTATION);
-
final IWindow clientWindow = new TestIWindow();
- final int result = mWm.addWindow(session, clientWindow, params, View.VISIBLE, displayId,
+ final int res = mWm.addWindow(session, clientWindow, params, View.VISIBLE, displayId,
userId, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
new InsetsSourceControl.Array(), new Rect(), new float[1]);
- assertTrue(result >= WindowManagerGlobal.ADD_OKAY);
- assertFalse(activity.isVisible());
-
+ assertTrue(res >= WindowManagerGlobal.ADD_OKAY);
final WindowState window = mWm.windowForClientLocked(session, clientWindow, false);
- window.removeImmediately();
- assertTrue(activity.isVisible());
+ window.mHasSurface = true;
+ return window;
+ }
+
+ private DisplayContent createPresentationDisplay() {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.flags = FLAG_PRESENTATION;
+ final DisplayContent dc = createNewDisplay(displayInfo);
+ final int displayId = dc.getDisplayId();
+ doReturn(dc).when(mWm.mRoot).getDisplayContentOrCreate(displayId);
+ return dc;
+ }
+
+ private void completeTransition(@NonNull Transition transition, boolean abortSync) {
+ final ActionChain chain = ActionChain.testFinish(transition);
+ if (abortSync) {
+ // Forcefully finishing the active sync for testing purpose.
+ mWm.mSyncEngine.abort(transition.getSyncId());
+ } else {
+ transition.onTransactionReady(transition.getSyncId(), mTransaction);
+ }
+ transition.finishTransition(chain);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 2ee34d3a4b36..77ad7f7bac7f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -683,7 +683,7 @@ public class TransitionTests extends WindowTestsBase {
app.onStartingWindowDrawn();
// The task appeared event should be deferred until transition ready.
assertFalse(task.taskAppearedReady());
- testPlayer.onTransactionReady(app.getSyncTransaction());
+ testPlayer.onTransactionReady();
assertTrue(task.taskAppearedReady());
assertTrue(playerProc.isRunningRemoteTransition());
assertTrue(controller.mRemotePlayer.reportRunning(delegateProc.getThread()));
@@ -1162,7 +1162,8 @@ public class TransitionTests extends WindowTestsBase {
screenDecor.updateSurfacePosition(mMockT);
assertEquals(prevPos, screenDecor.mLastSurfacePosition);
- final SurfaceControl.Transaction startTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction startTransaction = mTransaction;
+ clearInvocations(startTransaction);
final SurfaceControl.TransactionCommittedListener transactionCommittedListener =
onRotationTransactionReady(player, startTransaction);
@@ -1213,7 +1214,8 @@ public class TransitionTests extends WindowTestsBase {
assertFalse(statusBar.mToken.inTransition());
assertTrue(app.getTask().inTransition());
- final SurfaceControl.Transaction startTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction startTransaction = mTransaction;
+ clearInvocations(startTransaction);
final SurfaceControl leash = statusBar.mToken.getAnimationLeash();
doReturn(true).when(leash).isValid();
final SurfaceControl.TransactionCommittedListener transactionCommittedListener =
@@ -1287,7 +1289,8 @@ public class TransitionTests extends WindowTestsBase {
// Avoid DeviceStateController disturbing the test by triggering another rotation change.
doReturn(false).when(mDisplayContent).updateRotationUnchecked();
- onRotationTransactionReady(player, mWm.mTransactionFactory.get()).onTransactionCommitted();
+ clearInvocations(mTransaction);
+ onRotationTransactionReady(player, mTransaction).onTransactionCommitted();
assertEquals(ROTATION_ANIMATION_SEAMLESS, player.mLastReady.getChange(
mDisplayContent.mRemoteToken.toWindowContainerToken()).getRotationAnimation());
spyOn(navBarInsetsProvider);
@@ -1350,7 +1353,7 @@ public class TransitionTests extends WindowTestsBase {
mDisplayContent.setFixedRotationLaunchingAppUnchecked(home);
doReturn(true).when(home).hasFixedRotationTransform(any());
player.startTransition();
- player.onTransactionReady(mDisplayContent.getSyncTransaction());
+ player.onTransactionReady();
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
final RemoteDisplayChangeController displayChangeController = mDisplayContent
@@ -3071,8 +3074,11 @@ public class TransitionTests extends WindowTestsBase {
TestTransitionPlayer player, SurfaceControl.Transaction startTransaction) {
final ArgumentCaptor<SurfaceControl.TransactionCommittedListener> listenerCaptor =
ArgumentCaptor.forClass(SurfaceControl.TransactionCommittedListener.class);
- player.onTransactionReady(startTransaction);
- verify(startTransaction).addTransactionCommittedListener(any(), listenerCaptor.capture());
+ player.onTransactionReady();
+ // The startTransaction is from mWm.mTransactionFactory.get() in SyncGroup#finishNow.
+ // 2 times are from SyncGroup#finishNow and AsyncRotationController#setupStartTransaction.
+ verify(startTransaction, times(2)).addTransactionCommittedListener(
+ any(), listenerCaptor.capture());
return listenerCaptor.getValue();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 97c6ac6854c3..c6416850c464 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -2159,13 +2159,14 @@ public class WindowTestsBase extends SystemServiceTestsBase {
mOrganizer.startTransition(mLastTransit.getToken(), null);
}
- void onTransactionReady(SurfaceControl.Transaction t) {
- mLastTransit.onTransactionReady(mLastTransit.getSyncId(), t);
+ void onTransactionReady() {
+ // SyncGroup#finishNow -> Transition#onTransactionReady.
+ mController.mSyncEngine.abort(mLastTransit.getSyncId());
}
void start() {
startTransition();
- onTransactionReady(mock(SurfaceControl.Transaction.class));
+ onTransactionReady();
}
public void finish() {