From 1aebee954c2da98cb68ab3ebba5daa373ada5938 Mon Sep 17 00:00:00 2001 From: Shraddha Basantwani Date: Mon, 2 Dec 2024 09:36:05 +0000 Subject: [PATCH 1/2] Add biometric authentication for package modification Add an extra step of Lock Screen for disabling, force-stopping or uninstalling updates for protected packages Bug: 352504490, 344865740 Test: atest AppButtonsPreferenceControllerTest Flag: EXEMPT High Security Bug DISABLE_TOPIC_PROTECTOR (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:32e388ad3199de3c062bb2e2db5d3239f934d0eb) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dbe975ff3111692da8ec0086ef74ed97e7d54ca9) Merged-In: I0c494e307b02229d751de118abcc89e4e61a6861 Change-Id: I0c494e307b02229d751de118abcc89e4e61a6861 --- src/com/android/settings/Utils.java | 16 +++++ .../AppButtonsPreferenceController.java | 66 +++++++++++++------ .../appinfo/AppInfoDashboardFragment.java | 3 +- .../AppButtonsPreferenceControllerTest.java | 2 + .../testutils/shadow/ShadowUtils.java | 11 ++++ 5 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index f996444b482..ad747ff92e1 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -114,6 +114,7 @@ import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settingslib.widget.ActionBarShadowController; import com.android.settingslib.widget.AdaptiveIcon; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -1229,4 +1230,19 @@ public final class Utils extends com.android.settingslib.Utils { public static int getHomepageIconColorHighlight(Context context) { return context.getColor(R.color.accent_select_primary_text); } + + /** + * Returns {@code true} if the supplied package is a protected package. Otherwise, returns + * {@code false}. + * + * @param context the context + * @param packageName the package name + */ + public static boolean isProtectedPackage( + @NonNull Context context, @NonNull String packageName) { + final List protectedPackageNames = Arrays.asList(context.getResources() + .getStringArray(com.android.internal.R.array + .config_biometric_protected_package_names)); + return protectedPackageNames != null && protectedPackageNames.contains(packageName); + } } diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java index 1b270d63b4d..69f23fe5648 100644 --- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java @@ -52,6 +52,7 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.applications.ApplicationFeatureProvider; +import com.android.settings.applications.appinfo.AppInfoDashboardFragment; import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.InstrumentedPreferenceFragment; @@ -249,13 +250,21 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp } else { showDialogInner(ButtonActionDialogFragment.DialogType.DISABLE); } + } else if (mAppEntry.info.enabled) { + requireAuthAndExecute(() -> { + mMetricsFeatureProvider.action( + mActivity, + SettingsEnums.ACTION_SETTINGS_DISABLE_APP, + getPackageNameForMetric()); + AsyncTask.execute(new DisableChangerRunnable(mPm, + mAppEntry.info.packageName, + PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)); + }); } else { mMetricsFeatureProvider.action( mActivity, - mAppEntry.info.enabled - ? SettingsEnums.ACTION_SETTINGS_DISABLE_APP - : SettingsEnums.ACTION_SETTINGS_ENABLE_APP, - getPackageNameForMetric()); + SettingsEnums.ACTION_SETTINGS_ENABLE_APP, + getPackageNameForMetric()); AsyncTask.execute(new DisableChangerRunnable(mPm, mAppEntry.info.packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)); } @@ -303,13 +312,28 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp } } + /** + * Runs the given action with restricted lock authentication if it is a protected package. + * + * @param action The action to run. + */ + private void requireAuthAndExecute(Runnable action) { + if (Utils.isProtectedPackage(mContext, mAppEntry.info.packageName)) { + AppInfoDashboardFragment.showLockScreen(mContext, () -> action.run()); + } else { + action.run(); + } + } + public void handleDialogClick(int id) { switch (id) { case ButtonActionDialogFragment.DialogType.DISABLE: - mMetricsFeatureProvider.action(mActivity, - SettingsEnums.ACTION_SETTINGS_DISABLE_APP); - AsyncTask.execute(new DisableChangerRunnable(mPm, mAppEntry.info.packageName, - PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)); + requireAuthAndExecute(() -> { + mMetricsFeatureProvider.action(mActivity, + SettingsEnums.ACTION_SETTINGS_DISABLE_APP); + AsyncTask.execute(new DisableChangerRunnable(mPm, mAppEntry.info.packageName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)); + }); break; case ButtonActionDialogFragment.DialogType.SPECIAL_DISABLE: mMetricsFeatureProvider.action(mActivity, @@ -317,7 +341,9 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp uninstallPkg(mAppEntry.info.packageName, false, true); break; case ButtonActionDialogFragment.DialogType.FORCE_STOP: - forceStopPackage(mAppEntry.info.packageName); + requireAuthAndExecute(() -> { + forceStopPackage(mAppEntry.info.packageName); + }); break; } } @@ -547,16 +573,18 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp @VisibleForTesting void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) { - stopListeningToPackageRemove(); - // Create new intent to launch Uninstaller activity - Uri packageUri = Uri.parse("package:" + packageName); - Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri); - uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers); - - mMetricsFeatureProvider.action( - mActivity, SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP); - mFragment.startActivityForResult(uninstallIntent, mRequestUninstall); - mDisableAfterUninstall = andDisable; + requireAuthAndExecute(() -> { + stopListeningToPackageRemove(); + // Create new intent to launch Uninstaller activity + Uri packageUri = Uri.parse("package:" + packageName); + Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri); + uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers); + + mMetricsFeatureProvider.action( + mActivity, SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP); + mFragment.startActivityForResult(uninstallIntent, mRequestUninstall); + mDisableAfterUninstall = andDisable; + }); } @VisibleForTesting diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java index 54455d4f110..8f79b910055 100755 --- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java @@ -430,7 +430,8 @@ public class AppInfoDashboardFragment extends DashboardFragment } } - private static void showLockScreen(Context context, Runnable successRunnable) { + /** Shows the lock screen if the keyguard is secured. */ + public static void showLockScreen(Context context, Runnable successRunnable) { final KeyguardManager keyguardManager = context.getSystemService( KeyguardManager.class); diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java index 9a65dc8829c..91c5e7bf0fd 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java @@ -81,6 +81,7 @@ import org.robolectric.util.ReflectionHelpers; import java.util.Set; +@Config(shadows = {ShadowUtils.class}) @RunWith(RobolectricTestRunner.class) public class AppButtonsPreferenceControllerTest { @@ -166,6 +167,7 @@ public class AppButtonsPreferenceControllerTest { @After public void tearDown() { ShadowAppUtils.reset(); + ShadowUtils.reset(); } @Test diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java index 40cb25bfb83..8bd959f0715 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java @@ -48,6 +48,7 @@ public class ShadowUtils { private static ArraySet sResultLinks = new ArraySet<>(); private static boolean sIsBatteryPresent; private static boolean sIsMultipleBiometricsSupported; + private static boolean sIsProtectedPackage; @Implementation protected static int enforceSameOwner(Context context, int userId) { @@ -71,6 +72,7 @@ public class ShadowUtils { sResultLinks = new ArraySet<>(); sIsBatteryPresent = true; sIsMultipleBiometricsSupported = false; + sIsProtectedPackage = false; } public static void setIsDemoUser(boolean isDemoUser) { @@ -177,4 +179,13 @@ public class ShadowUtils { public static void setIsMultipleBiometricsSupported(boolean isMultipleBiometricsSupported) { sIsMultipleBiometricsSupported = isMultipleBiometricsSupported; } + + @Implementation + protected static boolean isProtectedPackage(Context context, String packageName) { + return sIsProtectedPackage; + } + + public static void setIsProtectedPackage(boolean isProtectedPackage) { + sIsProtectedPackage = isProtectedPackage; + } } -- GitLab From 54ce11a8a72058b56c698d3f5fe3c6d4fb4a2fa0 Mon Sep 17 00:00:00 2001 From: Guojing Yuan Date: Tue, 28 Jan 2025 11:57:16 -0800 Subject: [PATCH 2/2] [CDM] Checks NLS component name instead of package name Bug: 386216637 Flag: EXEMPT bugfix Test: CTS (cherry picked from commit f5ed187ffb6f5a25ac1c06a1e8b023b0c7d8d4b8) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e01c7bc45cba39f232525c0f403ecbed4652a249) Merged-In: I1be52fcb3d52b8b84353ea00fd57d8360ddd966c Change-Id: I1be52fcb3d52b8b84353ea00fd57d8360ddd966c --- .../notification/NotificationAccessConfirmationActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java index 253ae88e4b3..79e99fed4e5 100644 --- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java +++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java @@ -122,7 +122,7 @@ public class NotificationAccessConfirmationActivity extends Activity NLSIntent, /* flags */ 0, mUserId); boolean hasNLSIntentFilter = false; for (ResolveInfo service : matchedServiceList) { - if (service.serviceInfo.packageName.equals(mComponentName.getPackageName())) { + if (service.serviceInfo.getComponentName().equals(mComponentName)) { if (!requiredPermission.equals(service.serviceInfo.permission)) { Slog.e(LOG_TAG, "Service " + mComponentName + " lacks permission " + requiredPermission); @@ -156,7 +156,7 @@ public class NotificationAccessConfirmationActivity extends Activity .installContent(p); // Consistent with the permission dialog // Used instead of p.mCancelable as that is only honored for AlertDialog - getWindow().setCloseOnTouchOutside(false); + getWindow().setCloseOnTouchOutside(false); } private void onAllow() { -- GitLab