summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/AndroidManifest.xml13
-rw-r--r--PermissionController/res/values/strings.xml9
-rw-r--r--PermissionController/res/xml/roles.xml18
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java129
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/ChangeDefaultCardEmulationActivity.java76
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/behavior/WalletRoleUiBehavior.java187
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java8
-rw-r--r--framework-s/api/current.txt1
-rw-r--r--framework-s/java/android/app/role/RoleManager.java9
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterFlags.java22
-rw-r--r--tests/cts/permission/Android.bp1
-rw-r--r--tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java3
-rw-r--r--tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java3
-rw-r--r--tests/cts/permissionpolicy/Android.bp1
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml10
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java3
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java3
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java3
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt13
40 files changed, 561 insertions, 46 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 379f7bd68..6dfee27d0 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -66,6 +66,7 @@
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
<uses-permission android:name="android.permission.GET_APP_METADATA" />
+ <uses-permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO" />
<application android:name="com.android.permissioncontroller.PermissionControllerApplication"
android:label="@string/app_name"
@@ -472,6 +473,18 @@
</intent-filter>
</activity>
+ <activity android:name="com.android.permissioncontroller.role.ui.ChangeDefaultCardEmulationActivity"
+ android:enabled="@bool/is_at_least_v"
+ android:excludeFromRecents="true"
+ android:noHistory="true"
+ android:exported="true"
+ android:theme="@android:style/Theme.NoDisplay">
+ <intent-filter android:priority="1001">
+ <action android:name="android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<provider android:name="com.android.permissioncontroller.permission.service.PermissionSearchIndexablesProvider"
android:authorities="com.android.permissioncontroller"
android:multiprocess="false"
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 24db04f2d..5e1c7d162 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1223,6 +1223,15 @@
<!-- Search keywords for the NOTES role. [CHAR LIMIT=NONE] -->
<string name="role_notes_search_keywords">notes</string>
+ <!-- Label for the wallet role. [CHAR LIMIT=30] -->
+ <string name="role_wallet_label">Default wallet app</string>
+ <!-- Short label for the wallet role. [CHAR LIMIT=30] -->
+ <string name="role_wallet_short_label">Wallet app</string>
+ <!-- Description for the wallet role. [CHAR LIMIT=NONE] -->
+ <string name="role_wallet_description">Wallet apps can store your credit and loyalty cards, car keys and other things to help with various forms of transactions.</string>
+ <string name="role_wallet_request_title">Set <xliff:g id="app_name" example="Super Wallet">%1$s</xliff:g> as your default wallet app?</string>
+ <string name="role_wallet_request_description">No permissions needed</string>
+
<!-- Subtitle for the application that is the current default application [CHAR LIMIT=30] -->
<string name="request_role_current_default">Current default</string>
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index e8f838c81..f09056f73 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -1655,4 +1655,22 @@
<app-op-permission name="android.permission.PACKAGE_USAGE_STATS" />
</app-op-permissions>
</role>
+
+ <role
+ name="android.app.role.WALLET"
+ behavior="WalletRoleBehavior"
+ defaultHolders="config_defaultWallet"
+ description="@string/role_wallet_description"
+ exclusive="true"
+ label="@string/role_wallet_label"
+ minSdkVersion="35"
+ overrideUserWhenGranting="true"
+ requestable="true"
+ requestDescription="@string/role_wallet_request_description"
+ requestTitle="@string/role_wallet_request_title"
+ showNone="true"
+ shortLabel="@string/role_wallet_short_label"
+ uiBehavior="WalletRoleUiBehavior"/>
+
+
</roles>
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java
new file mode 100644
index 000000000..170c42c3d
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.behavior;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.nfc.NfcAdapter;
+import android.nfc.cardemulation.ApduServiceInfo;
+import android.nfc.cardemulation.CardEmulation;
+import android.nfc.cardemulation.HostApduService;
+import android.nfc.cardemulation.OffHostApduService;
+import android.os.Build;
+import android.os.UserHandle;
+import android.permission.flags.Flags;
+import android.service.quickaccesswallet.QuickAccessWalletService;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.role.controller.model.Role;
+import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.util.UserUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Handles the behavior of the wallet role.
+ */
+@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+public class WalletRoleBehavior implements RoleBehavior {
+
+ private static final String LOG_TAG = WalletRoleBehavior.class.getSimpleName();
+
+ @Override
+ public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return SdkLevel.isAtLeastV() && Flags.walletRoleEnabled()
+ && !UserUtils.isProfile(user, context);
+ }
+
+ @Nullable
+ @Override
+ public List<String> getDefaultHoldersAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ CardEmulation cardEmulation;
+ Context userContext = UserUtils.getUserContext(context, user);
+ try {
+ cardEmulation =
+ CardEmulation.getInstance(NfcAdapter.getDefaultAdapter(userContext));
+ } catch (UnsupportedOperationException e) {
+ Log.e(LOG_TAG, "Unsupported Card Emulation Operation.", e);
+ return null;
+ }
+ ApduServiceInfo preferredPaymentService = cardEmulation
+ .getPreferredPaymentService();
+ if (preferredPaymentService != null) {
+ return Collections.singletonList(preferredPaymentService.getComponent()
+ .getPackageName());
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return !getQualifyingPackageNamesInternal(packageName, user, context).isEmpty();
+ }
+
+ @Nullable
+ @Override
+ public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return new ArrayList<>(getQualifyingPackageNamesInternal(null, user, context));
+ }
+
+ @NonNull
+ private static Set<String> getQualifyingPackageNamesInternal(@Nullable String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ Set<String> packageNames =
+ resolvePackageNames(HostApduService.SERVICE_INTERFACE, packageName, user,
+ context);
+ packageNames.addAll(
+ resolvePackageNames(OffHostApduService.SERVICE_INTERFACE, packageName, user,
+ context));
+ packageNames.addAll(
+ resolvePackageNames(QuickAccessWalletService.SERVICE_INTERFACE, packageName, user,
+ context));
+ return packageNames;
+ }
+
+ @NonNull
+ private static Set<String> resolvePackageNames(@NonNull String action,
+ @Nullable String packageName, @NonNull UserHandle user, @NonNull Context context) {
+ Intent intent = new Intent(action).setPackage(packageName);
+ PackageManager packageManager = context.getPackageManager();
+ List<ResolveInfo> resolveInfos = packageManager
+ .queryIntentServicesAsUser(intent, 0, user);
+ Set<String> packageNames = new ArraySet<>();
+ int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ packageNames.add(resolveInfos.get(i).serviceInfo.packageName);
+ }
+ return packageNames;
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index c615755be..61ad86a72 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -56,7 +56,7 @@ import android.text.style.ClickableSpan;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
-import android.view.MotionEvent;
+import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.Window;
@@ -686,25 +686,29 @@ public class GrantPermissionsActivity extends SettingsActivity
return buttonArray;
}
- // LINT.IfChange(dispatchTouchEvent)
@Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- View rootView = getWindow().getDecorView();
- if (rootView.getTop() != 0) {
- // We are animating the top view, need to compensate for that in motion events.
- ev.setLocation(ev.getX(), ev.getY() - rootView.getTop());
- }
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
- if ((x < 0) || (y < 0) || (x > (rootView.getWidth())) || (y > (rootView.getHeight()))) {
- if (MotionEvent.ACTION_DOWN == ev.getAction()) {
- mViewHandler.onCancelled();
- }
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE
+ && event.getRepeatCount() == 0
+ && event.hasNoModifiers()) {
+ event.startTracking();
+ mViewHandler.onCancelled();
finishAfterTransition();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE
+ && event.isTracking()
+ && !event.isCanceled()) {
+ // Mark it as handled since we did handle the down event
+ return true;
}
- return super.dispatchTouchEvent(ev);
+ return super.onKeyUp(keyCode, event);
}
- // LINT.ThenChange(PermissionRationaleActivity.java:dispatchTouchEvent)
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
index cd5f3eb8f..0afbb05fe 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
@@ -67,7 +67,6 @@ fun ListHeader(
modifier =
modifier
.defaultMinSize(minHeight = ListHeaderDefaults.Height)
- .height(IntrinsicSize.Min)
.wrapContentSize()
.background(backgroundColor)
.padding(contentPadding)
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/ChangeDefaultCardEmulationActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/ChangeDefaultCardEmulationActivity.java
new file mode 100644
index 000000000..882d01c56
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/ChangeDefaultCardEmulationActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.role.ui;
+
+import android.app.Activity;
+import android.app.role.RoleManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Bundle;
+import android.os.Process;
+import android.permission.flags.Flags;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.modules.utils.build.SdkLevel;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Activity to handle {@link android.nfc.cardemulation.CardEmulation#ACTION_CHANGE_DEFAULT}.
+ */
+public class ChangeDefaultCardEmulationActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent;
+ if (SdkLevel.isAtLeastV() && Flags.walletRoleEnabled()) {
+ intent = DefaultAppActivity.createIntent(RoleManager.ROLE_WALLET,
+ Process.myUserHandle(), this);
+ } else {
+ intent = getIntent();
+ setDefaultPaymentChangeHandlerDialogComponent(intent);
+ }
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ finish();
+ }
+
+ // The only other handler of this intent is in the NFC stack.
+ private void setDefaultPaymentChangeHandlerDialogComponent(@NonNull Intent intent) {
+ Intent queryIntent = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
+ PackageManager packageManager = getPackageManager();
+ List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(queryIntent,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ String packageName = resolveInfo.activityInfo.packageName;
+ if (!Objects.equals(packageName, getPackageName())) {
+ intent.setClassName(packageName,
+ resolveInfo.activityInfo.name);
+ return;
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
index f9a0193bd..e68fa88a0 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
@@ -191,7 +191,8 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat
preference.setIcon(Utils.getBadgedIcon(context, holderApplicationInfo));
preference.setSummary(Utils.getAppLabel(holderApplicationInfo, context));
}
- RoleUiBehaviorUtils.preparePreferenceAsUser(role, rolePreference, user, context);
+ RoleUiBehaviorUtils.preparePreferenceAsUser(role, holderApplicationInfos,
+ rolePreference, user, context);
preferenceGroup.addPreference(preference);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java
index 323325d0b..0142e1c40 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java
@@ -38,6 +38,8 @@ import com.android.permissioncontroller.role.ui.TwoTargetPreference;
import com.android.permissioncontroller.role.utils.UserUtils;
import com.android.role.controller.model.Role;
+import java.util.List;
+
/***
* Class for UI behavior of Home role
*/
@@ -47,7 +49,8 @@ public class HomeRoleUiBehavior implements RoleUiBehavior {
@Override
public void preparePreferenceAsUser(@NonNull Role role, @NonNull TwoTargetPreference preference,
- @NonNull UserHandle user, @NonNull Context context) {
+ @NonNull List<ApplicationInfo> applicationInfos, @NonNull UserHandle user,
+ @NonNull Context context) {
TwoTargetPreference.OnSecondTargetClickListener listener = null;
RoleManager roleManager = context.getSystemService(RoleManager.class);
String packageName = CollectionUtils.firstOrNull(roleManager.getRoleHoldersAsUser(
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java
index 29dc5d2fc..0a8f9113f 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java
@@ -28,6 +28,8 @@ import androidx.preference.Preference;
import com.android.permissioncontroller.role.ui.TwoTargetPreference;
import com.android.role.controller.model.Role;
+import java.util.List;
+
/***
* Interface for UI behavior for roles
*/
@@ -53,11 +55,13 @@ public interface RoleUiBehavior {
*
* @param role the role to prepare the preference for
* @param preference the {@link Preference} for this role
+ * @param applicationInfos a list {@link ApplicationInfo} for the current role holders
* @param user the user for this role
* @param context the {@code Context} to retrieve system services
*/
default void preparePreferenceAsUser(@NonNull Role role,
@NonNull TwoTargetPreference preference,
+ @NonNull List<ApplicationInfo> applicationInfos,
@NonNull UserHandle user,
@NonNull Context context) {}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/WalletRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/WalletRoleUiBehavior.java
new file mode 100644
index 000000000..858621d74
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/WalletRoleUiBehavior.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.role.ui.behavior;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.nfc.cardemulation.ApduServiceInfo;
+import android.nfc.cardemulation.CardEmulation;
+import android.nfc.cardemulation.HostApduService;
+import android.nfc.cardemulation.OffHostApduService;
+import android.os.Build;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.core.util.Pair;
+import androidx.preference.Preference;
+
+import com.android.permissioncontroller.role.ui.TwoTargetPreference;
+import com.android.role.controller.model.Role;
+import com.android.role.controller.util.UserUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/***
+ * Class for UI behavior of Wallet role
+ */
+@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+public class WalletRoleUiBehavior implements RoleUiBehavior {
+
+ private static final String LOG_TAG = WalletRoleUiBehavior.class.getSimpleName();
+
+ @Override
+ public void preparePreferenceAsUser(@NonNull Role role, @NonNull TwoTargetPreference preference,
+ @NonNull List<ApplicationInfo> applicationInfos, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ if (!applicationInfos.isEmpty()) {
+ preparePreferenceInternal(preference.asPreference(), applicationInfos.get(0),
+ false, user, userContext);
+ }
+ }
+
+ @Override
+ public void prepareApplicationPreferenceAsUser(@NonNull Role role,
+ @NonNull Preference preference, @NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ preparePreferenceInternal(preference, applicationInfo, true, user, userContext);
+ }
+
+ private void preparePreferenceInternal(@NonNull Preference preference,
+ @NonNull ApplicationInfo applicationInfo, boolean setTitle, @NonNull UserHandle user,
+ @NonNull Context context) {
+ if (isSystemApplication(applicationInfo)) {
+ List<ApduServiceInfo> serviceInfos = getNfcServicesForPackage(
+ applicationInfo.packageName, user, context);
+
+ Pair<Drawable, CharSequence> bannerAndLabel =
+ getNonPaymentServiceBannerAndLabelIfExists(serviceInfos, user, context);
+ if (bannerAndLabel != null) {
+ preference.setIcon(bannerAndLabel.first);
+ if (setTitle) {
+ preference.setTitle(bannerAndLabel.second);
+ } else {
+ preference.setSummary(bannerAndLabel.second);
+ }
+ }
+ }
+ }
+
+ @NonNull
+ private static List<ApduServiceInfo> getNfcServicesForPackage(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ Intent hostApduIntent = new Intent(HostApduService.SERVICE_INTERFACE);
+ Intent offHostApduIntent = new Intent(OffHostApduService.SERVICE_INTERFACE);
+ hostApduIntent.setPackage(packageName);
+ offHostApduIntent.setPackage(packageName);
+ List<ResolveInfo> hostApduServices = packageManager.queryIntentServicesAsUser(
+ hostApduIntent,
+ PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), user);
+ List<ResolveInfo> offHostApduServices = packageManager.queryIntentServicesAsUser(
+ offHostApduIntent,
+ PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), user);
+ List<ApduServiceInfo> nfcServices = new ArrayList<>();
+ int apduServiceInfoSize = hostApduServices.size();
+ for (int i = 0; i < apduServiceInfoSize; i++) {
+ ResolveInfo resolveInfo = hostApduServices.get(i);
+ ApduServiceInfo apduServiceInfo;
+ try {
+ apduServiceInfo = new ApduServiceInfo(packageManager, resolveInfo, true);
+ } catch (XmlPullParserException | IOException e) {
+ Log.e(LOG_TAG, "Error creating the apduserviceinfo.", e);
+ continue;
+ }
+ nfcServices.add(apduServiceInfo);
+ }
+ int offHostApduServiceInfoSize = offHostApduServices.size();
+ for (int i = 0; i < offHostApduServiceInfoSize; i++) {
+ ResolveInfo resolveInfo = offHostApduServices.get(i);
+ ApduServiceInfo apduServiceInfo;
+ try {
+ apduServiceInfo = new ApduServiceInfo(packageManager, resolveInfo, false);
+ } catch (XmlPullParserException | IOException e) {
+ Log.e(LOG_TAG, "Error creating the apduserviceinfo.", e);
+ continue;
+ }
+ nfcServices.add(apduServiceInfo);
+ }
+ return nfcServices;
+ }
+
+ @Nullable
+ private Pair<Drawable, CharSequence> getNonPaymentServiceBannerAndLabelIfExists(
+ @NonNull List<ApduServiceInfo> apduServiceInfos, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
+ Pair<Drawable, CharSequence> bannerAndLabel;
+ int apduServiceInfoSize = apduServiceInfos.size();
+ for (int i = 0; i < apduServiceInfoSize; i++) {
+ ApduServiceInfo serviceInfo = apduServiceInfos.get(i);
+ if (serviceInfo.getAids().isEmpty()) {
+ bannerAndLabel = loadBannerAndLabel(serviceInfo, userPackageManager);
+ if (bannerAndLabel != null) {
+ return bannerAndLabel;
+ }
+ } else {
+ List<String> aids = serviceInfo.getAids();
+ int aidsSize = aids.size();
+ for (int j = 0; j < aidsSize; j++) {
+ String aid = aids.get(j);
+ String category = serviceInfo.getCategoryForAid(aid);
+ if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) {
+ bannerAndLabel = loadBannerAndLabel(serviceInfo, userPackageManager);
+ if (bannerAndLabel != null) {
+ return bannerAndLabel;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private Pair<Drawable, CharSequence> loadBannerAndLabel(@NonNull ApduServiceInfo info,
+ @NonNull PackageManager userPackageManager) {
+ Drawable drawable = info.loadBanner(userPackageManager);
+ CharSequence label = info.loadLabel(userPackageManager);
+ if (drawable != null && !TextUtils.isEmpty(label)) {
+ return new Pair<>(drawable, label);
+ } else {
+ return null;
+ }
+ }
+
+ private static boolean isSystemApplication(@NonNull ApplicationInfo applicationInfo) {
+ return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
index 4b256cef0..b06904930 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
@@ -115,7 +115,8 @@ public class SpecialAppAccessListChildFragment<PF extends PreferenceFragmentComp
} else {
preference = rolePreference.asPreference();
}
- RoleUiBehaviorUtils.preparePreferenceAsUser(role, rolePreference,
+ RoleUiBehaviorUtils.preparePreferenceAsUser(role, roleItem.getHolderApplicationInfos(),
+ rolePreference,
Process.myUserHandle(),
context);
preferenceScreen.addPreference(preference);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt
index 5e8a2f9ad..bbcedea53 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt
@@ -61,6 +61,7 @@ class WearDefaultAppListHelper(val context: Context, val user: UserHandle) {
.let {
RoleUiBehaviorUtils.preparePreferenceAsUser(
roleItem.role,
+ roleItem.holderApplicationInfos,
it,
user,
context
diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
index 7ebc1ebd1..5114af536 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
@@ -33,6 +33,8 @@ import com.android.permissioncontroller.role.ui.UserRestrictionAwarePreference;
import com.android.permissioncontroller.role.ui.behavior.RoleUiBehavior;
import com.android.role.controller.model.Role;
+import java.util.List;
+
/**
* Utility methods for Role UI behavior
*/
@@ -78,15 +80,15 @@ public final class RoleUiBehaviorUtils {
* @see RoleUiBehavior#preparePreferenceAsUser
*/
public static void preparePreferenceAsUser(@NonNull Role role,
- @NonNull RolePreference preference, @NonNull UserHandle user,
- @NonNull Context context) {
+ @NonNull List<ApplicationInfo> applicationInfos, @NonNull RolePreference preference,
+ @NonNull UserHandle user, @NonNull Context context) {
prepareUserRestrictionAwarePreferenceAsUser(role, preference, user, context);
RoleUiBehavior uiBehavior = getUiBehavior(role);
if (uiBehavior == null) {
return;
}
- uiBehavior.preparePreferenceAsUser(role, preference, user, context);
+ uiBehavior.preparePreferenceAsUser(role, preference, applicationInfos, user, context);
}
/**
diff --git a/framework-s/api/current.txt b/framework-s/api/current.txt
index d54af92f5..d943a03a1 100644
--- a/framework-s/api/current.txt
+++ b/framework-s/api/current.txt
@@ -14,6 +14,7 @@ package android.app.role {
field public static final String ROLE_HOME = "android.app.role.HOME";
field public static final String ROLE_NOTES = "android.app.role.NOTES";
field public static final String ROLE_SMS = "android.app.role.SMS";
+ field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final String ROLE_WALLET = "android.app.role.WALLET";
}
}
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index 3cf1e94ba..fe27d50f3 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -146,6 +146,15 @@ public final class RoleManager {
public static final String ROLE_NOTES = "android.app.role.NOTES";
/**
+ * The name of the Wallet role.
+ *
+ * @see android.nfc.cardemulation.CardEmulation
+ */
+ @FlaggedApi(Flags.FLAG_WALLET_ROLE_ENABLED)
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ public static final String ROLE_WALLET = "android.app.role.WALLET";
+
+ /**
* The name of the system wellbeing role.
*
* @hide
diff --git a/service/java/com/android/safetycenter/SafetyCenterFlags.java b/service/java/com/android/safetycenter/SafetyCenterFlags.java
index 67c4d25d6..e51d3a1cf 100644
--- a/service/java/com/android/safetycenter/SafetyCenterFlags.java
+++ b/service/java/com/android/safetycenter/SafetyCenterFlags.java
@@ -123,6 +123,9 @@ public final class SafetyCenterFlags {
private static final String RESURFACE_ISSUE_DELAYS_DEFAULT = "";
private static final Duration RESURFACE_ISSUE_DELAYS_DEFAULT_DURATION = Duration.ofDays(180);
+ private static final ArraySet<String> sAllowedNotificationSourcesUPlus =
+ new ArraySet<>(new String[] {"GoogleBackupAndRestore"});
+
private static volatile String sUntrackedSourcesDefault =
"AndroidAccessibility,AndroidBackgroundLocation,"
+ "AndroidNotificationListener,AndroidPermissionAutoRevoke";
@@ -175,7 +178,10 @@ public final class SafetyCenterFlags {
fout.println("FLAGS");
printFlag(fout, PROPERTY_SAFETY_CENTER_ENABLED, getSafetyCenterEnabled());
printFlag(fout, PROPERTY_NOTIFICATIONS_ENABLED, getNotificationsEnabled());
- printFlag(fout, PROPERTY_NOTIFICATIONS_ALLOWED_SOURCES, getNotificationsAllowedSourceIds());
+ printFlag(
+ fout,
+ PROPERTY_NOTIFICATIONS_ALLOWED_SOURCES,
+ getNotificationsAllowedSourceIdsFlag());
printFlag(fout, PROPERTY_NOTIFICATIONS_MIN_DELAY, getNotificationsMinDelay());
printFlag(
fout,
@@ -244,6 +250,20 @@ public final class SafetyCenterFlags {
* and therefore this is the only way to enable notifications for sources on Android T.
*/
public static ArraySet<String> getNotificationsAllowedSourceIds() {
+ ArraySet<String> sources = getNotificationsAllowedSourceIdsFlag();
+ if (SdkLevel.isAtLeastU()) {
+ // This is a hack to update the flag value via mainline update. Reasons why we can't do
+ // this via:
+ // remote flag update - these are generally avoided and considered risky
+ // XML config - it would break GTS tests for OEMs that have a separate config copy
+ // default flag value - it would also require a remote flag update
+ sources.addAll(sAllowedNotificationSourcesUPlus);
+ }
+
+ return sources;
+ }
+
+ private static ArraySet<String> getNotificationsAllowedSourceIdsFlag() {
return getCommaSeparatedStrings(PROPERTY_NOTIFICATIONS_ALLOWED_SOURCES);
}
diff --git a/tests/cts/permission/Android.bp b/tests/cts/permission/Android.bp
index c7c5f9279..ed7fcea25 100644
--- a/tests/cts/permission/Android.bp
+++ b/tests/cts/permission/Android.bp
@@ -54,6 +54,7 @@ android_test {
"platform-test-rules",
"CtsVirtualDeviceCommonLib",
"android.permission.flags-aconfig-java",
+ "androidx.test.rules",
],
jni_libs: [
"libctspermission_jni",
diff --git a/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java b/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
index 294896d97..fa43bfb18 100644
--- a/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
@@ -20,7 +20,8 @@ import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Test that protected AppWidgetManager APIs cannot be called without permissions
diff --git a/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java b/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java
index 99f2862f1..981735388 100644
--- a/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.hardware.Camera;
import android.os.Environment;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
import java.io.FileOutputStream;
diff --git a/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java b/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java
index 984fd6cfe..69b64d790 100644
--- a/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java
+++ b/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.content.ContentValues;
import android.provider.ContactsContract;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify permissions are enforced.
diff --git a/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
index 835ba124c..3d9ba8214 100644
--- a/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
@@ -21,7 +21,8 @@ import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
import java.util.List;
diff --git a/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java
index c2c42a10d..50498b1d5 100644
--- a/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java
@@ -25,9 +25,10 @@ import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
/**
* Verify the audio related operations require specific permissions.
*/
diff --git a/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java
index 5630c5b8c..1a46842b2 100644
--- a/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.content.Intent;
import android.os.Bundle;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify Context related methods without specific BROADCAST series permissions.
diff --git a/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java
index 6ad048308..e0573044c 100644
--- a/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java
@@ -22,9 +22,10 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.ImageReader;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.DisplayMetrics;
+import androidx.test.filters.SmallTest;
+
/**
* Verify the capture system video output permission requirements.
*/
diff --git a/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java
index 5a0b25993..ac77947d9 100644
--- a/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.app.KeyguardManager;
import android.content.Context;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify the key input related operations require specific permissions.
diff --git a/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
index b8d2ee21a..5dc73d520 100644
--- a/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.content.Context;
import android.net.ConnectivityManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.net.InetAddress;
diff --git a/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
index b6fb84dc7..f0d70b2ce 100644
--- a/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
@@ -21,7 +21,8 @@ import android.system.Os;
import android.system.OsConstants;
import android.system.StructStat;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
index 51b3bd830..437aa19c4 100644
--- a/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
@@ -28,7 +28,8 @@ import android.os.VibratorManager;
import android.platform.test.annotations.AppModeFull;
import android.telephony.gsm.SmsManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
index 030f341aa..95c4da727 100644
--- a/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
@@ -26,7 +26,8 @@ import android.net.wifi.WifiManager.WifiLock;
import android.os.PowerManager;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify the Wake Lock related operations require specific permissions.
diff --git a/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
index 18e4375bc..fc1d6b59f 100644
--- a/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
@@ -27,7 +27,8 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.function.ThrowingRunnable;
diff --git a/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
index df3ec3c64..7ebb09f98 100644
--- a/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
+++ b/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
@@ -21,7 +21,8 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify the PackageManager related operations require specific permissions.
diff --git a/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java b/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java
index 9f5a813d1..83c2ffaee 100644
--- a/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java
@@ -35,12 +35,11 @@ import android.provider.ContactsContract;
import android.provider.Settings;
import android.provider.Telephony;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
-import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
diff --git a/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java b/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java
index b1d3d5afb..13f17dce8 100644
--- a/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java
@@ -18,7 +18,8 @@ package android.permission.cts;
import android.content.Intent;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify that rebooting requires Permission.
diff --git a/tests/cts/permissionpolicy/Android.bp b/tests/cts/permissionpolicy/Android.bp
index a6ef8bde2..7a481b7ff 100644
--- a/tests/cts/permissionpolicy/Android.bp
+++ b/tests/cts/permissionpolicy/Android.bp
@@ -37,6 +37,7 @@ android_test {
"androidx.test.ext.junit-nodeps",
"truth",
"permission-test-util-lib",
+ "androidx.test.rules",
],
srcs: [
"src/**/*.java",
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
index 3f53bf863..a721a9f6f 100644
--- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -6974,6 +6974,16 @@
android:label="@string/permlab_foregroundServiceFileManagement"
android:protectionLevel="normal|instant" />
+ <!-- @FlaggedApi("android.content.pm.introduce_media_processing_type")
+ Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "mediaProcessing".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROCESSING"
+ android:description="@string/permdesc_foregroundServiceMediaProcessing"
+ android:label="@string/permlab_foregroundServiceMediaProcessing"
+ android:protectionLevel="normal|instant" />
+
<!-- Allows a regular application to use {@link android.app.Service#startForeground
Service.startForeground} with the type "specialUse".
<p>Protection level: normal|appop|instant
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java
index d8dc11a14..f34170a9b 100644
--- a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java
@@ -21,7 +21,8 @@ import android.content.ContentValues;
import android.platform.test.annotations.AppModeFull;
import android.provider.ContactsContract;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify that deprecated contacts permissions are not enforced.
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java
index 0f7638694..ef38573ab 100644
--- a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java
@@ -21,7 +21,8 @@ import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify the capture system video output permission requirements.
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java
index b02b32f22..8bf3e83a4 100644
--- a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java
@@ -19,7 +19,8 @@ package android.permission.cts;
import android.content.pm.PackageManager;
import android.os.Process;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Verify permission behaviors with android:maxSdkVersion
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
index edf76e888..fe75a05a2 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
@@ -24,14 +24,23 @@ import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
+/** toBooleanString() doesn't seem available on all Kotlin versions we need to support. */
+private fun String.toBooleanStrictInt(): Boolean =
+ when (this) {
+ "true" -> true
+ "false" -> false
+ else ->
+ throw IllegalArgumentException("The string doesn't represent a boolean value: $this")
+ }
+
/** JUnit rule for host side tests that requires Safety Center to be supported and enabled. */
class RequireSafetyCenterRule(private val hostTestClass: BaseHostJUnit4Test) : TestRule {
private val safetyCenterSupported: Boolean by lazy {
- shellCommandStdoutOrThrow("cmd safety_center supported").toBooleanStrict()
+ shellCommandStdoutOrThrow("cmd safety_center supported").toBooleanStrictInt()
}
private val safetyCenterEnabled: Boolean by lazy {
- shellCommandStdoutOrThrow("cmd safety_center enabled").toBooleanStrict()
+ shellCommandStdoutOrThrow("cmd safety_center enabled").toBooleanStrictInt()
}
override fun apply(base: Statement, description: Description): Statement {