Merge "[base] Migrate deprecated GL GrBackendRenderTarget constructor" into main
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7be4b15..0255860 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2876,16 +2876,25 @@
final SuspendDialogInfo dialogInfo = !TextUtils.isEmpty(dialogMessage)
? new SuspendDialogInfo.Builder().setMessage(dialogMessage).build()
: null;
- return setPackagesSuspended(packageNames, suspended, appExtras, launcherExtras, dialogInfo);
+ return setPackagesSuspended(packageNames, suspended, appExtras, launcherExtras,
+ dialogInfo, 0);
}
@Override
public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
PersistableBundle appExtras, PersistableBundle launcherExtras,
SuspendDialogInfo dialogInfo) {
+ return setPackagesSuspended(packageNames, suspended, appExtras, launcherExtras,
+ dialogInfo, 0);
+ }
+
+ @Override
+ public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
+ PersistableBundle appExtras, PersistableBundle launcherExtras,
+ SuspendDialogInfo dialogInfo, int flags) {
try {
return mPM.setPackagesSuspendedAsUser(packageNames, suspended, appExtras,
- launcherExtras, dialogInfo, mContext.getOpPackageName(),
+ launcherExtras, dialogInfo, flags, mContext.getOpPackageName(),
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c11a8fc..5ef7b11 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -323,6 +323,7 @@
// Make sure no flag uses the sign bit (most significant bit) of the long integer,
// to avoid future confusion.
BIND_BYPASS_USER_NETWORK_RESTRICTIONS,
+ BIND_FILTER_OUT_QUARANTINED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface BindServiceFlagsLongBits {}
@@ -697,6 +698,13 @@
*/
public static final long BIND_BYPASS_USER_NETWORK_RESTRICTIONS = 0x1_0000_0000L;
+ /**
+ * Flag for {@link #bindService}.
+ *
+ * @hide
+ */
+ public static final long BIND_FILTER_OUT_QUARANTINED_COMPONENTS = 0x2_0000_0000L;
+
/**
* These bind flags reduce the strength of the binding such that we shouldn't
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index fe108a5..afeb3d29 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6383,6 +6383,15 @@
"android.intent.extra.changed_uid_list";
/**
+ * This field is part of
+ * {@link android.content.Intent#ACTION_PACKAGES_SUSPENDED},
+ * and only present if the packages were quarantined.
+ * @hide
+ */
+ public static final String EXTRA_QUARANTINED =
+ "android.intent.extra.quarantined";
+
+ /**
* An integer denoting a bitwise combination of restrictions set on distracting packages via
* {@link PackageManager#setDistractingPackageRestrictions(String[], int)}
*
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 7c9ccba..c5585af 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -298,7 +298,7 @@
String[] setPackagesSuspendedAsUser(in String[] packageNames, boolean suspended,
in PersistableBundle appExtras, in PersistableBundle launcherExtras,
- in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
+ in SuspendDialogInfo dialogInfo, int flags, String callingPackage, int userId);
String[] getUnsuspendablePackagesForUser(in String[] packageNames, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9f14c97..885e67e1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -834,6 +834,7 @@
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ FILTER_OUT_QUARANTINED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ComponentInfoFlagsBits {}
@@ -857,7 +858,8 @@
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
- MATCH_CLONE_PROFILE
+ MATCH_CLONE_PROFILE,
+ FILTER_OUT_QUARANTINED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResolveInfoFlagsBits {}
@@ -1233,6 +1235,11 @@
public static final long GET_ATTRIBUTIONS_LONG = 0x80000000L;
/**
+ * @hide
+ */
+ public static final long FILTER_OUT_QUARANTINED_COMPONENTS = 0x100000000L;
+
+ /**
* Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
* resolving an intent that matches the {@code CrossProfileIntentFilter},
* the current profile will be skipped. Only activities in the target user
@@ -1685,7 +1692,7 @@
/** @hide */
@IntDef(flag = true, value = {
DONT_KILL_APP,
- SYNCHRONOUS
+ SYNCHRONOUS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EnabledFlags {}
@@ -1708,6 +1715,24 @@
public static final int SYNCHRONOUS = 0x00000002;
/** @hide */
+ @IntDef(flag = true, value = {
+ FLAG_SUSPEND_QUARANTINED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SuspendedFlags {}
+
+ /**
+ * Flag parameter {@link #setPackagesSuspended(String[], boolean, PersistableBundle,
+ * PersistableBundle, android.content.pm.SuspendDialogInfo, int)}:
+ * Apps in this state not only appear suspended for all user visible purposes (eg, Launcher,
+ * ShareSheet), but also individual components of the app can behave as disabled depending on
+ * the importance of the calling app.
+ *
+ * @hide
+ */
+ public static final int FLAG_SUSPEND_QUARANTINED = 0x00000001;
+
+ /** @hide */
@IntDef(prefix = { "INSTALL_REASON_" }, value = {
INSTALL_REASON_UNKNOWN,
INSTALL_REASON_POLICY,
@@ -9654,6 +9679,63 @@
}
/**
+ * Puts the given packages in a suspended state, where attempts at starting activities are
+ * denied.
+ *
+ * <p>The suspended application's notifications and all of its windows will be hidden, any
+ * of its started activities will be stopped and it won't be able to ring the device.
+ * It doesn't remove the data or the actual package file.
+ *
+ * <p>When the user tries to launch a suspended app, a system dialog alerting them that the app
+ * is suspended will be shown instead.
+ * The caller can optionally customize the dialog by passing a {@link SuspendDialogInfo} object
+ * to this API. This dialog will have a button that starts the
+ * {@link Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} intent if the suspending app declares an
+ * activity which handles this action.
+ *
+ * <p>The packages being suspended must already be installed. If a package is uninstalled, it
+ * will no longer be suspended.
+ *
+ * <p>Optionally, the suspending app can provide extra information in the form of
+ * {@link PersistableBundle} objects to be shared with the apps being suspended and the
+ * launcher to support customization that they might need to handle the suspended state.
+ *
+ * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} to use this API except for
+ * device owner and profile owner.
+ *
+ * @param packageNames The names of the packages to set the suspended status.
+ * @param suspended If set to {@code true}, the packages will be suspended, if set to
+ * {@code false}, the packages will be unsuspended.
+ * @param appExtras An optional {@link PersistableBundle} that the suspending app can provide
+ * which will be shared with the apps being suspended. Ignored if
+ * {@code suspended} is false.
+ * @param launcherExtras An optional {@link PersistableBundle} that the suspending app can
+ * provide which will be shared with the launcher. Ignored if
+ * {@code suspended} is false.
+ * @param dialogInfo An optional {@link SuspendDialogInfo} object describing the dialog that
+ * should be shown to the user when they try to launch a suspended app.
+ * Ignored if {@code suspended} is false.
+ * @param flags Optional behavior flags.
+ *
+ * @return an array of package names for which the suspended status could not be set as
+ * requested in this method. Returns {@code null} if {@code packageNames} was {@code null}.
+ *
+ * @see #isPackageSuspended
+ * @see SuspendDialogInfo
+ * @see SuspendDialogInfo.Builder
+ * @see Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS
+ *
+ * @hide
+ */
+ @RequiresPermission(value=Manifest.permission.SUSPEND_APPS, conditional=true)
+ @Nullable
+ public String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended,
+ @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras,
+ @Nullable SuspendDialogInfo dialogInfo, @SuspendedFlags int flags) {
+ throw new UnsupportedOperationException("setPackagesSuspended not implemented");
+ }
+
+ /**
* Returns any packages in a given set of packages that cannot be suspended via a call to {@link
* #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
* SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 048289f..9387ae1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -8005,7 +8005,7 @@
ai.enabled = true;
} else if (state.getEnabledState()
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
- ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
+ ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
} else if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|| state.getEnabledState()
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7a96fd2..e1de05b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6948,6 +6948,7 @@
// something is going to start.
opts.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
+ opts.setPendingIntentBackgroundActivityLaunchAllowedByPermission(true);
return Pair.create(intent, opts);
}
}
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index a5e775a..1e0b2a0 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -297,7 +297,7 @@
final IPackageManager ipm = AppGlobals.getPackageManager();
try {
final String[] errored = ipm.setPackagesSuspendedAsUser(
- new String[]{mSuspendedPackage}, false, null, null, null,
+ new String[]{mSuspendedPackage}, false, null, null, null, 0,
mSuspendingPackage, mUserId);
if (ArrayUtils.contains(errored, mSuspendedPackage)) {
Slog.e(TAG, "Could not unsuspend " + mSuspendedPackage);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 58106c0..bb67bbc3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -441,7 +441,7 @@
String.valueOf(Global.Wearable.TETHERED_CONFIG_TETHERED)
}));
VALIDATORS.put(Global.Wearable.PHONE_SWITCHING_SUPPORTED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Global.Wearable.WEAR_LAUNCHER_UI_MODE, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Global.Wearable.WEAR_LAUNCHER_UI_MODE, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Global.Wearable.WEAR_POWER_ANOMALY_SERVICE_ENABLED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media.xml b/packages/SystemUI/res/drawable-television/ic_volume_media.xml
deleted file mode 100644
index 6a368d5..0000000
--- a/packages/SystemUI/res/drawable-television/ic_volume_media.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/tv_volume_icons_size"
- android:height="@dimen/tv_volume_icons_size"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="@color/tv_volume_dialog_accent"
- android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM10,8.83v6.34L7.83,13L5,13v-2h2.83L10,8.83zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77 0,-4.28 -2.99,-7.86 -7,-8.77z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
deleted file mode 100644
index 6eb944f..0000000
--- a/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/tv_volume_icons_size"
- android:height="@dimen/tv_volume_icons_size"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <group android:translateX="-2">
- <path
- android:fillColor="@color/tv_volume_dialog_accent"
- android:pathData="M16,7.97v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02 0,-1.77 -1.02,-3.29 -2.5,-4.03zM5,9v6h4l5,5L14,4L9,9L5,9zM12,8.83v6.34L9.83,13L7,13v-2h2.83L12,8.83z"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
deleted file mode 100644
index b683089..0000000
--- a/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/tv_volume_icons_size"
- android:height="@dimen/tv_volume_icons_size"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <group android:translateX="-4">
- <path
- android:fillColor="@color/tv_volume_dialog_accent"
- android:pathData="M14,8.83v6.34L11.83,13H9v-2h2.83L14,8.83M16,4l-5,5H7v6h4l5,5V4z"/>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_off.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_off.xml
deleted file mode 100644
index 7a44aa6..0000000
--- a/packages/SystemUI/res/drawable-television/ic_volume_media_off.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/tv_volume_icons_size"
- android:height="@dimen/tv_volume_icons_size"
- android:viewportHeight="24"
- android:viewportWidth="24">
- <path
- android:fillColor="@color/tv_volume_dialog_accent"
- android:pathData="M4.34,2.93L2.93,4.34 7.29,8.7 7,9L3,9v6h4l5,5v-6.59l4.18,4.18c-0.65,0.49 -1.38,0.88 -2.18,1.11v2.06c1.34,-0.3 2.57,-0.92 3.61,-1.75l2.05,2.05 1.41,-1.41L4.34,2.93zM10,15.17L7.83,13L5,13v-2h2.83l0.88,-0.88L10,11.41v3.76zM19,12c0,0.82 -0.15,1.61 -0.41,2.34l1.53,1.53c0.56,-1.17 0.88,-2.48 0.88,-3.87 0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM12,4l-1.88,1.88L12,7.76zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v1.79l2.48,2.48c0.01,-0.08 0.02,-0.16 0.02,-0.24z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable-television/volume_row_seekbar.xml b/packages/SystemUI/res/drawable-television/volume_row_seekbar.xml
deleted file mode 100644
index e49fc15..0000000
--- a/packages/SystemUI/res/drawable-television/volume_row_seekbar.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2021 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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
- android:paddingMode="stack">
- <item android:id="@android:id/background"
- android:gravity="center_vertical|fill_horizontal">
- <layer-list>
- <item android:id="@+id/volume_seekbar_background_solid">
- <shape>
- <size android:height="@dimen/volume_dialog_slider_width" />
- <solid android:color="@color/tv_volume_dialog_seek_bar_background"/>
- <corners android:radius="@dimen/volume_dialog_slider_corner_radius" />
- </shape>
- </item>
- </layer-list>
- </item>
- <item android:id="@android:id/progress"
- android:gravity="center_vertical|fill_horizontal">
- <com.android.systemui.util.RoundedCornerProgressDrawable
- android:drawable="@drawable/volume_row_seekbar_progress"
- />
- </item>
-</layer-list>
diff --git a/packages/SystemUI/res/drawable-television/volume_row_seekbar_progress.xml b/packages/SystemUI/res/drawable-television/volume_row_seekbar_progress.xml
deleted file mode 100644
index bce193a..0000000
--- a/packages/SystemUI/res/drawable-television/volume_row_seekbar_progress.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 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.
- -->
-
-<!-- Progress drawable for volume row SeekBars. This is the accent-colored round rect that moves up
- and down as the progress value changes. -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true">
- <item android:id="@+id/volume_seekbar_progress_solid">
- <shape android:shape="rectangle">
- <size android:height="@dimen/volume_dialog_slider_width"/>
- <solid android:color="@color/tv_volume_dialog_seek_bar_fill" />
- <corners android:radius="@dimen/volume_dialog_slider_width" />
- </shape>
- </item>
-</layer-list>
diff --git a/services/core/Android.bp b/services/core/Android.bp
index a4d72b1..66a77a3 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -191,6 +191,7 @@
"apache-commons-math",
"power_optimization_flags_lib",
"notification_flags_lib",
+ "pm_flags_lib",
],
javac_shard_size: 50,
javacflags: [
@@ -240,4 +241,4 @@
prebuilt_etc {
name: "protolog.conf.json.gz",
src: ":services.core.json.gz",
-}
\ No newline at end of file
+}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index fc51e2e..557e4ac 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1374,7 +1374,7 @@
* and the package should get out of stopped state and be enabled.
*/
public abstract void notifyComponentUsed(@NonNull String packageName,
- @UserIdInt int userId, @NonNull String recentCallingPackage);
+ @UserIdInt int userId, @NonNull String recentCallingPackage, @NonNull String debugInfo);
/** @deprecated For legacy shell command only. */
@Deprecated
@@ -1403,4 +1403,10 @@
*/
public abstract int[] getDistractingPackageRestrictionsAsUser(
@NonNull String[] packageNames, int userId);
+
+ /**
+ * Checks if package is quarantined for a specific user.
+ */
+ public abstract boolean isPackageQuarantined(@NonNull String packageName,
+ @UserIdInt int userId);
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d398260..330742a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -5309,11 +5309,12 @@
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
}
- int flags = Context.BIND_AUTO_CREATE;
+ long flags = Context.BIND_FILTER_OUT_QUARANTINED_COMPONENTS | Context.BIND_AUTO_CREATE;
if (mAuthenticatorCache.getBindInstantServiceAllowed(mAccounts.userId)) {
flags |= Context.BIND_ALLOW_INSTANT;
}
- if (!mContext.bindServiceAsUser(intent, this, flags, UserHandle.of(mAccounts.userId))) {
+ if (!mContext.bindServiceAsUser(intent, this, Context.BindServiceFlags.of(flags),
+ UserHandle.of(mAccounts.userId))) {
Log.w(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
// Perform unbind as per documentation at Context.bindServiceAsUser
mContext.unbindService(this);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index cb246f6..93fe0c9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3601,6 +3601,8 @@
|| (flags & Context.BIND_EXTERNAL_SERVICE_LONG) != 0;
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
final boolean inSharedIsolatedProcess = (flags & Context.BIND_SHARED_ISOLATED_PROCESS) != 0;
+ final boolean filterOutQuarantined =
+ (flags & Context.BIND_FILTER_OUT_QUARANTINED_COMPONENTS) != 0;
ProcessRecord attributedApp = null;
if (sdkSandboxClientAppUid > 0) {
@@ -3610,7 +3612,7 @@
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
isBindExternal, allowInstant, null /* fgsDelegateOptions */,
- inSharedIsolatedProcess);
+ inSharedIsolatedProcess, filterOutQuarantined);
if (res == null) {
return 0;
}
@@ -4119,6 +4121,20 @@
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant, ForegroundServiceDelegationOptions fgsDelegateOptions,
boolean inSharedIsolatedProcess) {
+ return retrieveServiceLocked(service, instanceName, isSdkSandboxService,
+ sdkSandboxClientAppUid, sdkSandboxClientAppPackage, resolvedType, callingPackage,
+ callingPid, callingUid, userId, createIfNeeded, callingFromFg, isBindExternal,
+ allowInstant, fgsDelegateOptions, inSharedIsolatedProcess,
+ false /* filterOutQuarantined */);
+ }
+
+ private ServiceLookupResult retrieveServiceLocked(Intent service,
+ String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
+ String sdkSandboxClientAppPackage, String resolvedType,
+ String callingPackage, int callingPid, int callingUid, int userId,
+ boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
+ boolean allowInstant, ForegroundServiceDelegationOptions fgsDelegateOptions,
+ boolean inSharedIsolatedProcess, boolean filterOutQuarantined) {
if (isSdkSandboxService && instanceName == null) {
throw new IllegalArgumentException("No instanceName provided for sdk sandbox process");
}
@@ -4235,11 +4251,14 @@
if (r == null) {
try {
- int flags = ActivityManagerService.STOCK_PM_FLAGS
+ long flags = ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
if (allowInstant) {
flags |= PackageManager.MATCH_INSTANT;
}
+ if (filterOutQuarantined) {
+ flags |= PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
+ }
// TODO: come back and remove this assumption to triage all services
ResolveInfo rInfo = mAm.getPackageManagerInternal().resolveService(service,
resolvedType, flags, userId, callingUid);
@@ -5118,7 +5137,7 @@
try {
mAm.mPackageManagerInt.notifyComponentUsed(
- r.packageName, r.userId, r.mRecentCallingPackage);
+ r.packageName, r.userId, r.mRecentCallingPackage, r.toString());
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4dc76db..c4816fb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -58,6 +58,7 @@
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_PERSISTENT;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_SYSTEM;
import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
+import static android.content.pm.PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
@@ -14221,7 +14222,8 @@
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users, int[] broadcastAllowList) {
// TODO: come back and remove this assumption to triage all broadcasts
- int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
+ long pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING
+ | FILTER_OUT_QUARANTINED_COMPONENTS;
List<ResolveInfo> receivers = null;
HashSet<ComponentName> singleUserReceivers = null;
@@ -14849,6 +14851,16 @@
mAtmInternal.onPackagesSuspendedChanged(packageNames, suspended,
userIdExtra);
+
+ final boolean quarantined = intent.getBooleanExtra(
+ Intent.EXTRA_QUARANTINED, false);
+ if (suspended && quarantined && packageNames != null) {
+ for (int i = 0; i < packageNames.length; i++) {
+ forceStopPackageLocked(packageNames[i], -1, false, true, true,
+ false, false, userId, "suspended");
+ }
+ }
+
break;
}
break;
diff --git a/services/core/java/com/android/server/am/ComponentAliasResolver.java b/services/core/java/com/android/server/am/ComponentAliasResolver.java
index 6e93ce4..3fa6102 100644
--- a/services/core/java/com/android/server/am/ComponentAliasResolver.java
+++ b/services/core/java/com/android/server/am/ComponentAliasResolver.java
@@ -457,7 +457,7 @@
@Nullable
public Resolution<ResolveInfo> resolveReceiver(@NonNull Intent intent,
@NonNull ResolveInfo receiver, @Nullable String resolvedType,
- int packageFlags, int userId, int callingUid, boolean forSend) {
+ long packageFlags, int userId, int callingUid, boolean forSend) {
// Resolve this alias.
final Resolution<ComponentName> resolution = resolveComponentAlias(() ->
receiver.activityInfo.getComponentName());
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 65fd54a..4cc147f 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -509,7 +509,8 @@
checkTime(startTime,
"getContentProviderImpl: before set stopped state");
mService.mPackageManagerInt.notifyComponentUsed(
- cpr.appInfo.packageName, userId, callingPackage);
+ cpr.appInfo.packageName, userId, callingPackage,
+ cpr.toString());
checkTime(startTime, "getContentProviderImpl: after set stopped state");
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 8a8e2af..70a1c91 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -1531,7 +1531,11 @@
sb.append("ServiceRecord{")
.append(Integer.toHexString(System.identityHashCode(this)))
.append(" u").append(userId)
- .append(' ').append(shortInstanceName).append('}');
+ .append(' ').append(shortInstanceName);
+ if (mRecentCallingPackage != null) {
+ sb.append(" c:").append(mRecentCallingPackage);
+ }
+ sb.append('}');
return stringName = sb.toString();
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 86da39b..a17b3d5 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -97,7 +97,7 @@
*/
public final class AppHibernationService extends SystemService {
private static final String TAG = "AppHibernationService";
- private static final int PACKAGE_MATCH_FLAGS =
+ private static final long PACKAGE_MATCH_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 3e31bd1..0aac7c2 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -220,8 +220,10 @@
private static final int SYNC_OP_STATE_INVALID_SYNC_DISABLED = 5;
/** Flags used when connecting to a sync adapter service */
- private static final int SYNC_ADAPTER_CONNECTION_FLAGS = Context.BIND_AUTO_CREATE
- | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT;
+ private static final Context.BindServiceFlags SYNC_ADAPTER_CONNECTION_FLAGS =
+ Context.BindServiceFlags.of(
+ Context.BIND_FILTER_OUT_QUARANTINED_COMPONENTS | Context.BIND_AUTO_CREATE
+ | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT);
/** Singleton instance. */
@GuardedBy("SyncManager.class")
diff --git a/services/core/java/com/android/server/pm/Android.bp b/services/core/java/com/android/server/pm/Android.bp
new file mode 100644
index 0000000..89c0124
--- /dev/null
+++ b/services/core/java/com/android/server/pm/Android.bp
@@ -0,0 +1,12 @@
+aconfig_declarations {
+ name: "pm_flags",
+ package: "com.android.server.pm",
+ srcs: [
+ "*.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "pm_flags_lib",
+ aconfig_declarations: "pm_flags",
+}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 5b05b48..7d878ec 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -522,6 +522,7 @@
comp != null || pkgName != null /*onlyExposedExplicitly*/,
isImplicitImageCaptureIntentAndNotSetByDpc(intent, userId, resolvedType,
flags));
+
List<ResolveInfo> list = Collections.emptyList();
boolean skipPostResolution = false;
if (comp != null) {
@@ -643,6 +644,12 @@
final String instantAppPkgName = getInstantAppPackageName(callingUid);
flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
+
+ // Only if the query is coming from the system process,
+ // it should be allowed to match quarantined components
+ if (callingUid != Process.SYSTEM_UID) {
+ flags |= PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
+ }
Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
@@ -4031,6 +4038,9 @@
flags = updateFlagsForComponent(flags, userId);
enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
false /* checkShell */, "get provider info");
+ if (callingUid != Process.SYSTEM_UID) {
+ flags |= PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
+ }
ParsedProvider p = mComponentResolver.getProvider(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getProviderInfo " + component + ": " + p);
@@ -4660,6 +4670,9 @@
int callingUid) {
if (!mUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId);
+ if (callingUid != Process.SYSTEM_UID) {
+ flags |= PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
+ }
final ProviderInfo providerInfo = mComponentResolver.queryProvider(this, name, flags,
userId);
boolean checkedGrants = false;
@@ -4772,6 +4785,13 @@
false /* checkShell */, "queryContentProviders");
if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForComponent(flags, userId);
+
+ // Only if the service query is coming from the system process,
+ // it should be allowed to match quarantined components
+ if (callingUid != Process.SYSTEM_UID) {
+ flags |= PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
+ }
+
ArrayList<ProviderInfo> finalList = null;
final List<ProviderInfo> matchList = mComponentResolver.queryProviders(this, processName,
metaDataKey, uid, flags, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index 82587c5..6efd067 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -746,10 +746,18 @@
}
@Override
- public void notifyComponentUsed(@NonNull String packageName,
- @UserIdInt int userId, @NonNull String recentCallingPackage) {
+ public void notifyComponentUsed(@NonNull String packageName, @UserIdInt int userId,
+ @NonNull String recentCallingPackage, @NonNull String debugInfo) {
mService.notifyComponentUsed(snapshot(), packageName, userId,
- recentCallingPackage);
+ recentCallingPackage, debugInfo);
+ }
+
+ @Override
+ public boolean isPackageQuarantined(@NonNull String packageName,
+ @UserIdInt int userId) {
+ final PackageStateInternal packageState = getPackageStateInternal(packageName);
+ return (packageState == null) ? false
+ : packageState.getUserStateOrDefault(userId).isQuarantined();
}
@NonNull
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6bcfcfe..6c0aeec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4583,7 +4583,18 @@
}
void notifyComponentUsed(@NonNull Computer snapshot, @NonNull String packageName,
- @UserIdInt int userId, @NonNull String recentCallingPackage) {
+ @UserIdInt int userId, @NonNull String recentCallingPackage,
+ @NonNull String debugInfo) {
+ synchronized (mLock) {
+ final PackageUserStateInternal userState = mSettings.getPackageLPr(
+ packageName).getUserStateOrDefault(userId);
+ if (userState.isQuarantined()) {
+ Slog.i(TAG,
+ "Component is quarantined+suspended but being used: "
+ + packageName + " by " + recentCallingPackage + ", debugInfo: "
+ + debugInfo);
+ }
+ }
PackageManagerService.this
.setPackageStoppedState(snapshot, packageName, false /* stopped */,
userId);
@@ -6120,14 +6131,16 @@
@Override
public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
PersistableBundle appExtras, PersistableBundle launcherExtras,
- SuspendDialogInfo dialogInfo, String callingPackage, int userId) {
+ SuspendDialogInfo dialogInfo, int flags, String callingPackage, int userId) {
final int callingUid = Binder.getCallingUid();
final Computer snapshot = snapshotComputer();
enforceCanSetPackagesSuspendedAsUser(snapshot, callingPackage, callingUid, userId,
"setPackagesSuspendedAsUser");
+ boolean quarantined = ((flags & PackageManager.FLAG_SUSPEND_QUARANTINED) != 0)
+ && Flags.quarantinedEnabled();
return mSuspendPackageHelper.setPackagesSuspended(snapshot, packageNames, suspended,
appExtras, launcherExtras, dialogInfo, callingPackage, userId, callingUid,
- false /* forQuietMode */);
+ false /* forQuietMode */, quarantined);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index ce0e7ad..ceae1fe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -288,9 +288,11 @@
case "unhide":
return runSetHiddenSetting(false);
case "suspend":
- return runSuspend(true);
+ return runSuspend(true, 0);
+ case "suspend-quarantine":
+ return runSuspend(true, PackageManager.FLAG_SUSPEND_QUARANTINED);
case "unsuspend":
- return runSuspend(false);
+ return runSuspend(false, 0);
case "set-distracting-restriction":
return runSetDistractingRestriction();
case "get-distracting-restriction":
@@ -2644,7 +2646,7 @@
}
}
- private int runSuspend(boolean suspendedState) {
+ private int runSuspend(boolean suspendedState, int flags) {
final PrintWriter pw = getOutPrintWriter();
int userId = UserHandle.USER_SYSTEM;
String dialogMessage = null;
@@ -2712,7 +2714,7 @@
mInterface.setPackagesSuspendedAsUser(packageNames.toArray(new String[] {}),
suspendedState, ((appExtras.size() > 0) ? appExtras : null),
((launcherExtras.size() > 0) ? launcherExtras : null),
- info, callingPackage, translatedUserId);
+ info, flags, callingPackage, translatedUserId);
for (int i = 0; i < packageNames.size(); i++) {
final String packageName = packageNames.get(i);
pw.println("Package " + packageName + " new suspended state: "
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index dee31ec..14693a6 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -937,8 +937,8 @@
otherState.isHidden(), otherState.getDistractionFlags(),
otherState.getSuspendParams() == null
? null : otherState.getSuspendParams().untrackedStorage(),
- otherState.isInstantApp(),
- otherState.isVirtualPreload(), otherState.getLastDisableAppCaller(),
+ otherState.isInstantApp(), otherState.isVirtualPreload(),
+ otherState.getLastDisableAppCaller(),
otherState.getEnabledComponentsNoCopy() == null
? null : otherState.getEnabledComponentsNoCopy().untrackedStorage(),
otherState.getDisabledComponentsNoCopy() == null
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c6135e0..b6da462 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1918,9 +1918,9 @@
ArraySet<String> enabledComponents = null;
ArraySet<String> disabledComponents = null;
- PersistableBundle suspendedAppExtras = null;
- PersistableBundle suspendedLauncherExtras = null;
SuspendDialogInfo oldSuspendDialogInfo = null;
+ PersistableBundle oldSuspendedAppExtras = null;
+ PersistableBundle oldSuspendedLauncherExtras = null;
ArchiveState archiveState = null;
int packageDepth = parser.getDepth();
@@ -1939,16 +1939,17 @@
case TAG_DISABLED_COMPONENTS:
disabledComponents = readComponentsLPr(parser);
break;
- case TAG_SUSPENDED_APP_EXTRAS:
- suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
- break;
- case TAG_SUSPENDED_LAUNCHER_EXTRAS:
- suspendedLauncherExtras = PersistableBundle.restoreFromXml(
- parser);
- break;
case TAG_SUSPENDED_DIALOG_INFO:
oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
break;
+ case TAG_SUSPENDED_APP_EXTRAS:
+ oldSuspendedAppExtras = PersistableBundle.restoreFromXml(
+ parser);
+ break;
+ case TAG_SUSPENDED_LAUNCHER_EXTRAS:
+ oldSuspendedLauncherExtras = PersistableBundle.restoreFromXml(
+ parser);
+ break;
case TAG_SUSPEND_PARAMS:
final String suspendingPackage = parser.getAttributeValue(null,
ATTR_SUSPENDING_PACKAGE);
@@ -1979,8 +1980,9 @@
if (suspended && suspendParamsMap == null) {
final SuspendParams suspendParams = new SuspendParams(
oldSuspendDialogInfo,
- suspendedAppExtras,
- suspendedLauncherExtras);
+ oldSuspendedAppExtras,
+ oldSuspendedLauncherExtras,
+ false /* quarantined */);
suspendParamsMap = new ArrayMap<>();
suspendParamsMap.put(oldSuspendingPackage, suspendParams);
}
@@ -1989,13 +1991,12 @@
setBlockUninstallLPw(userId, name, true);
}
ps.setUserState(userId, ceDataInode, enabled, installed, stopped,
- notLaunched,
- hidden, distractionFlags, suspendParamsMap, instantApp,
- virtualPreload,
- enabledCaller, enabledComponents, disabledComponents, installReason,
- uninstallReason, harmfulAppWarning, splashScreenTheme,
- firstInstallTime != 0 ? firstInstallTime :
- origFirstInstallTimes.getOrDefault(name, 0L),
+ notLaunched, hidden, distractionFlags, suspendParamsMap, instantApp,
+ virtualPreload, enabledCaller, enabledComponents,
+ disabledComponents, installReason, uninstallReason,
+ harmfulAppWarning, splashScreenTheme,
+ firstInstallTime != 0 ? firstInstallTime
+ : origFirstInstallTimes.getOrDefault(name, 0L),
minAspectRatio, archiveState);
mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
@@ -4824,6 +4825,7 @@
pw.print(userState.isNotLaunched() ? "l" : "L");
pw.print(userState.isInstantApp() ? "IA" : "ia");
pw.print(userState.isVirtualPreload() ? "VPI" : "vpi");
+ pw.print(userState.isQuarantined() ? "Q" : "q");
String harmfulAppWarning = userState.getHarmfulAppWarning();
pw.print(harmfulAppWarning != null ? "HA" : "ha");
pw.print(",");
@@ -5185,6 +5187,8 @@
pw.print(userState.isInstantApp());
pw.print(" virtual=");
pw.println(userState.isVirtualPreload());
+ pw.print(" quarantined=");
+ pw.print(userState.isQuarantined());
pw.print(" installReason=");
pw.println(userState.getInstallReason());
@@ -5207,6 +5211,8 @@
if (params != null) {
pw.print(" dialogInfo=");
pw.print(params.getDialogInfo());
+ pw.print(" quarantined=");
+ pw.println(params.isQuarantined());
}
pw.println();
}
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 94e09f1..ddb045d 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -115,17 +115,18 @@
boolean suspended, @Nullable PersistableBundle appExtras,
@Nullable PersistableBundle launcherExtras, @Nullable SuspendDialogInfo dialogInfo,
@NonNull String callingPackage, @UserIdInt int userId, int callingUid,
- boolean forQuietMode) {
+ boolean forQuietMode, boolean quarantined) {
if (ArrayUtils.isEmpty(packageNames)) {
return packageNames;
}
- if (suspended && !forQuietMode && !isSuspendAllowedForUser(snapshot, userId, callingUid)) {
+ if (suspended && !quarantined && !forQuietMode && !isSuspendAllowedForUser(snapshot, userId,
+ callingUid)) {
Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId);
return packageNames;
}
final SuspendParams newSuspendParams =
- new SuspendParams(dialogInfo, appExtras, launcherExtras);
+ new SuspendParams(dialogInfo, appExtras, launcherExtras, quarantined);
final List<String> unmodifiablePackages = new ArrayList<>(packageNames.length);
@@ -160,7 +161,6 @@
final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
packageState.getUserStateOrDefault(userId).getSuspendParams();
-
SuspendParams oldSuspendParams = suspendParamsMap == null
? null : suspendParamsMap.get(packageName);
boolean changed = !Objects.equals(oldSuspendParams, newSuspendParams);
@@ -213,14 +213,15 @@
sendPackagesSuspendedForUser(
suspended ? Intent.ACTION_PACKAGES_SUSPENDED
: Intent.ACTION_PACKAGES_UNSUSPENDED,
- changedPackages, notifyUids.toArray(), userId);
+ changedPackages, notifyUids.toArray(), quarantined, userId);
sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, userId);
mPm.scheduleWritePackageRestrictions(userId);
}
// Send the suspension changed broadcast to ensure suspension state is not stale.
if (!changedPackagesList.isEmpty()) {
sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED,
- changedPackagesList.toArray(new String[0]), changedUids.toArray(), userId);
+ changedPackagesList.toArray(new String[0]), changedUids.toArray(), quarantined,
+ userId);
}
return unmodifiablePackages.toArray(new String[0]);
}
@@ -354,7 +355,7 @@
new String[unsuspendedPackages.size()]);
sendMyPackageSuspendedOrUnsuspended(packageArray, false, userId);
sendPackagesSuspendedForUser(Intent.ACTION_PACKAGES_UNSUSPENDED,
- packageArray, unsuspendedUids.toArray(), userId);
+ packageArray, unsuspendedUids.toArray(), false, userId);
}
}
@@ -618,11 +619,14 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
void sendPackagesSuspendedForUser(@NonNull String intent, @NonNull String[] pkgList,
- @NonNull int[] uidList, int userId) {
+ @NonNull int[] uidList, boolean quarantined, int userId) {
final Handler handler = mInjector.getHandler();
final Bundle extras = new Bundle(3);
extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
+ if (quarantined) {
+ extras.putBoolean(Intent.EXTRA_QUARANTINED, true);
+ }
final int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND;
final Bundle options = new BroadcastOptions()
.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
@@ -672,7 +676,7 @@
snapshot, toSuspend.toArray(new String[0]), suspend,
null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */,
PackageManagerService.PLATFORM_PACKAGE_NAME, userId, Process.SYSTEM_UID,
- false /* forQuietMode */)));
+ false /* forQuietMode */, false /* quarantined */)));
}
return unsuspendable.toArray(String[]::new);
}
@@ -716,7 +720,7 @@
setPackagesSuspended(snapshot, toSuspend.toArray(new String[0]),
suspend, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */,
PackageManagerService.PLATFORM_PACKAGE_NAME, userId, Process.SYSTEM_UID,
- true /* forQuietMode */);
+ true /* forQuietMode */, false /* quarantined */);
}
private Set<String> packagesToSuspendInQuietMode(Computer snapshot, int userId) {
diff --git a/services/core/java/com/android/server/pm/flags.aconfig b/services/core/java/com/android/server/pm/flags.aconfig
new file mode 100644
index 0000000..368a843
--- /dev/null
+++ b/services/core/java/com/android/server/pm/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.pm"
+
+flag {
+ name: "quarantined_enabled"
+ namespace: "package_manager_service"
+ description: "Feature flag for Quarantined state"
+ bug: "269127435"
+}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 94e9599..27812df 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -379,7 +379,10 @@
| flag(state.isVirtualPreload(), ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
| flag(state.isHidden(), ApplicationInfo.PRIVATE_FLAG_HIDDEN);
- if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ if ((flags & PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS) != 0
+ && state.isQuarantined()) {
+ ai.enabled = false;
+ } else if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
ai.enabled = true;
} else if (state.getEnabledState()
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserState.java b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
index 81915b4..7bc518c 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
@@ -209,6 +209,13 @@
boolean isVirtualPreload();
/**
+ * @return whether the package is quarantined in order to minimize ad-spam and pop ups
+ * when-not-in-use.
+ * @hide
+ */
+ boolean isQuarantined();
+
+ /**
* The "package:type/entry" form of the theme resource ID previously set as the splash screen.
*
* @hide
@@ -225,6 +232,7 @@
*/
@PackageManager.UserMinAspectRatio
int getMinAspectRatio();
+
/**
* Information about the archived state of an app. Set only if an app is archived.
*
@@ -233,4 +241,5 @@
@Immutable.Ignore
@Nullable
ArchiveState getArchiveState();
+
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
index cce18a8..3534d75 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
@@ -129,6 +129,11 @@
return false;
}
+ @Override
+ public boolean isQuarantined() {
+ return false;
+ }
+
@Nullable
@Override
public String getSplashScreenTheme() {
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index d8c8af6..2349fbf 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -670,6 +670,21 @@
return getBoolean(Booleans.VIRTUAL_PRELOADED);
}
+ @Override
+ public boolean isQuarantined() {
+ if (!isSuspended()) {
+ return false;
+ }
+ final var suspendParams = mSuspendParams;
+ for (int i = 0, size = suspendParams.size(); i < size; i++) {
+ final SuspendParams params = suspendParams.valueAt(i);
+ if (params.isQuarantined()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@@ -879,7 +894,7 @@
}
@DataClass.Generated(
- time = 1691186062924L,
+ time = 1691601685901L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java",
inputSignatures = "private int mBooleans\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mDisabledComponentsWatched\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mEnabledComponentsWatched\nprivate long mCeDataInode\nprivate int mDistractionFlags\nprivate @android.content.pm.PackageManager.EnabledState int mEnabledState\nprivate @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mOverlayPaths\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate @android.content.pm.PackageManager.UserMinAspectRatio int mMinAspectRatio\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams> mSuspendParams\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>> mComponentLabelIconOverrideMap\nprivate @android.annotation.CurrentTimeMillisLong long mFirstInstallTimeMillis\nprivate @android.annotation.Nullable com.android.server.utils.Watchable mWatchable\nprivate @android.annotation.Nullable com.android.server.pm.pkg.ArchiveState mArchiveState\nfinal @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> mSnapshot\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\nprivate com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> makeCache()\nprivate void onChanged()\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserStateImpl snapshot()\npublic @android.annotation.Nullable boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths)\npublic boolean setSharedLibraryOverlayPaths(java.lang.String,android.content.pm.overlay.OverlayPaths)\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponentsNoCopy()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponentsNoCopy()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getDisabledComponents()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getEnabledComponents()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer)\npublic void resetOverrideComponentLabelIcon()\npublic @android.annotation.Nullable android.util.Pair<java.lang.String,java.lang.Integer> getOverrideLabelIconForComponent(android.content.ComponentName)\npublic @java.lang.Override boolean isSuspended()\npublic com.android.server.pm.pkg.PackageUserStateImpl putSuspendParams(java.lang.String,com.android.server.pm.pkg.SuspendParams)\npublic com.android.server.pm.pkg.PackageUserStateImpl removeSuspension(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setCeDataInode(long)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstalled(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setStopped(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setNotLaunched(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHidden(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDistractionFlags(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstantApp(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setVirtualPreload(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setUninstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHarmfulAppWarning(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setLastDisableAppCaller(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSharedLibraryOverlayPaths(android.util.ArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSplashScreenTheme(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setMinAspectRatio(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSuspendParams(android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setComponentLabelIconOverrideMap(android.util.ArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setFirstInstallTimeMillis(long)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setArchiveState(com.android.server.pm.pkg.ArchiveState)\npublic @android.annotation.NonNull @java.lang.Override java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getSharedLibraryOverlayPaths()\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setWatchable(com.android.server.utils.Watchable)\nprivate boolean watchableEquals(com.android.server.utils.Watchable)\nprivate int watchableHashCode()\nprivate boolean snapshotEquals(com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl>)\nprivate int snapshotHashCode()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isVirtualPreload()\nclass PackageUserStateImpl extends com.android.server.utils.WatchableImpl implements [com.android.server.pm.pkg.PackageUserStateInternal, com.android.server.utils.Snappable]\nprivate static final int INSTALLED\nprivate static final int STOPPED\nprivate static final int NOT_LAUNCHED\nprivate static final int HIDDEN\nprivate static final int INSTANT_APP\nprivate static final int VIRTUAL_PRELOADED\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false, genEqualsHashCode=true)")
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index 15e3d0c..e342453 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -16,6 +16,7 @@
package com.android.server.pm.pkg;
+import static android.content.pm.PackageManager.FILTER_OUT_QUARANTINED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
@@ -122,6 +123,10 @@
return true;
}
+ if ((flags & FILTER_OUT_QUARANTINED_COMPONENTS) != 0 && state.isQuarantined()) {
+ return false;
+ }
+
// First check if the overall package is disabled; if the package is
// enabled then fall through to check specific component
switch (state.getEnabledState()) {
diff --git a/services/core/java/com/android/server/pm/pkg/SuspendParams.java b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
index dc48a33..153238fa 100644
--- a/services/core/java/com/android/server/pm/pkg/SuspendParams.java
+++ b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
@@ -42,16 +42,25 @@
private static final String TAG_DIALOG_INFO = "dialog-info";
private static final String TAG_APP_EXTRAS = "app-extras";
private static final String TAG_LAUNCHER_EXTRAS = "launcher-extras";
+ private static final String ATTR_QUARANTINED = "quarantined";
- private final SuspendDialogInfo dialogInfo;
- private final PersistableBundle appExtras;
- private final PersistableBundle launcherExtras;
+ private final SuspendDialogInfo mDialogInfo;
+ private final PersistableBundle mAppExtras;
+ private final PersistableBundle mLauncherExtras;
+
+ private final boolean mQuarantined;
public SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
PersistableBundle launcherExtras) {
- this.dialogInfo = dialogInfo;
- this.appExtras = appExtras;
- this.launcherExtras = launcherExtras;
+ this(dialogInfo, appExtras, launcherExtras, false /* quarantined */);
+ }
+
+ public SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
+ PersistableBundle launcherExtras, boolean quarantined) {
+ this.mDialogInfo = dialogInfo;
+ this.mAppExtras = appExtras;
+ this.mLauncherExtras = launcherExtras;
+ this.mQuarantined = quarantined;
}
@Override
@@ -63,13 +72,16 @@
return false;
}
final SuspendParams other = (SuspendParams) obj;
- if (!Objects.equals(dialogInfo, other.dialogInfo)) {
+ if (!Objects.equals(mDialogInfo, other.mDialogInfo)) {
return false;
}
- if (!BaseBundle.kindofEquals(appExtras, other.appExtras)) {
+ if (!BaseBundle.kindofEquals(mAppExtras, other.mAppExtras)) {
return false;
}
- if (!BaseBundle.kindofEquals(launcherExtras, other.launcherExtras)) {
+ if (!BaseBundle.kindofEquals(mLauncherExtras, other.mLauncherExtras)) {
+ return false;
+ }
+ if (mQuarantined != other.mQuarantined) {
return false;
}
return true;
@@ -77,9 +89,10 @@
@Override
public int hashCode() {
- int hashCode = Objects.hashCode(dialogInfo);
- hashCode = 31 * hashCode + ((appExtras != null) ? appExtras.size() : 0);
- hashCode = 31 * hashCode + ((launcherExtras != null) ? launcherExtras.size() : 0);
+ int hashCode = Objects.hashCode(mDialogInfo);
+ hashCode = 31 * hashCode + ((mAppExtras != null) ? mAppExtras.size() : 0);
+ hashCode = 31 * hashCode + ((mLauncherExtras != null) ? mLauncherExtras.size() : 0);
+ hashCode = 31 * hashCode + Boolean.hashCode(mQuarantined);
return hashCode;
}
@@ -89,25 +102,26 @@
* @param out the {@link XmlSerializer} object
*/
public void saveToXml(TypedXmlSerializer out) throws IOException {
- if (dialogInfo != null) {
+ out.attributeBoolean(null, ATTR_QUARANTINED, mQuarantined);
+ if (mDialogInfo != null) {
out.startTag(null, TAG_DIALOG_INFO);
- dialogInfo.saveToXml(out);
+ mDialogInfo.saveToXml(out);
out.endTag(null, TAG_DIALOG_INFO);
}
- if (appExtras != null) {
+ if (mAppExtras != null) {
out.startTag(null, TAG_APP_EXTRAS);
try {
- appExtras.saveToXml(out);
+ mAppExtras.saveToXml(out);
} catch (XmlPullParserException e) {
Slog.e(LOG_TAG, "Exception while trying to write appExtras."
+ " Will be lost on reboot", e);
}
out.endTag(null, TAG_APP_EXTRAS);
}
- if (launcherExtras != null) {
+ if (mLauncherExtras != null) {
out.startTag(null, TAG_LAUNCHER_EXTRAS);
try {
- launcherExtras.saveToXml(out);
+ mLauncherExtras.saveToXml(out);
} catch (XmlPullParserException e) {
Slog.e(LOG_TAG, "Exception while trying to write launcherExtras."
+ " Will be lost on reboot", e);
@@ -127,6 +141,8 @@
PersistableBundle readAppExtras = null;
PersistableBundle readLauncherExtras = null;
+ final boolean quarantined = in.getAttributeBoolean(null, ATTR_QUARANTINED, false);
+
final int currentDepth = in.getDepth();
int type;
try {
@@ -157,18 +173,22 @@
Slog.e(LOG_TAG, "Exception while trying to parse SuspendParams,"
+ " some fields may default", e);
}
- return new SuspendParams(readDialogInfo, readAppExtras, readLauncherExtras);
+ return new SuspendParams(readDialogInfo, readAppExtras, readLauncherExtras, quarantined);
}
public SuspendDialogInfo getDialogInfo() {
- return dialogInfo;
+ return mDialogInfo;
}
public PersistableBundle getAppExtras() {
- return appExtras;
+ return mAppExtras;
}
public PersistableBundle getLauncherExtras() {
- return launcherExtras;
+ return mLauncherExtras;
+ }
+
+ public boolean isQuarantined() {
+ return mQuarantined;
}
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index d8cc8d3..57b6e37 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1329,7 +1329,7 @@
.notifyBeforePackageUnstopped(next.packageName);
mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(
next.packageName, next.mUserId,
- next.packageName); /* TODO: Verify if correct userid */
+ next.packageName, next.toString()); /* TODO: Verify if correct userid */
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ next.packageName + ": " + e);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b3fa782..af1bac8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11004,25 +11004,18 @@
}
}
- private void dumpPerUserData(IndentingPrintWriter pw) {
+ private void dumpPersonalAppInfoForSystemUserNoLock(IndentingPrintWriter pw) {
+ wtfIfInLock();
+ PersonalAppsSuspensionHelper.forUser(mContext, UserHandle.USER_SYSTEM).dump(pw);
+ }
+
+ private void dumpPerUserPolicyData(IndentingPrintWriter pw) {
int userCount = mUserData.size();
for (int i = 0; i < userCount; i++) {
int userId = mUserData.keyAt(i);
DevicePolicyData policy = getUserData(userId);
policy.dump(pw);
pw.println();
-
- if (userId == UserHandle.USER_SYSTEM) {
- pw.increaseIndent();
- PersonalAppsSuspensionHelper.forUser(mContext, userId).dump(pw);
- pw.decreaseIndent();
- pw.println();
- } else {
- // pm.getUnsuspendablePackages() will fail if it's called for a different user;
- // as this dump is mostly useful for system user anyways, we can just ignore the
- // others (rather than changing the permission check in the PM method)
- Slogf.d(LOG_TAG, "skipping PersonalAppsSuspensionHelper.dump() for user " + userId);
- }
}
}
@@ -11040,7 +11033,7 @@
pw.println();
mDeviceAdminServiceController.dump(pw);
pw.println();
- dumpPerUserData(pw);
+ dumpPerUserPolicyData(pw);
pw.println();
mConstants.dump(pw);
pw.println();
@@ -11067,6 +11060,7 @@
mStateCache.dump(pw);
pw.println();
}
+ dumpPersonalAppInfoForSystemUserNoLock(pw);
synchronized (mSubscriptionsChangedListenerLock) {
pw.println("Subscription changed listener : " + mSubscriptionsChangedListener);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index 5cca5fa..6797576 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -40,7 +40,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
targetPackages, true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
verify(pms).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
@@ -64,14 +64,14 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
null /* packageNames */, true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
assertThat(failedNames).isNull()
failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOfNulls(0), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
assertThat(failedNames).isEmpty()
}
@@ -81,7 +81,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID,
- Binder.getCallingUid(), false /* forQuietMode */)
+ Binder.getCallingUid(), false /* forQuietMode */, false /* quarantined */)
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(TEST_PACKAGE_2)
@@ -92,7 +92,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(DEVICE_OWNER_PACKAGE), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(DEVICE_OWNER_PACKAGE)
@@ -103,7 +103,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(NONEXISTENT_PACKAGE), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(NONEXISTENT_PACKAGE)
@@ -116,7 +116,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
knownPackages, true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)!!
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)!!
assertThat(failedNames.size).isEqualTo(knownPackages.size)
for (pkg in knownPackages) {
@@ -132,7 +132,7 @@
val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
knownPackages, true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, true /* forQuietMode */)!!
+ TEST_USER_ID, deviceOwnerUid, true /* forQuietMode */, false /* quarantined */)!!
assertThat(failedNames.size).isEqualTo(1)
assertThat(failedNames[0]).isEqualTo(MGMT_ROLE_HOLDER_PACKAGE)
@@ -144,13 +144,13 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
targetPackages, true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
targetPackages, false /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
@@ -202,7 +202,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_1), true /* suspended */, appExtras, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
- false /* forQuietMode */)
+ false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -220,7 +220,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
targetPackages, true /* suspended */, appExtras, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
- false /* forQuietMode */)
+ false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
@@ -265,7 +265,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
- false /* forQuietMode */)
+ false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -280,7 +280,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
- TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */)
+ TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -295,7 +295,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
- false /* forQuietMode */)
+ false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -310,7 +310,7 @@
var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
null /* launcherExtras */, dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
- deviceOwnerUid, false /* forQuietMode */)
+ deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -324,7 +324,7 @@
@Throws(Exception::class)
fun sendPackagesSuspendedForUser() {
suspendPackageHelper.sendPackagesSuspendedForUser(
- Intent.ACTION_PACKAGES_SUSPENDED, packagesToChange, uidsToChange, TEST_USER_ID)
+ Intent.ACTION_PACKAGES_SUSPENDED, packagesToChange, uidsToChange, false, TEST_USER_ID)
testHandler.flush()
verify(broadcastHelper).sendPackageBroadcast(any(), nullable(), bundleCaptor.capture(),
anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable(),
@@ -341,7 +341,7 @@
@Throws(Exception::class)
fun sendPackagesSuspendModifiedForUser() {
suspendPackageHelper.sendPackagesSuspendedForUser(
- Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, packagesToChange, uidsToChange, TEST_USER_ID)
+ Intent.ACTION_PACKAGES_SUSPENSION_CHANGED, packagesToChange, uidsToChange, false, TEST_USER_ID)
testHandler.flush()
verify(broadcastHelper).sendPackageBroadcast(
eq(Intent.ACTION_PACKAGES_SUSPENSION_CHANGED), nullable(), bundleCaptor.capture(),
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index b539a76..943a9c47 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -236,7 +236,7 @@
verify(getServices().packageManagerInternal, never())
.unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, USER_SYSTEM);
verify(getServices().ipackageManager, never()).setPackagesSuspendedAsUser(
- any(), anyBoolean(), any(), any(), any(), any(), anyInt());
+ any(), anyBoolean(), any(), any(), any(), anyInt(), any(), anyInt());
final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext);
poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 7478778..f408ef0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -7527,7 +7527,7 @@
.cancel(eq(SystemMessageProto.SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED));
// Verify that the apps are NOT unsuspeded.
verify(getServices().ipackageManager, never()).setPackagesSuspendedAsUser(
- any(), eq(false), any(), any(), any(), any(), anyInt());
+ any(), eq(false), any(), any(), any(), anyInt(), any(), anyInt());
// Verify that DPC is invoked to check policy compliance.
verify(mContext.spiedContext).startActivityAsUser(
MockUtils.checkIntentAction(ACTION_CHECK_POLICY_COMPLIANCE),
diff --git a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
index 24029b1..fc27edc 100644
--- a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
@@ -35,6 +35,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -68,6 +69,27 @@
mBugreportFileManager = new BugreportManagerServiceImpl.BugreportFileManager();
}
+ @After
+ public void tearDown() throws Exception {
+ // Changes to RoleManager persist between tests, so we need to clear out any funny
+ // business we did in previous tests.
+ RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(
+ () -> {
+ roleManager.setBypassingRoleQualification(false);
+ roleManager.removeRoleHolderAsUser(
+ "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
+ mContext.getPackageName(),
+ /* flags= */ 0,
+ Process.myUserHandle(),
+ mContext.getMainExecutor(),
+ future);
+ });
+
+ assertThat(future.get()).isEqualTo(true);
+ }
+
@Test
public void testBugreportFileManagerFileExists() {
Pair<Integer, String> callingInfo = new Pair<>(mCallingUid, mCallingPackage);
@@ -131,14 +153,17 @@
new BugreportManagerServiceImpl.Injector(mContext, new ArraySet<>()));
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
CallbackFuture future = new CallbackFuture();
- runWithShellPermissionIdentity(() -> roleManager.setBypassingRoleQualification(true));
- runWithShellPermissionIdentity(() -> roleManager.addRoleHolderAsUser(
- "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
- mContext.getPackageName(),
- /* flags= */ 0,
- Process.myUserHandle(),
- mContext.getMainExecutor(),
- future));
+ runWithShellPermissionIdentity(
+ () -> {
+ roleManager.setBypassingRoleQualification(true);
+ roleManager.addRoleHolderAsUser(
+ "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
+ mContext.getPackageName(),
+ /* flags= */ 0,
+ Process.myUserHandle(),
+ mContext.getMainExecutor(),
+ future);
+ });
assertThat(future.get()).isEqualTo(true);
mService.cancelBugreport(Binder.getCallingUid(), mContext.getPackageName());
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 64c2a4c..baacb57 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -85,11 +85,11 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -1328,10 +1328,24 @@
private final Context mContext;
- // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
- // the Context and subId.
- private static final Map<Pair<Context, Integer>, Resources> sResourcesCache =
- new ConcurrentHashMap<>();
+ /**
+ * In order to prevent the overflow of the heap size due to an indiscriminate increase in the
+ * cache, the heap size of the resource cache is set sufficiently large.
+ */
+ private static final int MAX_RESOURCE_CACHE_ENTRY_COUNT = 10_000;
+
+ /**
+ * Cache of Resources that has been created in getResourcesForSubId. Key contains package name,
+ * and Configuration of Resources. If more than the maximum number of resources are stored in
+ * this cache, the least recently used Resources will be removed to maintain the maximum size.
+ */
+ private static final Map<Pair<String, Configuration>, Resources> sResourcesCache =
+ Collections.synchronizedMap(new LinkedHashMap<>(16, 0.75f, true) {
+ @Override
+ protected boolean removeEldestEntry(Entry eldest) {
+ return size() > MAX_RESOURCE_CACHE_ENTRY_COUNT;
+ }
+ });
/**
* A listener class for monitoring changes to {@link SubscriptionInfo} records.
@@ -2817,14 +2831,20 @@
@NonNull
public static Resources getResourcesForSubId(Context context, int subId,
boolean useRootLocale) {
- // Check if resources for this context and subId already exist in the resource cache.
- // Resources that use the root locale are not cached.
- Pair<Context, Integer> cacheKey = null;
- if (isValidSubscriptionId(subId) && !useRootLocale) {
- cacheKey = Pair.create(context, subId);
- if (sResourcesCache.containsKey(cacheKey)) {
+ // Check if the Resources already exists in the cache based on the given context. Find a
+ // Resource that match Configuration.
+ Pair<String, Configuration> cacheKey = null;
+ if (isValidSubscriptionId(subId)) {
+ Configuration configurationKey =
+ new Configuration(context.getResources().getConfiguration());
+ if (useRootLocale) {
+ configurationKey.setLocale(Locale.ROOT);
+ }
+ cacheKey = Pair.create(context.getPackageName(), configurationKey);
+ Resources cached = sResourcesCache.get(cacheKey);
+ if (cached != null) {
// Cache hit. Use cached Resources.
- return sResourcesCache.get(cacheKey);
+ return cached;
}
}