Merge "Clear routes when media router manager has no callback" into rvc-dev
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1dadbda..85bafd9 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1695,7 +1695,7 @@
}
// Check to see if overlay should be excluded based on system property condition
- if (!checkRequiredSystemProperty(requiredSystemPropertyName,
+ if (!checkRequiredSystemProperties(requiredSystemPropertyName,
requiredSystemPropertyValue)) {
Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+ codePath + ": overlay ignored due to required system property: "
@@ -1997,7 +1997,7 @@
}
// check to see if overlay should be excluded based on system property condition
- if (!checkRequiredSystemProperty(propName, propValue)) {
+ if (!checkRequiredSystemProperties(propName, propValue)) {
Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
+ pkg.baseCodePath+ ": overlay ignored due to required system property: "
+ propName + " with value: " + propValue);
@@ -2427,24 +2427,42 @@
/**
* Returns {@code true} if both the property name and value are empty or if the given system
- * property is set to the specified value. In all other cases, returns {@code false}
+ * property is set to the specified value. Properties can be one or more, and if properties are
+ * more than one, they must be separated by comma, and count of names and values must be equal,
+ * and also every given system property must be set to the corresponding value.
+ * In all other cases, returns {@code false}
*/
- public static boolean checkRequiredSystemProperty(String propName, String propValue) {
- if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
- if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
+ public static boolean checkRequiredSystemProperties(@Nullable String rawPropNames,
+ @Nullable String rawPropValues) {
+ if (TextUtils.isEmpty(rawPropNames) || TextUtils.isEmpty(rawPropValues)) {
+ if (!TextUtils.isEmpty(rawPropNames) || !TextUtils.isEmpty(rawPropValues)) {
// malformed condition - incomplete
- Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
- + "=" + propValue + "' - require both requiredSystemPropertyName"
- + " AND requiredSystemPropertyValue to be specified.");
+ Slog.w(TAG, "Disabling overlay - incomplete property :'" + rawPropNames
+ + "=" + rawPropValues + "' - require both requiredSystemPropertyName"
+ + " AND requiredSystemPropertyValue to be specified.");
return false;
}
// no valid condition set - so no exclusion criteria, overlay will be included.
return true;
}
- // check property value - make sure it is both set and equal to expected value
- final String currValue = SystemProperties.get(propName);
- return (currValue != null && currValue.equals(propValue));
+ final String[] propNames = rawPropNames.split(",");
+ final String[] propValues = rawPropValues.split(",");
+
+ if (propNames.length != propValues.length) {
+ Slog.w(TAG, "Disabling overlay - property :'" + rawPropNames
+ + "=" + rawPropValues + "' - require both requiredSystemPropertyName"
+ + " AND requiredSystemPropertyValue lists to have the same size.");
+ return false;
+ }
+ for (int i = 0; i < propNames.length; i++) {
+ // Check property value: make sure it is both set and equal to expected value
+ final String currValue = SystemProperties.get(propNames[i]);
+ if (!TextUtils.equals(currValue, propValues[i])) {
+ return false;
+ }
+ }
+ return true;
}
/**
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 27399e4..2f416a2 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -413,7 +413,7 @@
}
// Check to see if overlay should be excluded based on system property condition
- if (!PackageParser.checkRequiredSystemProperty(requiredSystemPropertyName,
+ if (!PackageParser.checkRequiredSystemProperties(requiredSystemPropertyName,
requiredSystemPropertyValue)) {
Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+ codePath + ": overlay ignored due to required system property: "
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 29ece49..88f4c31 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -84,7 +84,6 @@
import android.os.Bundle;
import android.os.FileUtils;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.Trace;
import android.os.ext.SdkExtensions;
import android.text.TextUtils;
@@ -2348,7 +2347,7 @@
R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName);
String propValue = sa.getString(
R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
- if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
+ if (!PackageParser.checkRequiredSystemProperties(propName, propValue)) {
Slog.i(TAG, "Skipping target and overlay pair " + target + " and "
+ pkg.getBaseCodePath()
+ ": overlay ignored due to required system property: "
@@ -2522,24 +2521,6 @@
}
}
- private static boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
- if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
- if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
- // malformed condition - incomplete
- Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
- + "=" + propValue + "' - require both requiredSystemPropertyName"
- + " AND requiredSystemPropertyValue to be specified.");
- return false;
- }
- // no valid condition set - so no exclusion criteria, overlay will be included.
- return true;
- }
-
- // check property value - make sure it is both set and equal to expected value
- final String currValue = SystemProperties.get(propName);
- return (currValue != null && currValue.equals(propValue));
- }
-
/**
* This is a pre-density application which will get scaled - instead of being pixel perfect.
* This type of application is not resizable.
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index e551b69..ee8fb38 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -38,7 +38,7 @@
BluetoothMediaDevice(Context context, CachedBluetoothDevice device,
MediaRouter2Manager routerManager, MediaRoute2Info info, String packageName) {
- super(context, MediaDeviceType.TYPE_BLUETOOTH_DEVICE, routerManager, info, packageName);
+ super(context, routerManager, info, packageName);
mCachedDevice = device;
initDeviceRecord();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 85fa988..83a9671 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -38,7 +38,7 @@
InfoMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
String packageName) {
- super(context, MediaDeviceType.TYPE_CAST_DEVICE, routerManager, info, packageName);
+ super(context, routerManager, info, packageName);
initDeviceRecord();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 39e6a12..6aff301 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -15,6 +15,16 @@
*/
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_GROUP;
+import static android.media.MediaRoute2Info.TYPE_HEARING_AID;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
+import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
@@ -38,13 +48,21 @@
private static final String TAG = "MediaDevice";
@Retention(RetentionPolicy.SOURCE)
- @IntDef({MediaDeviceType.TYPE_CAST_DEVICE,
+ @IntDef({MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE,
+ MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE,
+ MediaDeviceType.TYPE_FAST_PAIR_BLUETOOTH_DEVICE,
MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
+ MediaDeviceType.TYPE_CAST_DEVICE,
+ MediaDeviceType.TYPE_CAST_GROUP_DEVICE,
MediaDeviceType.TYPE_PHONE_DEVICE})
public @interface MediaDeviceType {
- int TYPE_PHONE_DEVICE = 1;
- int TYPE_CAST_DEVICE = 2;
- int TYPE_BLUETOOTH_DEVICE = 3;
+ int TYPE_USB_C_AUDIO_DEVICE = 1;
+ int TYPE_3POINT5_MM_AUDIO_DEVICE = 2;
+ int TYPE_FAST_PAIR_BLUETOOTH_DEVICE = 3;
+ int TYPE_BLUETOOTH_DEVICE = 4;
+ int TYPE_CAST_DEVICE = 5;
+ int TYPE_CAST_GROUP_DEVICE = 6;
+ int TYPE_PHONE_DEVICE = 7;
}
@VisibleForTesting
@@ -58,13 +76,43 @@
protected final MediaRouter2Manager mRouterManager;
protected final String mPackageName;
- MediaDevice(Context context, @MediaDeviceType int type, MediaRouter2Manager routerManager,
- MediaRoute2Info info, String packageName) {
- mType = type;
+ MediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
+ String packageName) {
mContext = context;
mRouteInfo = info;
mRouterManager = routerManager;
mPackageName = packageName;
+ setType(info);
+ }
+
+ private void setType(MediaRoute2Info info) {
+ if (info == null) {
+ mType = MediaDeviceType.TYPE_BLUETOOTH_DEVICE;
+ return;
+ }
+
+ switch (info.getType()) {
+ case TYPE_GROUP:
+ mType = MediaDeviceType.TYPE_CAST_GROUP_DEVICE;
+ break;
+ case TYPE_BUILTIN_SPEAKER:
+ mType = MediaDeviceType.TYPE_PHONE_DEVICE;
+ break;
+ case TYPE_WIRED_HEADSET:
+ case TYPE_WIRED_HEADPHONES:
+ mType = MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE;
+ break;
+ case TYPE_HEARING_AID:
+ case TYPE_BLUETOOTH_A2DP:
+ mType = MediaDeviceType.TYPE_BLUETOOTH_DEVICE;
+ break;
+ case TYPE_UNKNOWN:
+ case TYPE_REMOTE_TV:
+ case TYPE_REMOTE_SPEAKER:
+ default:
+ mType = MediaDeviceType.TYPE_CAST_DEVICE;
+ break;
+ }
}
void initDeviceRecord() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index af88723..c6c5ade 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -42,7 +42,7 @@
PhoneMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
String packageName) {
- super(context, MediaDeviceType.TYPE_PHONE_DEVICE, routerManager, info, packageName);
+ super(context, routerManager, info, packageName);
initDeviceRecord();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 4b08387..db05b76 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -15,6 +15,10 @@
*/
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
@@ -144,12 +148,19 @@
when(mCachedDevice2.isConnected()).thenReturn(true);
when(mCachedDevice3.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mCachedDevice3.isConnected()).thenReturn(true);
+ when(mBluetoothRouteInfo1.getType()).thenReturn(TYPE_BLUETOOTH_A2DP);
+ when(mBluetoothRouteInfo2.getType()).thenReturn(TYPE_BLUETOOTH_A2DP);
+ when(mBluetoothRouteInfo3.getType()).thenReturn(TYPE_BLUETOOTH_A2DP);
when(mRouteInfo1.getId()).thenReturn(ROUTER_ID_1);
when(mRouteInfo2.getId()).thenReturn(ROUTER_ID_2);
when(mRouteInfo3.getId()).thenReturn(ROUTER_ID_3);
when(mRouteInfo1.getName()).thenReturn(DEVICE_NAME_1);
when(mRouteInfo2.getName()).thenReturn(DEVICE_NAME_2);
when(mRouteInfo3.getName()).thenReturn(DEVICE_NAME_3);
+ when(mRouteInfo1.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
+ when(mRouteInfo2.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
+ when(mRouteInfo3.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
+ when(mPhoneRouteInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
@@ -271,12 +282,12 @@
@Test
public void compareTo_info_bluetooth_infoFirst() {
- mMediaDevices.add(mBluetoothMediaDevice1);
mMediaDevices.add(mInfoMediaDevice1);
+ mMediaDevices.add(mBluetoothMediaDevice1);
- assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
- Collections.sort(mMediaDevices, COMPARATOR);
assertThat(mMediaDevices.get(0)).isEqualTo(mInfoMediaDevice1);
+ Collections.sort(mMediaDevices, COMPARATOR);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
}
@Test
@@ -327,7 +338,7 @@
// 5.mBluetoothMediaDevice2: * 2 times usage
// 6.mBluetoothMediaDevice3: * 1 time usage
// 7.mPhoneMediaDevice: * 0 time usage
- // Order: 7 -> 2 -> 1 -> 3 -> 5 -> 4 -> 6
+ // Order: 7 -> 2 -> 1 -> 5 -> 3 -> 6 -> 4
@Test
public void compareTo_mixedDevices_carKitFirst() {
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
@@ -352,10 +363,10 @@
assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice1);
assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice1);
- assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice2);
- assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice2);
- assertThat(mMediaDevices.get(5)).isEqualTo(mInfoMediaDevice3);
- assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice3);
+ assertThat(mMediaDevices.get(3)).isEqualTo(mBluetoothMediaDevice2);
+ assertThat(mMediaDevices.get(4)).isEqualTo(mInfoMediaDevice2);
+ assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice3);
+ assertThat(mMediaDevices.get(6)).isEqualTo(mInfoMediaDevice3);
}
// 1.mInfoMediaDevice1: Last Selected device
@@ -365,7 +376,7 @@
// 5.mBluetoothMediaDevice2: * 4 times usage not connected
// 6.mBluetoothMediaDevice3: * 1 time usage
// 7.mPhoneMediaDevice: * 0 time usage
- // Order: 7 -> 1 -> 3 -> 4 -> 6 -> 2 -> 5
+ // Order: 7 -> 1 -> 3 -> 6 -> 4 -> 2 -> 5
@Test
public void compareTo_mixedDevices_connectDeviceFirst() {
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
@@ -394,8 +405,8 @@
assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
assertThat(mMediaDevices.get(1)).isEqualTo(mInfoMediaDevice1);
assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice2);
- assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice3);
- assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice3);
+ assertThat(mMediaDevices.get(3)).isEqualTo(mBluetoothMediaDevice3);
+ assertThat(mMediaDevices.get(4)).isEqualTo(mInfoMediaDevice3);
assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice1);
assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice2);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index f21f0e7..1a72cf0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2732,7 +2732,7 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
- new AccessibilityShellCommand(this).exec(this, in, out, err, args,
+ new AccessibilityShellCommand(this, mSystemActionPerformer).exec(this, in, out, err, args,
callback, resultReceiver);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityShellCommand.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityShellCommand.java
index 20a11bd..b36626f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityShellCommand.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityShellCommand.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.os.Binder;
+import android.os.Process;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -28,9 +30,12 @@
*/
final class AccessibilityShellCommand extends ShellCommand {
final @NonNull AccessibilityManagerService mService;
+ final @NonNull SystemActionPerformer mSystemActionPerformer;
- AccessibilityShellCommand(@NonNull AccessibilityManagerService service) {
+ AccessibilityShellCommand(@NonNull AccessibilityManagerService service,
+ @NonNull SystemActionPerformer systemActionPerformer) {
mService = service;
+ mSystemActionPerformer = systemActionPerformer;
}
@Override
@@ -45,6 +50,9 @@
case "set-bind-instant-service-allowed": {
return runSetBindInstantServiceAllowed();
}
+ case "call-system-action": {
+ return runCallSystemAction();
+ }
}
return -1;
}
@@ -74,6 +82,22 @@
return 0;
}
+ private int runCallSystemAction() {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.ROOT_UID
+ && callingUid != Process.SYSTEM_UID
+ && callingUid != Process.SHELL_UID) {
+ return -1;
+ }
+ final String option = getNextArg();
+ if (option != null) {
+ int actionId = Integer.parseInt(option);
+ mSystemActionPerformer.performSystemAction(actionId);
+ return 0;
+ }
+ return -1;
+ }
+
private Integer parseUserId() {
final String option = getNextOption();
if (option != null) {
@@ -97,5 +121,7 @@
pw.println(" Set whether binding to services provided by instant apps is allowed.");
pw.println(" get-bind-instant-service-allowed [--user <USER_ID>]");
pw.println(" Get whether binding to services provided by instant apps is allowed.");
+ pw.println(" call-system-action <ACTION_ID>");
+ pw.println(" Calls the system action with the given action id.");
}
}
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index ffae770..b9e3050 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -305,6 +305,7 @@
sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
return true;
default:
+ Slog.e(TAG, "Invalid action id: " + actionId);
return false;
}
} finally {
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index c27ec66..63b56e0 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -480,6 +480,12 @@
public abstract void pruneInstantApps();
/**
+ * Prunes the cache of the APKs in the given APEXes.
+ * @param apexPackages The list of APEX packages that may contain APK-in-APEX.
+ */
+ public abstract void pruneCachedApksInApex(@NonNull List<PackageInfo> apexPackages);
+
+ /**
* @return The SetupWizard package name.
*/
public abstract String getSetupWizardPackageName();
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 28f8380..3cf22c8 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -215,7 +215,6 @@
.setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
.setDescription(mContext.getResources().getText(
R.string.bluetooth_a2dp_audio_route_name).toString())
- //TODO: Set type correctly (BLUETOOTH_A2DP or HEARING_AID)
.setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP)
.setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.build();
@@ -236,6 +235,8 @@
// Update volume when the connection state is changed.
MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route)
.setConnectionState(state);
+ builder.setType(btRoute.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)
+ ? MediaRoute2Info.TYPE_HEARING_AID : MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 1345e37..41d7fff 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -19,6 +19,11 @@
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -194,19 +199,27 @@
private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
if (newRoutes != null) {
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
- if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
- || (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
name = com.android.internal.R.string.default_audio_route_name_headphones;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
name = com.android.internal.R.string.default_audio_route_name_hdmi;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
name = com.android.internal.R.string.default_audio_route_name_usb;
}
}
+
mDeviceRoute = new MediaRoute2Info.Builder(
DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
.setVolumeHandling(mAudioManager.isVolumeFixed()
@@ -214,8 +227,7 @@
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
- //TODO: Guess the exact type using AudioDevice
- .setType(TYPE_BUILTIN_SPEAKER)
+ .setType(type)
.addFeature(FEATURE_LIVE_AUDIO)
.addFeature(FEATURE_LIVE_VIDEO)
.setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2221644..6b1ef3a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -150,7 +150,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -2099,11 +2098,13 @@
continue;
}
- mResolvedInstructionSets.add(archSubDir.getName());
- List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
- if (!oatFiles.isEmpty()) {
- mResolvedInheritedFiles.addAll(oatFiles);
+ File[] files = archSubDir.listFiles();
+ if (files == null || files.length == 0) {
+ continue;
}
+
+ mResolvedInstructionSets.add(archSubDir.getName());
+ mResolvedInheritedFiles.addAll(Arrays.asList(files));
}
}
}
@@ -2117,7 +2118,8 @@
if (!libDir.exists() || !libDir.isDirectory()) {
continue;
}
- final List<File> libDirsToInherit = new LinkedList<>();
+ final List<String> libDirsToInherit = new ArrayList<>();
+ final List<File> libFilesToInherit = new ArrayList<>();
for (File archSubDir : libDir.listFiles()) {
if (!archSubDir.isDirectory()) {
continue;
@@ -2129,14 +2131,24 @@
Slog.e(TAG, "Skipping linking of native library directory!", e);
// shouldn't be possible, but let's avoid inheriting these to be safe
libDirsToInherit.clear();
+ libFilesToInherit.clear();
break;
}
- if (!mResolvedNativeLibPaths.contains(relLibPath)) {
- mResolvedNativeLibPaths.add(relLibPath);
+
+ File[] files = archSubDir.listFiles();
+ if (files == null || files.length == 0) {
+ continue;
}
- libDirsToInherit.addAll(Arrays.asList(archSubDir.listFiles()));
+
+ libDirsToInherit.add(relLibPath);
+ libFilesToInherit.addAll(Arrays.asList(files));
}
- mResolvedInheritedFiles.addAll(libDirsToInherit);
+ for (String subDir : libDirsToInherit) {
+ if (!mResolvedNativeLibPaths.contains(subDir)) {
+ mResolvedNativeLibPaths.add(subDir);
+ }
+ }
+ mResolvedInheritedFiles.addAll(libFilesToInherit);
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9f543b4..5447bcb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -351,6 +351,7 @@
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.dex.ViewCompiler;
+import com.android.server.pm.parsing.PackageCacher;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.library.PackageBackwardCompatibility;
@@ -24232,6 +24233,25 @@
}
@Override
+ public void pruneCachedApksInApex(@NonNull List<PackageInfo> apexPackages) {
+ if (mCacheDir == null) {
+ return;
+ }
+
+ final PackageCacher cacher = new PackageCacher(mCacheDir);
+ synchronized (mLock) {
+ for (int i = 0, size = apexPackages.size(); i < size; i++) {
+ final List<String> apkNames =
+ mApexManager.getApksInApex(apexPackages.get(i).packageName);
+ for (int j = 0, apksInApex = apkNames.size(); j < apksInApex; j++) {
+ final AndroidPackage pkg = getPackage(apkNames.get(j));
+ cacher.cleanCachedResult(new File(pkg.getCodePath()));
+ }
+ }
+ }
+ }
+
+ @Override
public String getSetupWizardPackageName() {
return mSetupWizardPackage;
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index d1d9877..1c1e64d 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1226,8 +1226,9 @@
// APEX checks. For single-package sessions, check if they contain an APEX. For
// multi-package sessions, find all the child sessions that contain an APEX.
if (hasApex) {
+ final List<PackageInfo> apexPackages;
try {
- final List<PackageInfo> apexPackages = submitSessionToApexService(session);
+ apexPackages = submitSessionToApexService(session);
for (int i = 0, size = apexPackages.size(); i < size; i++) {
validateApexSignature(apexPackages.get(i));
}
@@ -1235,6 +1236,10 @@
session.setStagedSessionFailed(e.error, e.getMessage());
return;
}
+
+ final PackageManagerInternal packageManagerInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ packageManagerInternal.pruneCachedApksInApex(apexPackages);
}
notifyPreRebootVerification_Apex_Complete(session.sessionId);
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index e5e1b0b..99c6dd1 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.content.pm.PackageParserCacheHelper;
+import android.os.FileUtils;
import android.os.Parcel;
import android.system.ErrnoException;
import android.system.Os;
@@ -197,4 +198,18 @@
Slog.w(TAG, "Error saving package cache.", e);
}
}
+
+ /**
+ * Delete the cache files for the given {@code packageFile}.
+ */
+ public void cleanCachedResult(@NonNull File packageFile) {
+ final String packageName = packageFile.getName();
+ final File[] files = FileUtils.listFilesOrEmpty(mCacheDir,
+ (dir, name) -> name.startsWith(packageName));
+ for (File file : files) {
+ if (!file.delete()) {
+ Slog.e(TAG, "Unable to clean cache file: " + file);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e76eda0..2648c86 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4712,7 +4712,7 @@
*/
private boolean shouldBeResumed(ActivityRecord activeActivity) {
return shouldMakeActive(activeActivity) && isFocusable()
- && getRootTask().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
+ && getTask().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
&& canResumeByCompat();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 0f57496..ff43e77 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -18,11 +18,8 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -142,13 +139,11 @@
import android.os.Trace;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.SurfaceControl;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -157,7 +152,6 @@
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -276,11 +270,6 @@
Rect mPreAnimationBounds = new Rect();
- /**
- * For {@link #prepareSurfaces}.
- */
- private final Point mLastSurfaceSize = new Point();
-
private final AnimatingActivityRegistry mAnimatingActivityRegistry =
new AnimatingActivityRegistry();
@@ -606,10 +595,6 @@
super.onConfigurationChanged(newParentConfig);
- // Only need to update surface size here since the super method will handle updating
- // surface position.
- updateSurfaceSize(getPendingTransaction());
-
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (taskDisplayArea == null) {
return;
@@ -3262,61 +3247,14 @@
scheduleAnimation();
}
- /**
- * Calculate an amount by which to expand the stack bounds in each direction.
- * Used to make room for shadows in the pinned windowing mode.
- */
- int getStackOutset() {
- // If we are drawing shadows on the task then don't outset the stack.
- if (mWmService.mRenderShadowsInCompositor) {
- return 0;
- }
- DisplayContent displayContent = getDisplayContent();
- if (inPinnedWindowingMode() && displayContent != null) {
- final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
-
- // We multiply by two to match the client logic for converting view elevation
- // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
- return (int) Math.ceil(
- mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
- * 2);
- }
- return 0;
- }
-
@Override
void getRelativePosition(Point outPos) {
super.getRelativePosition(outPos);
- final int outset = getStackOutset();
+ final int outset = getTaskOutset();
outPos.x -= outset;
outPos.y -= outset;
}
- private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
- if (mSurfaceControl == null) {
- return;
- }
-
- final Rect stackBounds = getBounds();
- int width = stackBounds.width();
- int height = stackBounds.height();
-
- final int outset = getStackOutset();
- width += 2 * outset;
- height += 2 * outset;
-
- if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
- return;
- }
- transaction.setWindowCrop(mSurfaceControl, width, height);
- mLastSurfaceSize.set(width, height);
- }
-
- @VisibleForTesting
- Point getLastSurfaceSize() {
- return mLastSurfaceSize;
- }
-
@Override
void onDisplayChanged(DisplayContent dc) {
super.onDisplayChanged(dc);
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 5f33ea1..9d44cad 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -597,8 +597,8 @@
return startAnimation(initializeBuilder()
.setSurfaceControl(mScreenshotLayer)
.setAnimationLeashParent(mDisplayContent.getOverlayLayer())
- .setWidth(mWidth)
- .setHeight(mHeight)
+ .setWidth(mDisplayContent.getSurfaceWidth())
+ .setHeight(mDisplayContent.getSurfaceHeight())
.build(),
createWindowAnimationSpec(mRotateAlphaAnimation),
this::onAnimationEnd);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 66ca0ac..df5cfee 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -120,6 +120,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
@@ -213,7 +214,6 @@
static final int INVALID_MIN_SIZE = -1;
private float mShadowRadius = 0;
- private final Rect mLastSurfaceCrop = new Rect();
/**
* The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
@@ -397,6 +397,7 @@
private Dimmer mDimmer = new Dimmer(this);
private final Rect mTmpDimBoundsRect = new Rect();
+ private final Point mLastSurfaceSize = new Point();
/** @see #setCanAffectSystemUiFlags */
private boolean mCanAffectSystemUiFlags = true;
@@ -1943,6 +1944,10 @@
mTmpPrevBounds.set(getBounds());
final boolean wasInMultiWindowMode = inMultiWindowMode();
super.onConfigurationChanged(newParentConfig);
+ // Only need to update surface size here since the super method will handle updating
+ // surface position.
+ updateSurfaceSize(getPendingTransaction());
+
if (wasInMultiWindowMode != inMultiWindowMode()) {
mStackSupervisor.scheduleUpdateMultiWindowMode(this);
}
@@ -1995,6 +2000,57 @@
return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
}
+ void updateSurfaceSize(SurfaceControl.Transaction transaction) {
+ if (mSurfaceControl == null || mCreatedByOrganizer) {
+ return;
+ }
+
+ // Apply crop to root tasks only and clear the crops of the descendant tasks.
+ int width = 0;
+ int height = 0;
+ if (isRootTask()) {
+ final Rect taskBounds = getBounds();
+ width = taskBounds.width();
+ height = taskBounds.height();
+
+ final int outset = getTaskOutset();
+ width += 2 * outset;
+ height += 2 * outset;
+ }
+ if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
+ return;
+ }
+ transaction.setWindowCrop(mSurfaceControl, width, height);
+ mLastSurfaceSize.set(width, height);
+ }
+
+ /**
+ * Calculate an amount by which to expand the task bounds in each direction.
+ * Used to make room for shadows in the pinned windowing mode.
+ */
+ int getTaskOutset() {
+ // If we are drawing shadows on the task then don't outset the stack.
+ if (mWmService.mRenderShadowsInCompositor) {
+ return 0;
+ }
+ DisplayContent displayContent = getDisplayContent();
+ if (inPinnedWindowingMode() && displayContent != null) {
+ final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
+
+ // We multiply by two to match the client logic for converting view elevation
+ // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
+ return (int) Math.ceil(
+ mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
+ * 2);
+ }
+ return 0;
+ }
+
+ @VisibleForTesting
+ Point getLastSurfaceSize() {
+ return mLastSurfaceSize;
+ }
+
@VisibleForTesting
boolean isInChangeTransition() {
return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransit(mTransit);
@@ -2225,14 +2281,16 @@
}
density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ // If bounds have been overridden at this level, restrict config resources to these bounds
+ // rather than the parent because the overridden bounds can be larger than the parent.
+ boolean hasOverrideBounds = false;
+
final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
- if (resolvedBounds == null) {
- mTmpFullBounds.setEmpty();
+ if (resolvedBounds == null || resolvedBounds.isEmpty()) {
+ mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
} else {
mTmpFullBounds.set(resolvedBounds);
- }
- if (mTmpFullBounds.isEmpty()) {
- mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
+ hasOverrideBounds = true;
}
Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
@@ -2244,7 +2302,16 @@
// the out bounds doesn't need to be restricted by the parent.
final boolean insideParentBounds = compatInsets == null;
if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
- final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
+ Rect parentAppBounds;
+ if (hasOverrideBounds) {
+ // Since we overrode the bounds, restrict appBounds to display non-decor rather
+ // than parent. Otherwise, it won't match the overridden bounds.
+ final TaskDisplayArea displayArea = getDisplayArea();
+ parentAppBounds = displayArea != null
+ ? displayArea.getConfiguration().windowConfiguration.getAppBounds() : null;
+ } else {
+ parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
+ }
if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
outAppBounds.intersect(parentAppBounds);
}
@@ -2291,13 +2358,13 @@
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
- inOutConfig.screenWidthDp = insideParentBounds
+ inOutConfig.screenWidthDp = (insideParentBounds && !hasOverrideBounds)
? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
: overrideScreenWidthDp;
}
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
- inOutConfig.screenHeightDp = insideParentBounds
+ inOutConfig.screenHeightDp = (insideParentBounds && !hasOverrideBounds)
? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
: overrideScreenHeightDp;
}
@@ -2344,27 +2411,27 @@
mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
super.resolveOverrideConfiguration(newParentConfig);
- // Resolve override windowing mode to fullscreen for home task (even on freeform
- // display), or split-screen-secondary if in split-screen mode.
int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
+
+ // Resolve override windowing mode to fullscreen for home task (even on freeform
+ // display), or split-screen if in split-screen mode.
if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
- windowingMode = parentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- : WINDOWING_MODE_FULLSCREEN;
+ windowingMode = WindowConfiguration.isSplitScreenWindowingMode(parentWindowingMode)
+ ? parentWindowingMode : WINDOWING_MODE_FULLSCREEN;
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
}
- if (!isLeafTask()) {
- // Compute configuration overrides for tasks that created by organizer, so that
- // organizer can get the correct configuration from those tasks.
- if (mCreatedByOrganizer) {
- computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
- }
- return;
+ if (isLeafTask()) {
+ resolveLeafOnlyOverrideConfigs(newParentConfig);
}
+ computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
+ }
+ void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig) {
+ int windowingMode =
+ getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
}
@@ -2404,7 +2471,6 @@
outOverrideBounds.offset(0, offsetTop);
}
}
- computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
}
/**
@@ -2803,28 +2869,6 @@
return boundsChange;
}
- private void updateSurfaceCrop() {
- // Only update the crop if we are drawing shadows on the task.
- if (mSurfaceControl == null || !mWmService.mRenderShadowsInCompositor || !isRootTask()) {
- return;
- }
-
- if (inSplitScreenWindowingMode()) {
- // inherit crop from parent
- mTmpRect.setEmpty();
- } else {
- getBounds(mTmpRect);
- }
-
- mTmpRect.offsetTo(0, 0);
- if (mLastSurfaceCrop.equals(mTmpRect)) {
- return;
- }
-
- getPendingTransaction().setWindowCrop(mSurfaceControl, mTmpRect);
- mLastSurfaceCrop.set(mTmpRect);
- }
-
@Override
public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
ConfigurationContainer requestingContainer) {
@@ -3453,7 +3497,6 @@
mTmpDimBoundsRect.offsetTo(0, 0);
}
- updateSurfaceCrop();
updateShadowsRadius(isFocused(), getPendingTransaction());
if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 83e7ad5..ef690e1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5289,7 +5289,7 @@
// to account for it. If we actually have shadows we will
// then un-inset ourselves by the surfaceInsets.
if (stack != null) {
- final int outset = stack.getStackOutset();
+ final int outset = stack.getTaskOutset();
outPoint.offset(outset, outset);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 6ae8313..0700f9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -329,6 +329,7 @@
private boolean mCreateStack = true;
private ActivityStack mStack;
+ private TaskDisplayArea mTaskDisplayArea;
TaskBuilder(ActivityStackSupervisor supervisor) {
mSupervisor = supervisor;
@@ -378,9 +379,16 @@
return this;
}
+ TaskBuilder setDisplay(DisplayContent display) {
+ mTaskDisplayArea = display.getDefaultTaskDisplayArea();
+ return this;
+ }
+
Task build() {
if (mStack == null && mCreateStack) {
- mStack = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
+ TaskDisplayArea displayArea = mTaskDisplayArea != null ? mTaskDisplayArea
+ : mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ mStack = displayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
spyOn(mStack);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index be25597..e887be0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -33,6 +33,7 @@
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Build/Install/Run:
@@ -40,6 +41,7 @@
*/
@SmallTest
@Presubmit
+@RunWith(WindowTestRunner.class)
@FlakyTest
public class RefreshRatePolicyTest extends WindowTestsBase {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 519ac78..dcc2ff1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -54,10 +54,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.app.TaskInfo;
@@ -75,12 +72,10 @@
import android.util.Xml;
import android.view.DisplayInfo;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.wm.Task.TaskFactory;
-import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before;
import org.junit.Test;
@@ -368,25 +363,38 @@
@Test
public void testComputeConfigResourceOverrides() {
- final Task task = new TaskBuilder(mSupervisor).build();
+ final Rect fullScreenBounds = new Rect(0, 0, 1080, 1920);
+ TestDisplayContent display = new TestDisplayContent.Builder(
+ mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
+ final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build();
final Configuration inOutConfig = new Configuration();
final Configuration parentConfig = new Configuration();
final int longSide = 1200;
final int shortSide = 600;
+ final Rect parentBounds = new Rect(0, 0, 250, 500);
+ parentConfig.windowConfiguration.setBounds(parentBounds);
parentConfig.densityDpi = 400;
- parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
- parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
+ parentConfig.screenHeightDp = (parentBounds.bottom * 160) / parentConfig.densityDpi; // 200
+ parentConfig.screenWidthDp = (parentBounds.right * 160) / parentConfig.densityDpi; // 100
parentConfig.windowConfiguration.setRotation(ROTATION_0);
- // Portrait bounds.
- inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
- // By default, the parent bounds should limit the existing input bounds.
+ // By default, the input bounds will fill parent.
task.computeConfigResourceOverrides(inOutConfig, parentConfig);
assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation);
+ // If bounds are overridden, config properties should be made to match. Surface hierarchy
+ // will crop for policy.
+ inOutConfig.setToDefaults();
+ inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
+ // By default, the parent bounds should limit the existing input bounds.
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(longSide, inOutConfig.screenHeightDp * parentConfig.densityDpi / 160);
+ assertEquals(shortSide, inOutConfig.screenWidthDp * parentConfig.densityDpi / 160);
+
inOutConfig.setToDefaults();
// Landscape bounds.
inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide);
@@ -394,21 +402,17 @@
// Setup the display with a top stable inset. The later assertion will ensure the inset is
// excluded from screenHeightDp.
final int statusBarHeight = 100;
- final DisplayContent displayContent = task.mDisplayContent;
- final DisplayPolicy policy = mock(DisplayPolicy.class);
+ final DisplayPolicy policy = display.getDisplayPolicy();
doAnswer(invocationOnMock -> {
final Rect insets = invocationOnMock.<Rect>getArgument(0);
insets.top = statusBarHeight;
return null;
}).when(policy).convertNonDecorInsetsToStableInsets(any(), eq(ROTATION_0));
- doReturn(policy).when(displayContent).getDisplayPolicy();
- doReturn(mock(WmDisplayCutout.class)).when(displayContent)
- .calculateDisplayCutoutForRotation(anyInt());
// Without limiting to be inside the parent bounds, the out screen size should keep relative
// to the input bounds.
final ActivityRecord.CompatDisplayInsets compatIntsets =
- new ActivityRecord.CompatDisplayInsets(displayContent, task);
+ new ActivityRecord.CompatDisplayInsets(display, task);
task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);
assertEquals((shortSide - statusBarHeight) * DENSITY_DEFAULT / parentConfig.densityDpi,
@@ -454,7 +458,6 @@
parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
parentConfig.windowConfiguration.setRotation(ROTATION_0);
- final float density = 2.5f; // densityDpi / DENSITY_DEFAULT_SCALE = 400 / 160.0f
final int longSideDp = 480; // longSide / density = 1200 / 400 * 160
final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160
final int screenLayout = parentConfig.screenLayout
@@ -463,31 +466,38 @@
Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp);
// Portrait bounds overlapping with navigation bar, without insets.
- inOutConfig.windowConfiguration.getBounds().set(0,
+ final Rect freeformBounds = new Rect(0,
displayHeight - 10 - longSide,
shortSide,
displayHeight - 10);
+ inOutConfig.windowConfiguration.setBounds(freeformBounds);
// Set to freeform mode to verify bug fix.
inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
task.computeConfigResourceOverrides(inOutConfig, parentConfig);
- assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
- assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ // screenW/H should not be effected by parent since overridden and freeform
+ assertEquals(freeformBounds.width() * 160 / parentConfig.densityDpi,
+ inOutConfig.screenWidthDp);
+ assertEquals(freeformBounds.height() * 160 / parentConfig.densityDpi,
+ inOutConfig.screenHeightDp);
assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
inOutConfig.setToDefaults();
// Landscape bounds overlapping with navigtion bar, without insets.
- inOutConfig.windowConfiguration.getBounds().set(0,
+ freeformBounds.set(0,
displayHeight - 10 - shortSide,
longSide,
displayHeight - 10);
+ inOutConfig.windowConfiguration.setBounds(freeformBounds);
inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
task.computeConfigResourceOverrides(inOutConfig, parentConfig);
- assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
- assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(freeformBounds.width() * 160 / parentConfig.densityDpi,
+ inOutConfig.screenWidthDp);
+ assertEquals(freeformBounds.height() * 160 / parentConfig.densityDpi,
+ inOutConfig.screenHeightDp);
assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 7cb5e84..f354a04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -186,7 +186,7 @@
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final int stackOutset = 10;
spyOn(stack);
- doReturn(stackOutset).when(stack).getStackOutset();
+ doReturn(stackOutset).when(stack).getTaskOutset();
doReturn(true).when(stack).inMultiWindowMode();
// Mock the resolved override windowing mode to non-fullscreen
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 53cc09b..f65328d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -44,7 +44,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -407,22 +406,20 @@
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction();
- t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
final int origScreenWDp = task.getConfiguration().screenHeightDp;
final int origScreenHDp = task.getConfiguration().screenHeightDp;
t = new WindowContainerTransaction();
// verify that setting config overrides on parent restricts children.
t.setScreenSizeDp(stack.mRemoteToken
- .toWindowContainerToken(), origScreenWDp, origScreenHDp);
- t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 150, 200));
+ .toWindowContainerToken(), origScreenWDp, origScreenHDp / 2);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
- assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
+ assertEquals(origScreenHDp / 2, task.getConfiguration().screenHeightDp);
t = new WindowContainerTransaction();
t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
SCREEN_HEIGHT_DP_UNDEFINED);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
- assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
+ assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
}
@Test