Merge "Set configChanges for Spa Browser Activity"
diff --git a/core/api/current.txt b/core/api/current.txt
index 3ca7dad..19f9515 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -49563,6 +49563,7 @@
method public float getY(int);
method public float getYPrecision();
method public boolean isButtonPressed(int);
+ method @Nullable public static android.view.MotionEvent obtain(long, long, int, int, @NonNull android.view.MotionEvent.PointerProperties[], @NonNull android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int, int, int);
method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
method @Deprecated public static android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index baf1f31..ad519ce 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1470,6 +1470,7 @@
public class BackupManagerMonitor {
ctor public BackupManagerMonitor();
method public void onEvent(android.os.Bundle);
+ field public static final String EXTRA_LOG_AGENT_LOGGING_RESULTS = "android.app.backup.extra.LOG_AGENT_LOGGING_RESULTS";
field public static final String EXTRA_LOG_CANCEL_ALL = "android.app.backup.extra.LOG_CANCEL_ALL";
field public static final String EXTRA_LOG_EVENT_CATEGORY = "android.app.backup.extra.LOG_EVENT_CATEGORY";
field public static final String EXTRA_LOG_EVENT_ID = "android.app.backup.extra.LOG_EVENT_ID";
@@ -1488,6 +1489,7 @@
field public static final int LOG_EVENT_CATEGORY_AGENT = 2; // 0x2
field public static final int LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY = 3; // 0x3
field public static final int LOG_EVENT_CATEGORY_TRANSPORT = 1; // 0x1
+ field public static final int LOG_EVENT_ID_AGENT_LOGGING_RESULTS = 52; // 0x34
field public static final int LOG_EVENT_ID_APK_NOT_INSTALLED = 40; // 0x28
field public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28; // 0x1c
field public static final int LOG_EVENT_ID_BACKUP_DISABLED = 13; // 0xd
@@ -1562,6 +1564,7 @@
method public int finishBackup();
method public void finishRestore();
method public android.app.backup.RestoreSet[] getAvailableRestoreSets();
+ method @Nullable public android.app.backup.BackupManagerMonitor getBackupManagerMonitor();
method public long getBackupQuota(String, boolean);
method public android.os.IBinder getBinder();
method public long getCurrentRestoreSet();
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index b3db38d..62b0f5c 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1029,7 +1029,9 @@
* @param password The password to associate with the account, null for none
* @param extras String values to use for the account's userdata, null for none
* @param visibility Map from packageName to visibility values which will be set before account
- * is added. See {@link #getAccountVisibility} for possible values.
+ * is added. See {@link #getAccountVisibility} for possible values. Declaring
+ * <a href="/training/basics/intents/package-visibility">package visibility</a> needs for
+ * package names in the map is needed, if the caller is targeting API level 34 and above.
*
* @return True if the account was successfully added, false if the account already exists, the
* account is null, or another error occurs.
@@ -1113,7 +1115,9 @@
* the specified account.
*
* @param account {@link Account} to update visibility
- * @param packageName Package name of the application to modify account visibility
+ * @param packageName Package name of the application to modify account visibility. Declaring
+ * <a href="/training/basics/intents/package-visibility">package visibility</a> needs
+ * for it is needed, if the caller is targeting API level 34 and above.
* @param visibility New visibility value
*
* @return True, if visibility value was successfully updated.
@@ -1145,7 +1149,9 @@
* @param account {@link Account} to get visibility
* @param packageName Package name of the application to get account visibility
*
- * @return int Visibility of given account.
+ * @return int Visibility of given account. For the caller targeting API level 34 and above,
+ * {@link #VISIBILITY_NOT_VISIBLE} is returned if the given package is filtered by the rules of
+ * <a href="/training/basics/intents/package-visibility">package visibility</a>.
*/
public @AccountVisibility int getAccountVisibility(Account account, String packageName) {
if (account == null)
diff --git a/core/java/android/app/backup/BackupManagerMonitor.java b/core/java/android/app/backup/BackupManagerMonitor.java
index 07e7688a..d134ca2 100644
--- a/core/java/android/app/backup/BackupManagerMonitor.java
+++ b/core/java/android/app/backup/BackupManagerMonitor.java
@@ -129,6 +129,13 @@
*/
public static final String EXTRA_LOG_OLD_VERSION = "android.app.backup.extra.LOG_OLD_VERSION";
+ /**
+ * ParcelableList: when we have an event of id LOG_EVENT_ID_AGENT_LOGGING_RESULTS we send a list
+ * of {@link android.app.backup.BackupRestoreEventLogger.DataTypeResult}.
+ */
+ public static final String EXTRA_LOG_AGENT_LOGGING_RESULTS =
+ "android.app.backup.extra.LOG_AGENT_LOGGING_RESULTS";
+
// TODO complete this list with all log messages. And document properly.
public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4;
public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5;
@@ -171,15 +178,10 @@
public static final int LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION = 48;
public static final int LOG_EVENT_ID_NO_PACKAGES = 49;
public static final int LOG_EVENT_ID_TRANSPORT_IS_NULL = 50;
+ /** The transport returned {@link BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED}. */
+ public static final int LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED = 51;
- /**
- * The transport returned {@link BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED}.
- */
- public static final int LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED = 51;
-
-
-
-
+ public static final int LOG_EVENT_ID_AGENT_LOGGING_RESULTS = 52;
/**
* This method will be called each time something important happens on BackupManager.
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index 90e9df4..f56c8c3 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -661,8 +661,6 @@
*
* <p>Backups requested from outside the framework may pass in a monitor with the request,
* however backups initiated by the framework will call this method to retrieve one.
- *
- * @hide
*/
@Nullable
public BackupManagerMonitor getBackupManagerMonitor() {
diff --git a/core/java/android/hardware/input/VirtualTouchEvent.java b/core/java/android/hardware/input/VirtualTouchEvent.java
index ad51eb8..9b1e6e8 100644
--- a/core/java/android/hardware/input/VirtualTouchEvent.java
+++ b/core/java/android/hardware/input/VirtualTouchEvent.java
@@ -33,6 +33,11 @@
* The pointer id, tool type, action, and location are required; pressure and main axis size are
* optional.
*
+ * Note: A VirtualTouchEvent with ACTION_CANCEL can only be created with TOOL_TYPE_PALM (and vice
+ * versa). Events are injected into the uinput kernel module, which has no concept of cancelling
+ * an action. The only way to state the intention that a pointer should not be handled as a pointer
+ * is to change its tool type to TOOL_TYPE_PALM.
+ *
* @hide
*/
@SystemApi
@@ -186,6 +191,10 @@
/**
* Creates a {@link VirtualTouchEvent} object with the current builder configuration.
+ *
+ * @throws IllegalArgumentException if one of the required arguments is missing or if
+ * ACTION_CANCEL is not set in combination with TOOL_TYPE_PALM. See
+ * {@link VirtualTouchEvent} for a detailed explanation.
*/
public @NonNull VirtualTouchEvent build() {
if (mToolType == TOOL_TYPE_UNKNOWN || mPointerId == MotionEvent.INVALID_POINTER_ID
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index b3e8fb6..c8a5d8d 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -22,7 +22,9 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
@@ -1780,19 +1782,18 @@
* @param displayId The display ID associated with this event.
* @param flags The motion event flags.
* @param classification The classification to give this event.
- * @hide
*/
- public static MotionEvent obtain(long downTime, long eventTime,
- int action, int pointerCount, PointerProperties[] pointerProperties,
- PointerCoords[] pointerCoords, int metaState, int buttonState,
- float xPrecision, float yPrecision, int deviceId,
- int edgeFlags, int source, int displayId, int flags,
- @Classification int classification) {
+ public static @Nullable MotionEvent obtain(long downTime, long eventTime, int action,
+ int pointerCount,
+ @SuppressLint("ArrayReturn") @NonNull PointerProperties[] pointerProperties,
+ @SuppressLint("ArrayReturn") @NonNull PointerCoords[] pointerCoords, int metaState,
+ int buttonState, float xPrecision, float yPrecision, int deviceId, int edgeFlags,
+ int source, int displayId, int flags, @Classification int classification) {
MotionEvent ev = obtain();
final boolean success = ev.initialize(deviceId, source, displayId, action, flags, edgeFlags,
metaState, buttonState, classification, 0, 0, xPrecision, yPrecision,
- downTime * NS_PER_MS, eventTime * NS_PER_MS,
- pointerCount, pointerProperties, pointerCoords);
+ downTime * NS_PER_MS, eventTime * NS_PER_MS, pointerCount, pointerProperties,
+ pointerCoords);
if (!success) {
Log.e(TAG, "Could not initialize MotionEvent");
ev.recycle();
diff --git a/core/res/res/values/cloneable_apps.xml b/core/res/res/values/cloneable_apps.xml
new file mode 100644
index 0000000..b852c3c
--- /dev/null
+++ b/core/res/res/values/cloneable_apps.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources>
+ <!-- A list of apps that are allowed to have another instance on a device
+ in the clone profile. -->
+ <string-array translatable="false" name="cloneable_apps">
+ </string-array>
+</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5811ed9..1b74e4b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1297,6 +1297,7 @@
<java-symbol type="array" name="vendor_cross_profile_apps" />
<java-symbol type="array" name="policy_exempt_apps" />
<java-symbol type="array" name="vendor_policy_exempt_apps" />
+ <java-symbol type="array" name="cloneable_apps" />
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="default_lock_wallpaper" />
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java b/core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java
index 3f504a0..100aba5 100644
--- a/core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java
+++ b/core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java
@@ -136,6 +136,12 @@
.build());
}
+ /**
+ * The combination of TOOL_TYPE_PALM with anything else than ACTION_CANCEL should throw an
+ * exception. This is due to an underlying implementation detail. See documentation of {@link
+ * VirtualTouchEvent}
+ * for details.
+ */
@Test
public void touchEvent_palmUsedImproperly() {
assertThrows(IllegalArgumentException.class, () -> new VirtualTouchEvent.Builder()
diff --git a/media/tests/MediaRouter/AndroidTest.xml b/media/tests/MediaRouter/AndroidTest.xml
index d350e05..3b8c846 100644
--- a/media/tests/MediaRouter/AndroidTest.xml
+++ b/media/tests/MediaRouter/AndroidTest.xml
@@ -6,6 +6,8 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
<option name="test-suite-tag" value="apct"/>
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
<option name="test-tag" value="MediaRouterTest"/>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 3ae2545..65a21a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -1160,12 +1160,21 @@
mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent());
}
- if (curr.getSuppressedChanges().getParent() != null) {
- mLogger.logParentChangeSuppressed(
+ GroupEntry currSuppressedParent = curr.getSuppressedChanges().getParent();
+ GroupEntry prevSuppressedParent = prev.getSuppressedChanges().getParent();
+ if (currSuppressedParent != null && (prevSuppressedParent == null
+ || !prevSuppressedParent.getKey().equals(currSuppressedParent.getKey()))) {
+ mLogger.logParentChangeSuppressedStarted(
mIterationCount,
- curr.getSuppressedChanges().getParent(),
+ currSuppressedParent,
curr.getParent());
}
+ if (prevSuppressedParent != null && currSuppressedParent == null) {
+ mLogger.logParentChangeSuppressedStopped(
+ mIterationCount,
+ prevSuppressedParent,
+ prev.getParent());
+ }
if (curr.getSuppressedChanges().getSection() != null) {
mLogger.logSectionChangeSuppressed(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index 8e052c7..4adc90a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -193,7 +193,7 @@
})
}
- fun logParentChangeSuppressed(
+ fun logParentChangeSuppressedStarted(
buildId: Int,
suppressedParent: GroupEntry?,
keepingParent: GroupEntry?
@@ -207,6 +207,21 @@
})
}
+ fun logParentChangeSuppressedStopped(
+ buildId: Int,
+ previouslySuppressedParent: GroupEntry?,
+ previouslyKeptParent: GroupEntry?
+ ) {
+ buffer.log(TAG, INFO, {
+ long1 = buildId.toLong()
+ str1 = previouslySuppressedParent?.logKey
+ str2 = previouslyKeptParent?.logKey
+ }, {
+ "(Build $long1) Change of parent to '$str1' no longer suppressed; " +
+ "replaced parent '$str2'"
+ })
+ }
+
fun logGroupPruningSuppressed(
buildId: Int,
keepingParent: GroupEntry?
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
index d411e34..ae30ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
@@ -94,7 +94,7 @@
overlayContainer = builder.build()
SurfaceControl.Transaction()
- .setLayer(overlayContainer, Integer.MAX_VALUE)
+ .setLayer(overlayContainer, UNFOLD_OVERLAY_LAYER_Z_INDEX)
.show(overlayContainer)
.apply()
@@ -268,4 +268,12 @@
this.isFolded = isFolded
}
)
+
+ private companion object {
+ private const val ROTATION_ANIMATION_OVERLAY_Z_INDEX = Integer.MAX_VALUE
+
+ // Put the unfold overlay below the rotation animation screenshot to hide the moment
+ // when it is rotated but the rotation of the other windows hasn't happen yet
+ private const val UNFOLD_OVERLAY_LAYER_Z_INDEX = ROTATION_ANIMATION_OVERLAY_Z_INDEX - 1
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
index 2a3d32e..9c36be6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
@@ -344,26 +344,6 @@
}
@Test
- fun testCheckViewsDontChangeSizeBetweenAnimationConstraints() {
- val views = mapOf(
- R.id.clock to "clock",
- R.id.date to "date",
- R.id.statusIcons to "icons",
- R.id.privacy_container to "privacy",
- R.id.carrier_group to "carriers",
- R.id.batteryRemainingIcon to "battery",
- )
- views.forEach { (id, name) ->
- assertWithMessage("$name changes height")
- .that(qqsConstraint.getConstraint(id).layout.mHeight)
- .isEqualTo(qsConstraint.getConstraint(id).layout.mHeight)
- assertWithMessage("$name changes width")
- .that(qqsConstraint.getConstraint(id).layout.mWidth)
- .isEqualTo(qsConstraint.getConstraint(id).layout.mWidth)
- }
- }
-
- @Test
fun testEmptyCutoutDateIconsAreConstrainedWidth() {
CombinedShadeHeadersConstraintManagerImpl.emptyCutoutConstraints()()
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 1e1ca95..379ae52 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -23,11 +23,13 @@
import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA_FILENAME;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupTransport;
import android.app.backup.FullBackupDataOutput;
+import android.app.backup.IBackupManagerMonitor;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -42,6 +44,7 @@
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.remote.RemoteCall;
import com.android.server.backup.utils.BackupEligibilityRules;
+import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.File;
@@ -60,12 +63,13 @@
private BackupRestoreTask mTimeoutMonitor;
private IBackupAgent mAgent;
private boolean mIncludeApks;
- private PackageInfo mPkg;
+ private final PackageInfo mPkg;
private final long mQuota;
private final int mOpToken;
private final int mTransportFlags;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final BackupEligibilityRules mBackupEligibilityRules;
+ @Nullable private final IBackupManagerMonitor mMonitor;
class FullBackupRunner implements Runnable {
private final @UserIdInt int mUserId;
@@ -193,7 +197,8 @@
long quota,
int opToken,
int transportFlags,
- BackupEligibilityRules backupEligibilityRules) {
+ BackupEligibilityRules backupEligibilityRules,
+ IBackupManagerMonitor monitor) {
this.backupManagerService = backupManagerService;
mOutput = output;
mPreflightHook = preflightHook;
@@ -208,6 +213,7 @@
backupManagerService.getAgentTimeoutParameters(),
"Timeout parameters cannot be null");
mBackupEligibilityRules = backupEligibilityRules;
+ mMonitor = monitor;
}
public int preflightCheck() throws RemoteException {
@@ -260,6 +266,8 @@
}
result = BackupTransport.TRANSPORT_OK;
}
+
+ BackupManagerMonitorUtils.monitorAgentLoggingResults(mMonitor, mPkg, mAgent);
} catch (IOException e) {
Slog.e(TAG, "Error backing up " + mPkg.packageName + ": " + e.getMessage());
result = BackupTransport.AGENT_ERROR;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index ec58e17..cba1e29 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -420,7 +420,8 @@
Long.MAX_VALUE,
mCurrentOpToken,
/*transportFlags=*/ 0,
- mBackupEligibilityRules);
+ mBackupEligibilityRules,
+ /* monitor= */ null);
sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
// Don't need to check preflight result as there is no preflight hook.
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index f0492a8..78df304 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -882,7 +882,8 @@
mQuota,
mCurrentOpToken,
mTransportFlags,
- mBackupEligibilityRules);
+ mBackupEligibilityRules,
+ mMonitor);
try {
try {
if (!mIsCancelled) {
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 16aa4eb..fd9c834 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -68,6 +68,7 @@
import com.android.server.backup.transport.TransportConnection;
import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.utils.BackupEligibilityRules;
+import com.android.server.backup.utils.BackupManagerMonitorUtils;
import libcore.io.IoUtils;
@@ -697,6 +698,8 @@
try {
extractAgentData(mCurrentPackage);
+ BackupManagerMonitorUtils.monitorAgentLoggingResults(
+ mReporter.getMonitor(), mCurrentPackage, mAgent);
int status = sendDataToTransport(mCurrentPackage);
cleanUpAgentForTransportStatus(status);
} catch (AgentException | TaskException e) {
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index b48367d..9f89339 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -405,6 +405,12 @@
BackupTransportClient transport =
mTransportConnection.connectOrThrow("PerformUnifiedRestoreTask.startRestore()");
+ // If the requester of the restore has not passed in a monitor, we ask the transport
+ // for one.
+ if (mMonitor == null) {
+ mMonitor = transport.getBackupManagerMonitor();
+ }
+
mStatus = transport.startRestore(mToken, packages);
if (mStatus != BackupTransport.TRANSPORT_OK) {
Slog.e(TAG, "Transport error " + mStatus + "; no restore possible");
@@ -885,6 +891,10 @@
OpType.RESTORE_WAIT);
mAgent.doRestoreFinished(mEphemeralOpToken,
backupManagerService.getBackupManagerBinder());
+
+ // Ask the agent for logs after doRestoreFinished() to allow it to finalize its logs.
+ BackupManagerMonitorUtils.monitorAgentLoggingResults(mMonitor, mCurrentPackage, mAgent);
+
// If we get this far, the callback or timeout will schedule the
// next restore state, so we're done
} catch (Exception e) {
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index 6f08376..8eda5b9 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -16,24 +16,43 @@
package com.android.server.backup.utils;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS;
import static com.android.server.backup.BackupManagerService.DEBUG;
import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
+import android.app.IBackupAgent;
import android.app.backup.BackupManagerMonitor;
+import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.IBackupManagerMonitor;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.infra.AndroidFuture;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
/**
* Utility methods to communicate with BackupManagerMonitor.
*/
public class BackupManagerMonitorUtils {
/**
+ * Timeout for how long we wait before we give up on getting logs from a {@link IBackupAgent}.
+ * We expect this to be very fast since the agent immediately returns whatever logs have been
+ * accumulated. The timeout adds a bit more security and ensures we don't hang the B&R waiting
+ * for non-essential logs.
+ */
+ private static final int AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS = 500;
+
+ /**
* Notifies monitor about the event.
*
* Calls {@link IBackupManagerMonitor#onEvent(Bundle)} with a bundle representing current event.
@@ -80,6 +99,48 @@
}
/**
+ * Extracts logging results from the provided {@code agent} and notifies the {@code monitor}
+ * about them.
+ *
+ * <p>Note that this method does two separate binder calls (one to the agent and one to the
+ * monitor).
+ *
+ * @param monitor - implementation of {@link IBackupManagerMonitor} to notify.
+ * @param pkg - package the {@code agent} belongs to.
+ * @param agent - the {@link IBackupAgent} to retrieve logs from.
+ * @return {@code null} if the monitor is null. {@code monitor} if we fail to retrieve the logs
+ * from the {@code agent}. Otherwise, the result of {@link
+ * #monitorEvent(IBackupManagerMonitor, int, PackageInfo, int, Bundle)}.
+ */
+ public static IBackupManagerMonitor monitorAgentLoggingResults(
+ @Nullable IBackupManagerMonitor monitor, PackageInfo pkg, IBackupAgent agent) {
+ if (monitor == null) {
+ return null;
+ }
+
+ try {
+ AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> resultsFuture =
+ new AndroidFuture<>();
+ agent.getLoggerResults(resultsFuture);
+ Bundle loggerResultsBundle = new Bundle();
+ loggerResultsBundle.putParcelableList(
+ EXTRA_LOG_AGENT_LOGGING_RESULTS,
+ resultsFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
+ return BackupManagerMonitorUtils.monitorEvent(
+ monitor,
+ LOG_EVENT_ID_AGENT_LOGGING_RESULTS,
+ pkg,
+ LOG_EVENT_CATEGORY_AGENT,
+ loggerResultsBundle);
+ } catch (TimeoutException e) {
+ Slog.w(TAG, "Timeout while waiting to retrieve logging results from agent", e);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to retrieve logging results from agent", e);
+ }
+ return monitor;
+ }
+
+ /**
* Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
* be created.
*
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c7c2655..7476317 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -45,6 +45,9 @@
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ComponentName;
@@ -70,6 +73,7 @@
import android.database.sqlite.SQLiteFullException;
import android.database.sqlite.SQLiteStatement;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -196,6 +200,14 @@
private static final int SIGNATURE_CHECK_MATCH = 1;
private static final int SIGNATURE_CHECK_UID_MATCH = 2;
+ /**
+ * Apps targeting Android U and above need to declare the package visibility needs in the
+ * manifest to access the AccountManager APIs.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ private static final long ENFORCE_PACKAGE_VISIBILITY_FILTERING = 154726397;
+
static {
ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
@@ -527,7 +539,7 @@
*/
private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
- if (!packageExistsForUser(packageName, accounts.userId)) {
+ if (!canCallerAccessPackage(packageName, callingUid, accounts.userId)) {
Log.w(TAG, "getAccountsAndVisibilityForPackage#Package not found " + packageName);
return new LinkedHashMap<>();
}
@@ -629,6 +641,9 @@
return AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
}
}
+ if (!canCallerAccessPackage(packageName, callingUid, accounts.userId)) {
+ return AccountManager.VISIBILITY_NOT_VISIBLE;
+ }
return resolveAccountVisibility(account, packageName, accounts);
} finally {
restoreCallingIdentity(identityToken);
@@ -779,7 +794,7 @@
try {
UserAccounts accounts = getUserAccounts(userId);
return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
- accounts);
+ accounts, callingUid);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -798,11 +813,12 @@
* @param newVisibility New visibility calue
* @param notify if the flag is set applications will get notification about visibility change
* @param accounts UserAccount that currently hosts the account and application
+ * @param callingUid The caller's uid.
*
* @return True if account visibility was changed.
*/
private boolean setAccountVisibility(Account account, String packageName, int newVisibility,
- boolean notify, UserAccounts accounts) {
+ boolean notify, UserAccounts accounts, int callingUid) {
synchronized (accounts.dbLock) {
synchronized (accounts.cacheLock) {
Map<String, Integer> packagesToVisibility;
@@ -813,8 +829,8 @@
getRequestingPackages(account, accounts);
accountRemovedReceivers = getAccountRemovedReceivers(account, accounts);
} else {
- if (!packageExistsForUser(packageName, accounts.userId)) {
- return false; // package is not installed.
+ if (!canCallerAccessPackage(packageName, callingUid, accounts.userId)) {
+ return false; // package is not installed or not visible.
}
packagesToVisibility = new HashMap<>();
packagesToVisibility.put(packageName,
@@ -826,8 +842,8 @@
}
} else {
// Notifications will not be send - only used during add account.
- if (!isSpecialPackageKey(packageName) &&
- !packageExistsForUser(packageName, accounts.userId)) {
+ if (!isSpecialPackageKey(packageName)
+ && !canCallerAccessPackage(packageName, callingUid, accounts.userId)) {
// package is not installed and not meta value.
return false;
}
@@ -1045,20 +1061,6 @@
return (receivers != null && receivers.size() > 0);
}
- private boolean packageExistsForUser(String packageName, int userId) {
- try {
- final long identityToken = clearCallingIdentity();
- try {
- mPackageManager.getPackageUidAsUser(packageName, userId);
- return true;
- } finally {
- restoreCallingIdentity(identityToken);
- }
- } catch (NameNotFoundException e) {
- return false;
- }
- }
-
/**
* Returns true if packageName is one of special values.
*/
@@ -1903,7 +1905,7 @@
for (Entry<String, Integer> entry : packageToVisibility.entrySet()) {
setAccountVisibility(account, entry.getKey() /* package */,
entry.getValue() /* visibility */, false /* notify */,
- accounts);
+ accounts, callingUid);
}
}
accounts.accountsDb.setTransactionSuccessful();
@@ -5915,6 +5917,32 @@
return (dpmi != null) && (dpmi.isActiveProfileOwner(uid) || dpmi.isActiveDeviceOwner(uid));
}
+ /**
+ * Filter the access to the target package by rules of the package visibility if the caller
+ * targeting API level U and above. Otherwise, returns true if the package is installed on
+ * the device.
+ *
+ * @param targetPkgName The package name to check.
+ * @param callingUid The caller that is going to access the package.
+ * @param userId The user ID where the target package resides.
+ * @return true if the caller is able to access the package.
+ */
+ private boolean canCallerAccessPackage(@NonNull String targetPkgName, int callingUid,
+ int userId) {
+ final PackageManagerInternal pmInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ if (!CompatChanges.isChangeEnabled(ENFORCE_PACKAGE_VISIBILITY_FILTERING, callingUid)) {
+ return pmInternal.getPackageUid(
+ targetPkgName, 0 /* flags */, userId) != Process.INVALID_UID;
+ }
+ final boolean canAccess = !pmInternal.filterAppAccess(targetPkgName, callingUid, userId);
+ if (!canAccess && Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Package " + targetPkgName + " is not visible to caller " + callingUid
+ + " for user " + userId);
+ }
+ return canAccess;
+ }
+
@Override
public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
throws RemoteException {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 990569c..9ded42a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -299,7 +299,6 @@
private boolean mAppliedAutoBrightness;
private boolean mAppliedDimming;
private boolean mAppliedLowPower;
- private boolean mAppliedScreenBrightnessOverride;
private boolean mAppliedTemporaryBrightness;
private boolean mAppliedTemporaryAutoBrightnessAdjustment;
private boolean mAppliedBrightnessBoost;
@@ -1202,15 +1201,6 @@
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
}
- if ((Float.isNaN(brightnessState))
- && isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
- brightnessState = mPowerRequest.screenBrightnessOverride;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
- mAppliedScreenBrightnessOverride = true;
- } else {
- mAppliedScreenBrightnessOverride = false;
- }
-
final boolean autoBrightnessEnabledInDoze =
mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()
&& Display.isDozeState(state);
@@ -2311,7 +2301,6 @@
pw.println(" mAppliedDimming=" + mAppliedDimming);
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
pw.println(" mAppliedThrottling=" + mAppliedThrottling);
- pw.println(" mAppliedScreenBrightnessOverride=" + mAppliedScreenBrightnessOverride);
pw.println(" mAppliedTemporaryBrightness=" + mAppliedTemporaryBrightness);
pw.println(" mAppliedTemporaryAutoBrightnessAdjustment="
+ mAppliedTemporaryAutoBrightnessAdjustment);
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessUtils.java b/services/core/java/com/android/server/display/brightness/BrightnessUtils.java
new file mode 100644
index 0000000..d62b1ee
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/BrightnessUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayBrightnessState;
+
+/**
+ * A helper class for eualuating brightness utilities
+ */
+public final class BrightnessUtils {
+ /**
+ * Checks whether the brightness is within the valid brightness range, not including off.
+ */
+ public static boolean isValidBrightnessValue(float brightness) {
+ return brightness >= PowerManager.BRIGHTNESS_MIN
+ && brightness <= PowerManager.BRIGHTNESS_MAX;
+ }
+
+ /**
+ * A utility to construct the DisplayBrightnessState
+ */
+ public static DisplayBrightnessState constructDisplayBrightnessState(
+ int brightnessChangeReason, float brightness, float sdrBrightness) {
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(brightnessChangeReason);
+ return new DisplayBrightnessState.Builder()
+ .setBrightness(brightness)
+ .setSdrBrightness(sdrBrightness)
+ .setBrightnessReason(brightnessReason)
+ .build();
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index fe4c101..80b5e65 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -34,6 +34,7 @@
private final int mDisplayId;
// Selects an appropriate strategy based on the request provided by the clients.
private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector;
+ private DisplayBrightnessStrategy mDisplayBrightnessStrategy;
/**
* The constructor of DisplayBrightnessController.
@@ -60,10 +61,10 @@
public DisplayBrightnessState updateBrightness(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
int targetDisplayState) {
- DisplayBrightnessStrategy displayBrightnessStrategy =
+ mDisplayBrightnessStrategy =
mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
targetDisplayState);
- return displayBrightnessStrategy.updateBrightness(displayPowerRequest);
+ return mDisplayBrightnessStrategy.updateBrightness(displayPowerRequest);
}
/**
@@ -82,6 +83,11 @@
public void dump(PrintWriter writer) {
writer.println();
writer.println("DisplayBrightnessController:");
+ writer.println(" mDisplayId=: " + mDisplayId);
+ if (mDisplayBrightnessStrategy != null) {
+ writer.println(" Last selected DisplayBrightnessStrategy= "
+ + mDisplayBrightnessStrategy.getName());
+ }
IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
mDisplayBrightnessStrategySelector.dump(ipw);
}
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 88707f0..b83b13b 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -27,6 +27,7 @@
import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
+import com.android.server.display.brightness.strategy.OverrideBrightnessStrategy;
import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
import java.io.PrintWriter;
@@ -46,6 +47,8 @@
private final ScreenOffBrightnessStrategy mScreenOffBrightnessStrategy;
// The brightness strategy used to manage the brightness state when the request state is
// invalid.
+ private final OverrideBrightnessStrategy mOverrideBrightnessStrategy;
+ // The brightness strategy used to manage the brightness state request is invalid.
private final InvalidBrightnessStrategy mInvalidBrightnessStrategy;
// We take note of the old brightness strategy so that we can know when the strategy changes.
@@ -63,6 +66,7 @@
mDisplayId = displayId;
mDozeBrightnessStrategy = injector.getDozeBrightnessStrategy();
mScreenOffBrightnessStrategy = injector.getScreenOffBrightnessStrategy();
+ mOverrideBrightnessStrategy = injector.getOverrideBrightnessStrategy();
mInvalidBrightnessStrategy = injector.getInvalidBrightnessStrategy();
mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
R.bool.config_allowAutoBrightnessWhileDozing);
@@ -82,6 +86,9 @@
displayBrightnessStrategy = mScreenOffBrightnessStrategy;
} else if (shouldUseDozeBrightnessStrategy(displayPowerRequest)) {
displayBrightnessStrategy = mDozeBrightnessStrategy;
+ } else if (BrightnessUtils
+ .isValidBrightnessValue(displayPowerRequest.screenBrightnessOverride)) {
+ displayBrightnessStrategy = mOverrideBrightnessStrategy;
}
if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
@@ -108,8 +115,11 @@
public void dump(PrintWriter writer) {
writer.println();
writer.println("DisplayBrightnessStrategySelector:");
+ writer.println(" mDisplayId= " + mDisplayId);
+ writer.println(" mOldBrightnessStrategyName= " + mOldBrightnessStrategyName);
writer.println(
- " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig);
+ " mAllowAutoBrightnessWhileDozingConfig= "
+ + mAllowAutoBrightnessWhileDozingConfig);
}
/**
@@ -138,6 +148,10 @@
return new DozeBrightnessStrategy();
}
+ OverrideBrightnessStrategy getOverrideBrightnessStrategy() {
+ return new OverrideBrightnessStrategy();
+ }
+
InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
return new InvalidBrightnessStrategy();
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
index c8b2c83..0bc900b 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -20,6 +20,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
/**
* Manages the brightness of the display when the system is in the doze state.
@@ -30,13 +31,8 @@
public DisplayBrightnessState updateBrightness(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
// Todo(brup): Introduce a validator class and add validations before setting the brightness
- BrightnessReason brightnessReason = new BrightnessReason();
- brightnessReason.setReason(BrightnessReason.REASON_DOZE);
- return new DisplayBrightnessState.Builder()
- .setBrightness(displayPowerRequest.dozeScreenBrightness)
- .setSdrBrightness(displayPowerRequest.dozeScreenBrightness)
- .setBrightnessReason(brightnessReason)
- .build();
+ return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_DOZE,
+ displayPowerRequest.dozeScreenBrightness, displayPowerRequest.dozeScreenBrightness);
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
index f6ddf4f..612bbe9 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
/**
* Manages the brightness of the display when the system is in the invalid state.
@@ -29,13 +30,8 @@
@Override
public DisplayBrightnessState updateBrightness(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
- BrightnessReason brightnessReason = new BrightnessReason();
- brightnessReason.set(null);
- return new DisplayBrightnessState.Builder()
- .setBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT)
- .setSdrBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT)
- .setBrightnessReason(brightnessReason)
- .build();
+ return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_UNKNOWN,
+ PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT);
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
new file mode 100644
index 0000000..f03f036
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.hardware.display.DisplayManagerInternal;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
+
+/**
+ * Manages the brightness of the display when the system brightness is overridden
+ */
+public class OverrideBrightnessStrategy implements DisplayBrightnessStrategy {
+ @Override
+ public DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ // Todo(brup): Introduce a validator class and add validations before setting the brightness
+ return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_OVERRIDE,
+ displayPowerRequest.screenBrightnessOverride,
+ displayPowerRequest.screenBrightnessOverride);
+ }
+
+ @Override
+ public String getName() {
+ return "OverrideBrightnessStrategy";
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
index 4138513..396fa06 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
/**
* Manages the brightness of the display when the system is in the ScreenOff state.
@@ -30,13 +31,9 @@
public DisplayBrightnessState updateBrightness(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
// Todo(brup): Introduce a validator class and add validations before setting the brightness
- BrightnessReason brightnessReason = new BrightnessReason();
- brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF);
- return new DisplayBrightnessState.Builder()
- .setBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
- .setSdrBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
- .setBrightnessReason(brightnessReason)
- .build();
+ return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_SCREEN_OFF,
+ PowerManager.BRIGHTNESS_OFF_FLOAT,
+ PowerManager.BRIGHTNESS_OFF_FLOAT);
}
@Override
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index f5ec880..11e2704 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -2443,10 +2443,9 @@
List<RouterRecord> routerRecords = getRouterRecords();
List<ManagerRecord> managerRecords = getManagerRecords();
- boolean shouldBindProviders = false;
-
+ boolean isManagerScanning = false;
if (service.mPowerManager.isInteractive()) {
- boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
+ isManagerScanning = managerRecords.stream().anyMatch(manager ->
manager.mIsScanning && service.mActivityManager
.getPackageImportance(manager.mPackageName)
<= PACKAGE_IMPORTANCE_FOR_DISCOVERY);
@@ -2455,7 +2454,6 @@
discoveryPreferences = routerRecords.stream()
.map(record -> record.mDiscoveryPreference)
.collect(Collectors.toList());
- shouldBindProviders = true;
} else {
discoveryPreferences = routerRecords.stream().filter(record ->
service.mActivityManager.getPackageImportance(record.mPackageName)
@@ -2468,7 +2466,7 @@
for (MediaRoute2Provider provider : mRouteProviders) {
if (provider instanceof MediaRoute2ProviderServiceProxy) {
((MediaRoute2ProviderServiceProxy) provider)
- .setManagerScanning(shouldBindProviders);
+ .setManagerScanning(isManagerScanning);
}
}
@@ -2484,7 +2482,7 @@
activeScan |= preference.shouldPerformActiveScan();
}
RouteDiscoveryPreference newPreference = new RouteDiscoveryPreference.Builder(
- List.copyOf(preferredFeatures), activeScan).build();
+ List.copyOf(preferredFeatures), activeScan || isManagerScanning).build();
synchronized (service.mLock) {
if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)) {
diff --git a/services/core/java/com/android/server/wm/LaunchParamsUtil.java b/services/core/java/com/android/server/wm/LaunchParamsUtil.java
index 65298c8..cd071af 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsUtil.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsUtil.java
@@ -46,6 +46,8 @@
private static final int DISPLAY_EDGE_OFFSET_DP = 27;
+ private static final Rect TMP_STABLE_BOUNDS = new Rect();
+
private LaunchParamsUtil() {}
/**
@@ -130,18 +132,42 @@
return new Size(adjWidth, adjHeight);
}
- static void adjustBoundsToFitInDisplayArea(@NonNull Rect stableBounds, int layoutDirection,
+ static void adjustBoundsToFitInDisplayArea(@NonNull TaskDisplayArea displayArea,
+ int layoutDirection,
@NonNull ActivityInfo.WindowLayout layout,
@NonNull Rect inOutBounds) {
+ // Give a small margin between the window bounds and the display bounds.
+ final Rect stableBounds = TMP_STABLE_BOUNDS;
+ displayArea.getStableRect(stableBounds);
+ final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT;
+ final int displayEdgeOffset = (int) (DISPLAY_EDGE_OFFSET_DP * density + 0.5f);
+ stableBounds.inset(displayEdgeOffset, displayEdgeOffset);
+
if (stableBounds.width() < inOutBounds.width()
|| stableBounds.height() < inOutBounds.height()) {
- // There is no way for us to fit the bounds in the displayArea without changing width
- // or height. Just move the start to align with the displayArea.
- final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
- ? stableBounds.right - inOutBounds.right + inOutBounds.left
- : stableBounds.left;
- inOutBounds.offsetTo(left, stableBounds.top);
- return;
+ final float heightShrinkRatio = stableBounds.width() / (float) inOutBounds.width();
+ final float widthShrinkRatio =
+ stableBounds.height() / (float) inOutBounds.height();
+ final float shrinkRatio = Math.min(heightShrinkRatio, widthShrinkRatio);
+ // Minimum layout requirements.
+ final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth;
+ final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
+ int adjustedWidth = Math.max(layoutMinWidth, (int) (inOutBounds.width() * shrinkRatio));
+ int adjustedHeight = Math.max(layoutMinHeight,
+ (int) (inOutBounds.height() * shrinkRatio));
+ if (stableBounds.width() < adjustedWidth
+ || stableBounds.height() < adjustedHeight) {
+ // There is no way for us to fit the bounds in the displayArea without breaking min
+ // size constraints. Set the min size to make visible as much content as possible.
+ final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
+ ? stableBounds.right - adjustedWidth
+ : stableBounds.left;
+ inOutBounds.set(left, stableBounds.top, left + adjustedWidth,
+ stableBounds.top + adjustedHeight);
+ return;
+ }
+ inOutBounds.set(inOutBounds.left, inOutBounds.top,
+ inOutBounds.left + adjustedWidth, inOutBounds.top + adjustedHeight);
}
final int dx;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 6ff91af..c15c57d 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -929,6 +929,7 @@
// Update windowing mode if necessary, e.g. launch into a different windowing mode.
if (windowingMode != WINDOWING_MODE_UNDEFINED && candidateTask.isRootTask()
&& candidateTask.getWindowingMode() != windowingMode) {
+ candidateTask.mTransitionController.collect(candidateTask);
candidateTask.setWindowingMode(windowingMode);
}
return candidateTask.getRootTask();
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index fdbed2a..da73fad 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -785,9 +785,10 @@
// to the center of suggested bounds (or the displayArea if no suggested bounds). The
// default size might be too big to center to source activity bounds in displayArea, so
// we may need to move it back to the displayArea.
+ adjustBoundsToFitInDisplayArea(displayArea, layout, mTmpBounds);
+ inOutBounds.setEmpty();
LaunchParamsUtil.centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(),
inOutBounds);
- adjustBoundsToFitInDisplayArea(displayArea, layout, inOutBounds);
if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
}
@@ -838,8 +839,7 @@
@NonNull Rect inOutBounds) {
final int layoutDirection = mSupervisor.mRootWindowContainer.getConfiguration()
.getLayoutDirection();
- displayArea.getStableRect(mTmpStableBounds);
- LaunchParamsUtil.adjustBoundsToFitInDisplayArea(mTmpStableBounds, layoutDirection, layout,
+ LaunchParamsUtil.adjustBoundsToFitInDisplayArea(displayArea, layoutDirection, layout,
inOutBounds);
}
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 962a07a..298cbf3 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -77,6 +77,8 @@
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManager;
+import android.app.backup.BackupManagerMonitor;
+import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupTransport;
import android.app.backup.IBackupCallback;
import android.app.backup.IBackupManager;
@@ -89,6 +91,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.net.Uri;
+import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -100,6 +103,7 @@
import android.util.Pair;
import com.android.internal.backup.IBackupTransport;
+import com.android.internal.infra.AndroidFuture;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.backup.BackupRestoreTask;
@@ -131,6 +135,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -1448,6 +1453,36 @@
}
@Test
+ public void testRunTask_whenFinishBackupSucceeds_sendsAgentLogsToMonitor() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+ KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+ // Mock the agent logging and returning its logs.
+ List<BackupRestoreEventLogger.DataTypeResult> results = new ArrayList<>();
+ results.add(new BackupRestoreEventLogger.DataTypeResult("testDataTypeResult"));
+ doAnswer(
+ invocation -> {
+ AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> in =
+ invocation.getArgument(0);
+ in.complete(results);
+ return null;
+ })
+ .when(agentMock.agentBinder)
+ .getLoggerResults(any());
+
+ runTask(task);
+
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mMonitor).onEvent(bundleCaptor.capture());
+ Bundle eventBundle = bundleCaptor.getValue();
+ List<BackupRestoreEventLogger.DataTypeResult> sentLoggingResults =
+ eventBundle.getParcelableArrayList(
+ BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
+ BackupRestoreEventLogger.DataTypeResult.class);
+ assertThat(sentLoggingResults.get(0).getDataType()).isEqualTo("testDataTypeResult");
+ }
+
+ @Test
public void testRunTask_whenFinishBackupSucceeds_notifiesCorrectly() throws Exception {
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgentWithData(PACKAGE_1);
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
index d3fd89c..cadc890 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
@@ -21,13 +21,20 @@
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import android.app.IBackupAgent;
+import android.app.backup.BackupManagerMonitor;
+import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.IBackupManagerMonitor;
import android.content.pm.PackageInfo;
import android.os.Bundle;
@@ -37,6 +44,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.infra.AndroidFuture;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,6 +53,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.List;
+
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -143,6 +155,44 @@
}
@Test
+ public void monitorAgentLoggingResults_fillsBundleCorrectly() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = "test.package";
+ // Mock an agent that returns a logging result.
+ IBackupAgent agent = spy(IBackupAgent.class);
+ List<BackupRestoreEventLogger.DataTypeResult> loggingResults = new ArrayList<>();
+ loggingResults.add(new BackupRestoreEventLogger.DataTypeResult("testLoggingResult"));
+ doAnswer(
+ invocation -> {
+ AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> in =
+ invocation.getArgument(0);
+ in.complete(loggingResults);
+ return null;
+ })
+ .when(agent)
+ .getLoggerResults(any());
+
+ IBackupManagerMonitor result =
+ BackupManagerMonitorUtils.monitorAgentLoggingResults(
+ mMonitorMock, packageInfo, agent);
+
+ assertThat(result).isEqualTo(mMonitorMock);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mMonitorMock).onEvent(bundleCaptor.capture());
+ Bundle eventBundle = bundleCaptor.getValue();
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID))
+ .isEqualTo(LOG_EVENT_ID_AGENT_LOGGING_RESULTS);
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY))
+ .isEqualTo(LOG_EVENT_CATEGORY_AGENT);
+ assertThat(eventBundle.getString(EXTRA_LOG_EVENT_PACKAGE_NAME)).isEqualTo("test.package");
+ List<BackupRestoreEventLogger.DataTypeResult> filledLoggingResults =
+ eventBundle.getParcelableArrayList(
+ BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
+ BackupRestoreEventLogger.DataTypeResult.class);
+ assertThat(filledLoggingResults.get(0).getDataType()).isEqualTo("testLoggingResult");
+ }
+
+ @Test
public void putMonitoringExtraString_bundleExists_fillsBundleCorrectly() throws Exception {
Bundle bundle = new Bundle();
@@ -204,5 +254,4 @@
assertThat(result.size()).isEqualTo(1);
assertThat(result.getBoolean("key")).isTrue();
}
-
}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index ba31e8c..59c69d1 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -31,6 +31,7 @@
import com.android.internal.R;
import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
+import com.android.server.display.brightness.strategy.OverrideBrightnessStrategy;
import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
import org.junit.Before;
@@ -50,6 +51,8 @@
@Mock
private DozeBrightnessStrategy mDozeBrightnessModeStrategy;
@Mock
+ private OverrideBrightnessStrategy mOverrideBrightnessStrategy;
+ @Mock
private InvalidBrightnessStrategy mInvalidBrightnessStrategy;
@Mock
private Context mContext;
@@ -75,6 +78,11 @@
}
@Override
+ OverrideBrightnessStrategy getOverrideBrightnessStrategy() {
+ return mOverrideBrightnessStrategy;
+ }
+
+ @Override
InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
return mInvalidBrightnessStrategy;
}
@@ -104,9 +112,19 @@
}
@Test
+ public void selectStrategySelectsOverrideStrategyWhenValid() {
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ displayPowerRequest.screenBrightnessOverride = 0.4f;
+ assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ Display.STATE_ON), mOverrideBrightnessStrategy);
+ }
+
+ @Test
public void selectStrategySelectsInvalidStrategyWhenNoStrategyIsValid() {
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
DisplayManagerInternal.DisplayPowerRequest.class);
+ displayPowerRequest.screenBrightnessOverride = Float.NaN;
assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
Display.STATE_ON), mInvalidBrightnessStrategy);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
new file mode 100644
index 0000000..4d89c28
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+
+import static org.junit.Assert.assertEquals;
+
+import android.hardware.display.DisplayManagerInternal;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+
+public class OverrideBrightnessStrategyTest {
+ private OverrideBrightnessStrategy mOverrideBrightnessStrategy;
+
+ @Before
+ public void before() {
+ mOverrideBrightnessStrategy = new OverrideBrightnessStrategy();
+ }
+
+ @Test
+ public void updateBrightnessWorksAsExpectedWhenScreenDozeStateIsRequested() {
+ DisplayManagerInternal.DisplayPowerRequest
+ displayPowerRequest = new DisplayManagerInternal.DisplayPowerRequest();
+ float overrideBrightness = 0.2f;
+ displayPowerRequest.screenBrightnessOverride = overrideBrightness;
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_OVERRIDE);
+ DisplayBrightnessState expectedDisplayBrightnessState =
+ new DisplayBrightnessState.Builder()
+ .setBrightness(overrideBrightness)
+ .setBrightnessReason(brightnessReason)
+ .setSdrBrightness(overrideBrightness)
+ .build();
+ DisplayBrightnessState updatedDisplayBrightnessState =
+ mOverrideBrightnessStrategy.updateBrightness(displayPowerRequest);
+ assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 2189ef8..59bf526 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -85,6 +85,11 @@
private static final Rect DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100,
/* top */ 200, /* right */ 1620, /* bottom */ 680);
+ private static final Rect SMALL_DISPLAY_BOUNDS = new Rect(/* left */ 0, /* top */ 0,
+ /* right */ 1000, /* bottom */ 500);
+ private static final Rect SMALL_DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100,
+ /* top */ 50, /* right */ 900, /* bottom */ 450);
+
private ActivityRecord mActivity;
private TaskLaunchParamsModifier mTarget;
@@ -1414,6 +1419,20 @@
}
@Test
+ public void testDefaultFreeformSizeShrinksOnSmallDisplay() {
+ final TestDisplayContent freeformDisplay = createNewDisplayContent(
+ WINDOWING_MODE_FREEFORM, SMALL_DISPLAY_BOUNDS, SMALL_DISPLAY_STABLE_BOUNDS);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options)
+ .calculate());
+
+ assertEquals(new Rect(414, 77, 587, 423), mResult.mBounds);
+ }
+
+ @Test
public void testDefaultFreeformSizeRespectsMinAspectRatio() {
final TestDisplayContent freeformDisplay = createNewDisplayContent(
WINDOWING_MODE_FREEFORM);
@@ -1603,16 +1622,15 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
- mCurrent.mBounds.set(100, 300, 1820, 1380);
+ mCurrent.mBounds.set(0, 0, 3000, 2000);
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).calculate());
- assertTrue("Result bounds should start from app bounds's origin, but it's "
- + mResult.mBounds,
- mResult.mBounds.left == 100 && mResult.mBounds.top == 200);
+ // Must shrink to fit the display while reserving aspect ratio.
+ assertEquals(new Rect(127, 227, 766, 653), mResult.mBounds);
}
@Test
@@ -1628,18 +1646,19 @@
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setMinWidth(500).setMinHeight(500).build();
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
- mCurrent.mBounds.set(100, 300, 1820, 1380);
+ mCurrent.mBounds.set(0, 0, 2000, 3000);
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
assertEquals(RESULT_CONTINUE,
- new CalculateRequestBuilder().setOptions(options).calculate());
+ new CalculateRequestBuilder().setOptions(options).setLayout(layout).calculate());
- assertTrue("Result bounds should start from top-right corner of app bounds, but "
- + "it's " + mResult.mBounds,
- mResult.mBounds.left == -100 && mResult.mBounds.top == 200);
+ // Must shrink to fit the display while reserving aspect ratio.
+ assertEquals(new Rect(1093, 227, 1593, 727), mResult.mBounds);
}
@Test
@@ -1814,7 +1833,7 @@
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).calculate());
- assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds);
+ assertEquals(new Rect(127, 227, 427, 527), mResult.mBounds);
}
@Test
@@ -1867,13 +1886,18 @@
}
private TestDisplayContent createNewDisplayContent(int windowingMode) {
+ return createNewDisplayContent(windowingMode, DISPLAY_BOUNDS, DISPLAY_STABLE_BOUNDS);
+ }
+
+ private TestDisplayContent createNewDisplayContent(int windowingMode, Rect displayBounds,
+ Rect displayStableBounds) {
final TestDisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
display.getDefaultTaskDisplayArea().setWindowingMode(windowingMode);
- display.setBounds(DISPLAY_BOUNDS);
+ display.setBounds(displayBounds);
display.getConfiguration().densityDpi = DENSITY_DEFAULT;
display.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
configInsetsState(display.getInsetsStateController().getRawInsetsState(), display,
- DISPLAY_STABLE_BOUNDS);
+ displayStableBounds);
return display;
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index e055f63..db9dfbb 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -1527,7 +1527,7 @@
*/
@NonNull
public Builder setGroupUuid(@Nullable String groupUuid) {
- mGroupUuid = groupUuid == null ? null : ParcelUuid.fromString(groupUuid);
+ mGroupUuid = TextUtils.isEmpty(groupUuid) ? null : ParcelUuid.fromString(groupUuid);
return this;
}