summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/AndroidManifest.xml7
-rw-r--r--PermissionController/res/values-v34/styles.xml1
-rw-r--r--PermissionController/res/values/strings.xml13
-rw-r--r--PermissionController/res/xml/roles.xml8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/Constants.java15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java84
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/legacy/PermissionApps.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/OverlayWarningDialog.java63
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/CardViewPreference.java (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java)5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelLegacy.kt)4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModelLegacy.kt)2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt31
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/AdvancedConfirmDialogArgs.kt)17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/CollectionUtils.java25
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt43
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java (renamed from PermissionController/src/com/android/permissioncontroller/permission/utils/AdminRestrictedPermissionsUtils.java)10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v31/SubattributionUtils.java (renamed from PermissionController/src/com/android/permissioncontroller/permission/utils/SubattributionUtils.java)9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/v34/HealthConnectPrivacySource.kt126
-rw-r--r--PermissionController/tests/inprocess/Android.bp6
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java258
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt74
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt60
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt165
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt59
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt211
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/HealthConnectPrivacySourceTest.kt200
-rw-r--r--SafetyCenter/Resources/res/raw-v34/safety_center_config.xml4
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataFactory.java12
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterFlags.java11
47 files changed, 1085 insertions, 603 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index b85e5ebdc..325597e67 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -356,11 +356,6 @@
</intent-filter>
</activity>
- <activity android:name="com.android.permissioncontroller.permission.ui.OverlayWarningDialog"
- android:excludeFromRecents="true"
- android:exported="false"
- android:theme="@style/Theme.DeviceDefault.Dialog.NoActionBar.DayNight" />
-
<activity android:name="com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog"
android:excludeFromRecents="true"
android:exported="false"
@@ -599,6 +594,8 @@
</intent-filter>
</activity>
+ <!-- Unexported empty activity for in-process tests -->
+ <activity android:name="android.app.Activity" />
</application>
</manifest>
diff --git a/PermissionController/res/values-v34/styles.xml b/PermissionController/res/values-v34/styles.xml
index f427d1a8e..cc119a331 100644
--- a/PermissionController/res/values-v34/styles.xml
+++ b/PermissionController/res/values-v34/styles.xml
@@ -149,6 +149,7 @@
<item name="android:gravity">center</item>
<item name="android:insetTop">6dp</item>
<item name="android:insetBottom">6dp</item>
+ <item name="android:minWidth">48dp</item>
<item name="android:minHeight">48dp</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 8c9f86d70..8399147c3 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -330,19 +330,6 @@
<!-- Title of the permission dialog for accessibility purposes- spoken to the user. [CHAR LIMIT=none] -->
<string name="permission_request_title">Permission request</string>
- <!-- Title for the dialog that warns the user they need to turn off screen overlays
- before permissions can be changed. [CHAR LIMIT=NONE] -->
- <string name="screen_overlay_title">Screen overlay detected</string>
-
- <!-- Message for the dialog that warns the user they need to turn off screen overlays
- before permissions can be changed. The "Settings > Apps" conveys to the user to
- go to Settings and click on apps, this may need updates in RTL languages. [CHAR LIMIT=NONE] -->
- <string name="screen_overlay_message">To change this permission setting, you first have to turn off the screen overlay from Settings \u003e Apps</string>
-
- <!-- Button for the dialog that warns the user they need to turn off screen overlays
- before permissions can be changed. [CHAR LIMIT=NONE] -->
- <string name="screen_overlay_button">Open settings</string>
-
<!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=30] -->
<string name="wear_not_allowed_dlg_title">Android Wear</string>
<!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=none] -->
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index d225d296a..dc884e810 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -68,12 +68,8 @@
</permission-set>
<permission-set name="sensors">
- <permission name="android.permission.BODY_SENSORS"/>
- <permission name="android.permission.BODY_SENSORS_BACKGROUND" minSdkVersion="33"/>
- <permission name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
- minSdkVersion="34"/>
- <permission name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- minSdkVersion="34"/>
+ <permission name="android.permission.BODY_SENSORS" />
+ <permission name="android.permission.BODY_SENSORS_BACKGROUND" minSdkVersion="33" />
</permission-set>
<permission-set name="storage">
diff --git a/PermissionController/src/com/android/permissioncontroller/Constants.java b/PermissionController/src/com/android/permissioncontroller/Constants.java
index e16f8d758..3995b608e 100644
--- a/PermissionController/src/com/android/permissioncontroller/Constants.java
+++ b/PermissionController/src/com/android/permissioncontroller/Constants.java
@@ -312,4 +312,19 @@ public class Constants {
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public static final String OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO =
"android:receive_ambient_trigger_audio";
+
+ /**
+ * Extra used by Settings to indicate an Intent should be treated as if opened directly by
+ * Settings app itself.
+ */
+ public static final String EXTRA_FROM_SETTINGS = "is_from_settings_homepage";
+
+ /**
+ * Extra used by Settings to indicate an Intent should be treated as if opened by a slice
+ * within Settings.
+ *
+ * <p>Slices are opened within settings by firing a PendingIntent, so we can use this extra to
+ * allow the same UX path to be taken as for slices.
+ */
+ public static final String EXTRA_IS_FROM_SLICE = "is_from_slice";
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java b/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java
new file mode 100644
index 000000000..637eb5fc4
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java
@@ -0,0 +1,84 @@
+/*
+ * 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.permission.compat;
+
+import android.text.Layout;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.method.LinkMovementMethod;
+import android.text.method.Touch;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Fixes the issue that links can be triggered for touches outside of line bounds for
+ * {@link LinkMovementMethod}.
+ * <p>
+ * This is based on the fix in ag/22301465.
+ */
+public class LinkMovementMethodCompat extends LinkMovementMethod {
+ @Override
+ public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer,
+ @NonNull MotionEvent event) {
+ int action = event.getAction();
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+
+ x -= widget.getTotalPaddingLeft();
+ y -= widget.getTotalPaddingTop();
+
+ x += widget.getScrollX();
+ y += widget.getScrollY();
+
+ Layout layout = widget.getLayout();
+ boolean isOutOfLineBounds;
+ if (y < 0 || y > layout.getHeight()) {
+ isOutOfLineBounds = true;
+ } else {
+ int line = layout.getLineForVertical(y);
+ isOutOfLineBounds = x < layout.getLineLeft(line) || x > layout.getLineRight(line);
+ }
+
+ if (isOutOfLineBounds) {
+ Selection.removeSelection(buffer);
+
+ // return LinkMovementMethod.super.onTouchEvent(widget, buffer, event);
+ return Touch.onTouchEvent(widget, buffer, event);
+ }
+ }
+
+ return super.onTouchEvent(widget, buffer, event);
+ }
+
+ /**
+ * @return a {@link LinkMovementMethodCompat} instance
+ */
+ @NonNull
+ public static LinkMovementMethodCompat getInstance() {
+ if (sInstance == null) {
+ sInstance = new LinkMovementMethodCompat();
+ }
+
+ return sInstance;
+ }
+
+ private static LinkMovementMethodCompat sInstance;
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/legacy/PermissionApps.java b/PermissionController/src/com/android/permissioncontroller/permission/model/legacy/PermissionApps.java
index 53ba48ace..196bfc6af 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/legacy/PermissionApps.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/legacy/PermissionApps.java
@@ -38,8 +38,8 @@ import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
-import com.android.permissioncontroller.permission.utils.SubattributionUtils;
import com.android.permissioncontroller.permission.utils.Utils;
+import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
index 3c1a9df39..001520c1b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
@@ -34,6 +34,7 @@ import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
@@ -50,6 +51,7 @@ import android.util.Xml;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.permissioncontroller.PermissionControllerProto.PermissionControllerDumpProto;
import com.android.permissioncontroller.PermissionControllerStatsLog;
@@ -59,12 +61,12 @@ import com.android.permissioncontroller.permission.model.Permission;
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo;
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState;
import com.android.permissioncontroller.permission.ui.AutoGrantPermissionsNotifier;
-import com.android.permissioncontroller.permission.utils.AdminRestrictedPermissionsUtils;
import com.android.permissioncontroller.permission.utils.ArrayUtils;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.PermissionMapping;
import com.android.permissioncontroller.permission.utils.UserSensitiveFlagsUtils;
import com.android.permissioncontroller.permission.utils.Utils;
+import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
@@ -777,6 +779,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
}
@Override
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions, @NonNull Runnable callback) {
PackageInfo pkgInfo = getPkgInfo(packageName);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index 7c4f197b2..a475a89ac 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -741,7 +741,7 @@ public class GrantPermissionsActivity extends SettingsActivity
removeActivityFromMap();
// If a new merge request came in before we managed to remove this activity from the
// map, then cancel the result set for now.
- if (!oldRequestedPermissions.equals(mRequestedPermissions)) {
+ if (!Objects.equals(oldRequestedPermissions, mRequestedPermissions)) {
return false;
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/OverlayWarningDialog.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/OverlayWarningDialog.java
deleted file mode 100644
index de1f68c98..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/OverlayWarningDialog.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 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.permission.ui;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.Intent;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.permissioncontroller.R;
-
-public class OverlayWarningDialog extends Activity implements OnClickListener, OnDismissListener {
-
- private static final String TAG = "OverlayWarningDialog";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- new AlertDialog.Builder(this)
- .setTitle(R.string.screen_overlay_title)
- .setMessage(R.string.screen_overlay_message)
- .setPositiveButton(R.string.screen_overlay_button, this)
- .setOnDismissListener(this)
- .show();
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- finish();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- finish();
- try {
- startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "No manage overlay settings", e);
- }
- }
-
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
index ad6b993fa..2de936469 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
@@ -55,11 +55,11 @@ import androidx.preference.TwoStatePreference;
import com.android.car.ui.AlertDialogBuilder;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.auto.AutoSettingsFrameFragment;
-import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ChangeRequest;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModelFactory;
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.PackageRemovalMonitor;
import com.android.settingslib.RestrictedLockUtils;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
index a7cb6c340..7ea400127 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
@@ -24,7 +24,7 @@ import androidx.preference.Preference.OnPreferenceClickListener
import com.android.car.ui.preference.CarUiPreference
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModelLegacy
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageDetailsViewModelLegacy
/** Preference that displays a permission usage for an app. */
@RequiresApi(Build.VERSION_CODES.S)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt
index eee9e8b6e..a16bc1ce4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt
@@ -42,8 +42,8 @@ import com.android.permissioncontroller.permission.model.v31.PermissionUsages
import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.auto.AutoDividerPreference
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModelFactoryLegacy
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModelLegacy
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageDetailsViewModelFactoryLegacy
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageDetailsViewModelLegacy
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
import com.android.permissioncontroller.permission.utils.Utils
import java.time.Clock
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
index a21e257c3..d4a2a073e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
@@ -40,9 +40,9 @@ import com.android.permissioncontroller.permission.model.v31.PermissionUsages
import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
import com.android.permissioncontroller.permission.ui.model.ManagePermissionsViewModel
import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageControlPreferenceUtils
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageViewModelFactoryLegacy
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageViewModelLegacy
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageViewModelLegacy.PermissionGroupWithUsageCount
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelFactoryLegacy
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelLegacy
+import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelLegacy.PermissionGroupWithUsageCount
import com.android.permissioncontroller.permission.utils.Utils
@RequiresApi(Build.VERSION_CODES.S)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
index bacf50144..946484626 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
@@ -74,13 +74,13 @@ import androidx.lifecycle.ViewModelProvider;
import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData.FullStoragePackageState;
-import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonState;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ChangeRequest;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModelFactory;
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.settingslib.RestrictedLockUtils;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
index 90d7204cf..220507426 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -53,6 +53,7 @@ import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage;
import com.android.permissioncontroller.permission.model.v31.PermissionUsages;
import com.android.permissioncontroller.permission.ui.Category;
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity;
+import com.android.permissioncontroller.permission.ui.handheld.v31.CardViewPreference;
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel;
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/CardViewPreference.java
index 6c76d906b..008813a83 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/CardViewPreference.java
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.ui.handheld;
+package com.android.permissioncontroller.permission.ui.handheld.v31;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.view.View;
import android.widget.Button;
+import androidx.annotation.RequiresApi;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -30,6 +32,7 @@ import com.android.permissioncontroller.R;
/**
* A Preference representing a banner message represented as a CardView
*/
+@RequiresApi(Build.VERSION_CODES.S)
public class CardViewPreference extends Preference {
private String mAction;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
index f3abc7619..88b5ebe87 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
@@ -18,7 +18,6 @@ package com.android.permissioncontroller.permission.ui.handheld.v34
import android.content.Context
import android.text.SpannableString
-import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.util.AttributeSet
import android.view.View
@@ -26,6 +25,7 @@ import android.widget.TextView
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.compat.LinkMovementMethodCompat
/** A preference for a footer with an icon and a link. */
class AppDataSharingUpdatesFooterPreference : Preference {
@@ -80,7 +80,7 @@ class AppDataSharingUpdatesFooterPreference : Preference {
footerLinkView?.let {
it.visibility = if (onFooterLinkClick == null) View.GONE else View.VISIBLE
it.text = footerLinkText
- it.movementMethod = LinkMovementMethod.getInstance()
+ it.movementMethod = LinkMovementMethodCompat.getInstance()
}
super.onBindViewHolder(holder)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
index 7504ae7d4..3998ca141 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
@@ -21,7 +21,6 @@ import android.content.Context
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
-import android.text.method.LinkMovementMethod
import android.transition.ChangeBounds
import android.transition.TransitionManager
import android.view.Gravity
@@ -29,13 +28,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
-import android.view.WindowManager
import android.view.animation.AnimationUtils
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.RequiresApi
import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.compat.LinkMovementMethodCompat
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleViewHandler
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleViewHandler.Result.Companion.CANCELLED
@@ -146,16 +145,16 @@ class PermissionRationaleViewHandlerImpl(
titleView = rootView.findViewById(R.id.permission_rationale_title)
dataSharingSourceMessageView = rootView.findViewById(R.id.data_sharing_source_message)
- dataSharingSourceMessageView!!.movementMethod = LinkMovementMethod.getInstance()
+ dataSharingSourceMessageView!!.movementMethod = LinkMovementMethodCompat.getInstance()
purposeTitleView = rootView.findViewById(R.id.purpose_title)
purposeMessageView = rootView.findViewById(R.id.purpose_message)
learnMoreMessageView = rootView.findViewById(R.id.learn_more_message)
- learnMoreMessageView!!.movementMethod = LinkMovementMethod.getInstance()
+ learnMoreMessageView!!.movementMethod = LinkMovementMethodCompat.getInstance()
settingsMessageView = rootView.findViewById(R.id.settings_message)
- settingsMessageView!!.movementMethod = LinkMovementMethod.getInstance()
+ settingsMessageView!!.movementMethod = LinkMovementMethodCompat.getInstance()
if (!shouldShowSettingsSection) {
val settingsSectionView: ViewGroup? = rootView.findViewById(R.id.settings_section)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelLegacy.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt
index 667667200..e219153f3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelLegacy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt
@@ -15,7 +15,7 @@
*/
@file:Suppress("DEPRECATION")
-package com.android.permissioncontroller.permission.ui.model.v31
+package com.android.permissioncontroller.permission.ui.legacy
import android.Manifest
import android.app.AppOpsManager
@@ -44,7 +44,7 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPackageLabel
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.StringUtils
-import com.android.permissioncontroller.permission.utils.SubattributionUtils
+import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils
import com.android.permissioncontroller.permission.utils.Utils
import java.time.Instant
import java.util.concurrent.TimeUnit
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModelLegacy.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt
index ff21a7216..d0e751f7d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModelLegacy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt
@@ -15,7 +15,7 @@
*/
@file:Suppress("DEPRECATION")
-package com.android.permissioncontroller.permission.ui.model.v31
+package com.android.permissioncontroller.permission.ui.legacy
import android.Manifest
import android.app.LoaderManager
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
index ddae7c0ee..cc44a400b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
@@ -63,7 +63,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightAppP
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
import com.android.permissioncontroller.permission.service.PermissionChangeStorageImpl
import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
-import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW_ALWAYS
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW_FOREGROUND
@@ -85,6 +85,7 @@ import com.android.permissioncontroller.permission.utils.PermissionMapping.getPa
import com.android.permissioncontroller.permission.utils.SafetyNetLogger
import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.permission.utils.navigateSafe
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
import com.android.settingslib.RestrictedLockUtils
import java.util.Random
import kotlin.collections.component1
@@ -206,7 +207,7 @@ class AppPermissionViewModel(
return
}
- value = PermissionMapping.getSafetyLabelSharingPurposesForGroup(
+ value = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
safetyLabel, permGroupName).any()
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
index 7cd1ea325..c6d89876b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -118,7 +118,7 @@ import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
-import com.android.permissioncontroller.permission.utils.AdminRestrictedPermissionsUtils
+import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultPrecision
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions
@@ -130,6 +130,7 @@ import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.PermissionMapping.getPartialStorageGrantPermissionsForGroup
import com.android.permissioncontroller.permission.utils.SafetyNetLogger
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
/**
* ViewModel for the GrantPermissionsActivity. Tracks all permission groups that are affected by
@@ -302,8 +303,9 @@ class GrantPermissionsViewModel(
appPermGroup.permissions[perm]?.isGrantedIncludingAppOp == true &&
appPermGroup.permissions[perm]?.isRevokeWhenRequested == false
}
- if (allAffectedGranted) {
- groupStates[key]!!.state = STATE_ALLOWED
+ if (allAffectedGranted || isCompatStorageGrant(appPermGroup)) {
+ groupStates[key] = GroupState(appPermGroup, state.isBackground,
+ state.affectedPermissions, STATE_ALLOWED)
}
}
} else {
@@ -625,7 +627,7 @@ class GrantPermissionsViewModel(
return false
}
- val purposes = PermissionMapping.getSafetyLabelSharingPurposesForGroup(safetyLabel,
+ val purposes = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(safetyLabel,
permissionGroupName)
return purposes.isNotEmpty()
}
@@ -804,6 +806,11 @@ class GrantPermissionsViewModel(
// then skip the request
return STATE_SKIPPED
}
+ // If the "false grant" for apps that don't support the permission has been applied,
+ // treat the permission as already granted
+ if (isCompatStorageGrant(group)) {
+ return STATE_ALLOWED
+ }
}
val isBackground = perm in group.backgroundPermNames
@@ -876,7 +883,7 @@ class GrantPermissionsViewModel(
* ACCESS_MEDIA_LOCATION granted
*/
private fun isPartialStorageGrant(group: LightAppPermGroup): Boolean {
- if (!KotlinUtils.isPhotoPickerPromptEnabled() || group.permGroupName != READ_MEDIA_VISUAL) {
+ if (group.permGroupName != READ_MEDIA_VISUAL || !KotlinUtils.isPhotoPickerPromptEnabled()) {
return false
}
@@ -886,6 +893,20 @@ class GrantPermissionsViewModel(
}
}
+ /**
+ * A compat storage grant is provided when the user selects "select photos" on an app that does
+ * not explicitly request the READ_MEDIA_VISUAL_USER_SELECTED permission. It grants RMVUS, and
+ * applies the "revoked compat" state to all other permissions in the group.
+ */
+ private fun isCompatStorageGrant(group: LightAppPermGroup): Boolean {
+ if (group.permGroupName != READ_MEDIA_VISUAL || !KotlinUtils.isPhotoPickerPromptEnabled()) {
+ return false
+ }
+ return group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]
+ ?.isGrantedIncludingAppOp == true &&
+ group.permissions.values.any { it.isCompatRevoked }
+ }
+
private fun getStateFromPolicy(perm: String, group: LightAppPermGroup): Int {
val isBackground = perm in group.backgroundPermNames
var skipGroup = false
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
index 00df47d3e..7633859fb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
@@ -55,7 +55,7 @@ import com.android.permissioncontroller.permission.ui.handheld.v31.shouldShowSub
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPackageLabel
import com.android.permissioncontroller.permission.utils.PermissionMapping
-import com.android.permissioncontroller.permission.utils.SubattributionUtils
+import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils
import com.android.permissioncontroller.permission.utils.Utils
import java.time.Instant
import java.util.Objects
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
index caf073632..561a8eef2 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
@@ -46,7 +46,7 @@ import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getAppStoreIntent
-import com.android.permissioncontroller.permission.utils.PermissionMapping
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
import com.android.settingslib.HelpUtils
/**
@@ -124,9 +124,9 @@ class PermissionRationaleViewModel(
KotlinUtils.getPackageLabel(app, it, Process.myUserHandle())
}
- val purposes = PermissionMapping.getSafetyLabelSharingPurposesForGroup(
+ val purposes = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
safetyLabelInfo.safetyLabel, permissionGroupName)
- if (isStale) {
+ if (value == null) {
logPermissionRationaleDialogViewed(purposes)
}
value =
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
index a5961dcec..e2df47009 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
@@ -66,13 +66,13 @@ import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData.FullStoragePackageState;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.AppPermissions;
-import com.android.permissioncontroller.permission.ui.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonState;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ChangeRequest;
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModelFactory;
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/AdvancedConfirmDialogArgs.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt
index 6b26c7e47..b841f3aeb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/AdvancedConfirmDialogArgs.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt
@@ -1,28 +1,27 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
- * Licensed under the Apache License;
- * Version 2.0 (the "License");
+ * 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.
+ * 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.permission.ui
+package com.android.permissioncontroller.permission.ui.v33
+import android.os.Build
import androidx.annotation.DrawableRes
+import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
data class AdvancedConfirmDialogArgs(
@DrawableRes val iconId: Int = 0,
@StringRes val titleId: Int = 0,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/CollectionUtils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/CollectionUtils.java
index 6f2a3079d..108120ced 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/CollectionUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/CollectionUtils.java
@@ -16,8 +16,6 @@
package com.android.permissioncontroller.permission.utils;
-import android.util.ArraySet;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -59,29 +57,6 @@ public final class CollectionUtils {
}
/**
- * Remove all values in the array set that do <b>not</b> exist in the given collection.
- *
- * @param <T> the class of the elements to retain and of the {@code ArraySet}
- * @param arraySet the {@code ArraySet} whose elements are to be removed or retained
- * @param valuesToRetain the values to be used to determine which elements to retain
- *
- * @return {@code true} if any values were removed from the array set, {@code false} otherwise.
- *
- * @see ArraySet#retainAll(java.util.Collection)
- */
- @SafeVarargs
- public static <T> boolean retainAll(ArraySet<T> arraySet, T... valuesToRetain) {
- boolean removed = false;
- for (int i = arraySet.size() - 1; i >= 0; i--) {
- if (!ArrayUtils.contains(valuesToRetain, arraySet.valueAt(i))) {
- arraySet.removeAt(i);
- removed = true;
- }
- }
- return removed;
- }
-
- /**
* Return a singleton list containing the element, or an empty list if the element is
* {@code null}.
*
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
index c4355b1e5..b06a09b28 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
@@ -26,11 +26,7 @@ import android.util.Log
import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
-import com.android.permission.safetylabel.DataCategory
import com.android.permission.safetylabel.DataCategoryConstants
-import com.android.permission.safetylabel.DataType
-import com.android.permission.safetylabel.DataTypeConstants
-import com.android.permission.safetylabel.SafetyLabel
/**
* This file contains the canonical mapping of permission to permission group, used in the
@@ -187,13 +183,6 @@ object PermissionMapping {
Manifest.permission_group.SENSORS
}
- if (SdkLevel.isAtLeastU()) {
- PLATFORM_PERMISSIONS[Utils.BODY_SENSORS_WRIST_TEMPERATURE] =
- Manifest.permission_group.SENSORS
- PLATFORM_PERMISSIONS[Utils.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND] =
- Manifest.permission_group.SENSORS
- }
-
for ((permission, permissionGroup) in PLATFORM_PERMISSIONS) {
PLATFORM_PERMISSION_GROUPS.getOrPut(permissionGroup) { mutableListOf() }.add(permission)
}
@@ -390,38 +379,6 @@ object PermissionMapping {
return AppOpsManager.opToPermission(opName)?.let { getGroupOfPlatformPermission(it) }
}
- /*
- * Get the sharing purposes for a SafetyLabel related to a specific permission group.
- */
- @JvmStatic
- fun getSafetyLabelSharingPurposesForGroup(
- safetyLabel: SafetyLabel,
- groupName: String
- ): Set<Int> {
- val purposeSet = mutableSetOf<Int>()
- val categoriesForPermission = getDataCategoriesForPermissionGroup(groupName)
- categoriesForPermission.forEach categoryLoop@{ category ->
- val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category]
- if (dataCategory == null) {
- // Continue to next
- return@categoryLoop
- }
- val typesForCategory = DataTypeConstants.getValidDataTypesForCategory(category)
- typesForCategory.forEach typeLoop@{ type ->
- val dataType: DataType? = dataCategory.dataTypes[type]
- if (dataType == null) {
- // Continue to next
- return@typeLoop
- }
- if (dataType.purposeSet.isNotEmpty()) {
- purposeSet.addAll(dataType.purposeSet)
- }
- }
- }
-
- return purposeSet
- }
-
/**
* Get the SafetyLabel categories pertaining to a specified permission group.
*
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index 7ccdd6465..d4354bd72 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -76,7 +76,6 @@ import android.hardware.SensorPrivacyManager;
import android.os.Binder;
import android.os.Build;
import android.os.Parcelable;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -110,8 +109,6 @@ import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo;
-import kotlin.Triple;
-
import java.lang.annotation.Retention;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
@@ -123,6 +120,8 @@ import java.util.Locale;
import java.util.Random;
import java.util.Set;
+import kotlin.Triple;
+
public final class Utils {
@Retention(SOURCE)
@@ -253,12 +252,6 @@ public final class Utils {
private static final String SYSTEM_VISUAL_INTELLIGENCE =
"android.app.role.SYSTEM_VISUAL_INTELLIGENCE";
- public static final String BODY_SENSORS_WRIST_TEMPERATURE =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE";
-
- public static final String BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND";
-
// TODO: theianchen Using hardcoded values here as a WIP solution for now.
private static final String[] EXEMPTED_ROLES = {
SYSTEM_AMBIENT_AUDIO_INTELLIGENCE,
@@ -660,10 +653,6 @@ public final class Utils {
return typedValue.resourceId;
}
- public static List<ApplicationInfo> getAllInstalledApplications(Context context) {
- return context.getPackageManager().getInstalledApplications(0);
- }
-
/**
* Is the group or background group user sensitive?
*
@@ -1073,38 +1062,6 @@ public final class Utils {
}
/**
- * Checks whether a package has an active one-time permission according to the system server's
- * flags
- *
- * @param context the {@code Context} to retrieve {@code PackageManager}
- * @param packageName The package to check for
- * @return Whether a package has an active one-time permission
- */
- public static boolean hasOneTimePermissions(Context context, String packageName) {
- String[] permissions;
- PackageManager pm = context.getPackageManager();
- try {
- permissions = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
- .requestedPermissions;
- } catch (NameNotFoundException e) {
- Log.w(LOG_TAG, "Checking for one-time permissions in nonexistent package");
- return false;
- }
- if (permissions == null) {
- return false;
- }
- for (String permissionName : permissions) {
- if ((pm.getPermissionFlags(permissionName, packageName, Process.myUserHandle())
- & PackageManager.FLAG_PERMISSION_ONE_TIME) != 0
- && pm.checkPermission(permissionName, packageName)
- == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- }
- return false;
- }
-
- /**
* Returns a random session ID value that's guaranteed to not be {@code INVALID_SESSION_ID}.
*
* @return A valid session ID.
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/AdminRestrictedPermissionsUtils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java
index 4944093ac..9b7927c1d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/AdminRestrictedPermissionsUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.utils;
+package com.android.permissioncontroller.permission.utils.v31;
import android.Manifest;
import android.app.admin.DevicePolicyManager;
@@ -24,6 +24,7 @@ import android.os.UserManager;
import android.util.ArraySet;
import com.android.modules.utils.build.SdkLevel;
+import com.android.permissioncontroller.permission.utils.Utils;
/**
* A class for dealing with permissions that the admin may not grant in certain configurations.
@@ -52,13 +53,6 @@ public final class AdminRestrictedPermissionsUtils {
if (SdkLevel.isAtLeastT()) {
ADMIN_RESTRICTED_SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS_BACKGROUND);
}
- // New U permissions - do not add unless running on U and above.
- if (SdkLevel.isAtLeastU()) {
- ADMIN_RESTRICTED_SENSORS_PERMISSIONS.add(
- Utils.BODY_SENSORS_WRIST_TEMPERATURE);
- ADMIN_RESTRICTED_SENSORS_PERMISSIONS.add(
- Utils.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND);
- }
}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/SubattributionUtils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/SubattributionUtils.java
index 2785eca74..8919953b4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/SubattributionUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/SubattributionUtils.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.utils;
+package com.android.permissioncontroller.permission.utils.v31;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.Attribution;
@@ -25,6 +24,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
+import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
@@ -42,6 +42,7 @@ public class SubattributionUtils {
/**
* Returns true if the app supports subattribution.
*/
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
public static boolean isSubattributionSupported(Context context, ApplicationInfo appInfo) {
if (!SdkLevel.isAtLeastS()) {
return false;
@@ -50,6 +51,7 @@ public class SubattributionUtils {
}
/** Returns whether the provided package supports subattribution. */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
public static boolean isSubattributionSupported(LightPackageInfo lightPackageInfo) {
return SdkLevel.isAtLeastS() && lightPackageInfo.getAreAttributionsUserVisible();
}
@@ -59,7 +61,6 @@ public class SubattributionUtils {
* {@code null} otherwise.
*/
@Nullable
- @SuppressLint("NewApi") // isSubattributionSupported checks api level
public static Map<Integer, String> getAttributionLabels(Context context, PackageInfo pkgInfo) {
if (!isSubattributionSupported(context, pkgInfo.applicationInfo)) {
return null;
@@ -72,7 +73,6 @@ public class SubattributionUtils {
* {@code null} otherwise.
*/
@Nullable
- @SuppressLint("NewApi") // isSubattributionSupported checks api level
public static Map<Integer, String> getAttributionLabels(Context context,
ApplicationInfo appInfo) {
if (!isSubattributionSupported(context, appInfo)) {
@@ -114,7 +114,6 @@ public class SubattributionUtils {
/** Returns the attribution label map for the package if the app supports subattribution. */
@Nullable
- @SuppressLint("NewApi") // isSubattributionSupported checks api level
public static Map<Integer, String> getAttributionLabels(Context context,
LightPackageInfo lightPackageInfo) {
if (!isSubattributionSupported(lightPackageInfo)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
new file mode 100644
index 000000000..5dbe203f9
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.permission.utils.v34
+
+import com.android.permission.safetylabel.DataCategory
+import com.android.permission.safetylabel.DataType
+import com.android.permission.safetylabel.DataTypeConstants
+import com.android.permission.safetylabel.SafetyLabel
+import com.android.permissioncontroller.permission.utils.PermissionMapping
+
+object SafetyLabelUtils {
+ /*
+ * Get the sharing purposes for a SafetyLabel related to a specific permission group.
+ */
+ @JvmStatic
+ fun getSafetyLabelSharingPurposesForGroup(
+ safetyLabel: SafetyLabel,
+ groupName: String
+ ): Set<Int> {
+ val purposeSet = mutableSetOf<Int>()
+ val categoriesForPermission = PermissionMapping
+ .getDataCategoriesForPermissionGroup(groupName)
+ categoriesForPermission.forEach categoryLoop@{ category ->
+ val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category]
+ if (dataCategory == null) {
+ // Continue to next
+ return@categoryLoop
+ }
+ val typesForCategory = DataTypeConstants.getValidDataTypesForCategory(category)
+ typesForCategory.forEach typeLoop@{ type ->
+ val dataType: DataType? = dataCategory.dataTypes[type]
+ if (dataType == null) {
+ // Continue to next
+ return@typeLoop
+ }
+ if (dataType.purposeSet.isNotEmpty()) {
+ purposeSet.addAll(dataType.purposeSet)
+ }
+ }
+ }
+
+ return purposeSet
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
index 11881e3ab..4ba685589 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
@@ -420,7 +420,7 @@ class AccessibilitySourceService(
// Start this Settings activity using the same UX that settings slices uses. This allows
// settings to correctly support 2-pane layout with as-best-as-possible transition
// animation.
- intent.putExtra(EXTRA_IS_FROM_SLICE, true)
+ intent.putExtra(Constants.EXTRA_IS_FROM_SLICE, true)
return PendingIntent.getActivity(
context,
0,
@@ -649,7 +649,6 @@ class AccessibilitySourceService(
private const val PROPERTY_SC_ACCESSIBILITY_JOB_INTERVAL_MILLIS =
"sc_accessibility_job_interval_millis"
private val DEFAULT_SC_ACCESSIBILITY_JOB_INTERVAL_MILLIS = TimeUnit.DAYS.toMillis(1)
- private val EXTRA_IS_FROM_SLICE = "is_from_slice"
private val sourceStateChanged = SafetyEvent.Builder(
SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt
index 874fe942e..885b8ea86 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt
@@ -39,8 +39,6 @@ import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.privacysources.WorkPolicyInfo.Companion.WORK_POLICY_INFO_SOURCE_ID
import com.android.permissioncontroller.privacysources.v34.AppDataSharingUpdatesPrivacySource
import com.android.permissioncontroller.privacysources.v34.AppDataSharingUpdatesPrivacySource.Companion.APP_DATA_SHARING_UPDATES_SOURCE_ID
-import com.android.permissioncontroller.privacysources.v34.HealthConnectPrivacySource
-import com.android.permissioncontroller.privacysources.v34.HealthConnectPrivacySource.Companion.HEALTH_CONNECT_SOURCE_ID
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Default
@@ -59,7 +57,6 @@ private fun createMapOfSourceIdsToSources(context: Context): Map<String, Privacy
if (SdkLevel.isAtLeastU()) {
sourceMap[APP_DATA_SHARING_UPDATES_SOURCE_ID] = AppDataSharingUpdatesPrivacySource()
- sourceMap[HEALTH_CONNECT_SOURCE_ID] = HealthConnectPrivacySource()
}
return sourceMap
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/v34/HealthConnectPrivacySource.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/v34/HealthConnectPrivacySource.kt
deleted file mode 100644
index f05b061c7..000000000
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/v34/HealthConnectPrivacySource.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.privacysources.v34
-
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.app.PendingIntent.FLAG_UPDATE_CURRENT
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
-import android.safetycenter.SafetySourceStatus
-import androidx.annotation.RequiresApi
-import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.utils.Utils
-import com.android.permissioncontroller.privacysources.PrivacySource
-import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent
-import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_DEVICE_REBOOTED
-import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_REFRESH_REQUESTED
-import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.UNKNOWN
-
-/**
- * Privacy source providing the Health Connect entry to Safety Center.
- *
- * The content of the Health Connect is static, however the entry should only be displayed if the
- * Health Connect Permission UI Enabled feature is enabled.
- */
-@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-class HealthConnectPrivacySource : PrivacySource {
-
- override val shouldProcessProfileRequest: Boolean = false
-
- override fun safetyCenterEnabledChanged(context: Context, enabled: Boolean) {
- // Do nothing.
- }
-
- override fun rescanAndPushSafetyCenterData(
- context: Context,
- intent: Intent,
- refreshEvent: RefreshEvent
- ) {
- val safetyCenterManager: SafetyCenterManager =
- Utils.getSystemServiceSafe(context, SafetyCenterManager::class.java)
-
- val safetySourceData =
- if (Utils.isHealthPermissionUiEnabled()) {
- SafetySourceData.Builder()
- .setStatus(
- SafetySourceStatus.Builder(
- context.getString(R.string.health_connect_title),
- context.getString(R.string.health_connect_summary),
- SEVERITY_LEVEL_UNSPECIFIED
- )
- .setPendingIntent(
- PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- Intent(HEALTH_CONNECT_INTENT_ACTION),
- FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
- )
- )
- .build(),
- )
- .build()
- } else {
- null
- }
-
- safetyCenterManager.setSafetySourceData(
- HEALTH_CONNECT_SOURCE_ID,
- safetySourceData,
- createSafetyEventForHealthConnect(refreshEvent, intent)
- )
- }
-
- private fun createSafetyEventForHealthConnect(
- refreshEvent: RefreshEvent,
- intent: Intent
- ): SafetyEvent {
- return when (refreshEvent) {
- EVENT_REFRESH_REQUESTED -> {
- val refreshBroadcastId =
- intent.getStringExtra(
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- )
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(refreshBroadcastId)
- .build()
- }
- EVENT_DEVICE_REBOOTED -> {
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build()
- }
- UNKNOWN -> {
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
- }
- }
- }
-
- /** Companion object for [HealthConnectPrivacySource]. */
- companion object {
- /** Source id for safety center source for health connect. */
- const val HEALTH_CONNECT_SOURCE_ID = "AndroidHealthConnect"
- const val HEALTH_CONNECT_INTENT_ACTION =
- "android.health.connect.action.HEALTH_HOME_SETTINGS"
- }
-}
diff --git a/PermissionController/tests/inprocess/Android.bp b/PermissionController/tests/inprocess/Android.bp
index 0cc355daa..78c767f1d 100644
--- a/PermissionController/tests/inprocess/Android.bp
+++ b/PermissionController/tests/inprocess/Android.bp
@@ -33,7 +33,10 @@ android_test {
target_sdk_version: "30",
min_sdk_version: "30",
- srcs: ["src/**/*.kt"],
+ srcs: [
+ "src/**/*.kt",
+ "src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java",
+ ],
libs: [
"android.test.base",
@@ -46,6 +49,7 @@ android_test {
"androidx.test.ext.junit",
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
+ "kotlin-test",
"permission-test-util-lib",
],
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java
new file mode 100644
index 000000000..b4b18dbbe
--- /dev/null
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.permission.compat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.SystemClock;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.Spanned;
+import android.text.method.MovementMethod;
+import android.text.style.ClickableSpan;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Test for {@link LinkMovementMethodCompat} without using Mockito, which is unavailable for
+ * in-process tests.
+ *
+ * @see android.text.method.cts.LinkMovementMethodTest
+ */
+public class LinkMovementMethodCompatTest {
+ private static final String CONTENT = "clickable\nunclickable\nclickable";
+
+ private Activity mActivity;
+ private LinkMovementMethodCompat mMethod;
+ private TextView mView;
+ private Spannable mSpannable;
+ private MockClickableSpan mClickable0;
+ private MockClickableSpan mClickable1;
+
+ @Rule
+ public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
+
+ @Before
+ public void setup() throws Throwable {
+ mActivity = mActivityRule.getActivity();
+ mMethod = new LinkMovementMethodCompat();
+
+ // Set the content view with a text view which contains 3 lines,
+ mActivityRule.runOnUiThread(() -> mView = new TextViewNoIme(mActivity));
+ mView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
+ mView.setText(CONTENT, TextView.BufferType.SPANNABLE);
+
+ mActivityRule.runOnUiThread(() -> mActivity.setContentView(mView));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ mSpannable = (Spannable) mView.getText();
+ // make first line clickable
+ mClickable0 = markClickable(0, CONTENT.indexOf('\n'));
+ // make last line clickable
+ mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length());
+ }
+
+ @Test
+ public void testConstructor() {
+ new LinkMovementMethodCompat();
+ }
+
+ @Test
+ public void testGetInstance() {
+ MovementMethod method0 = LinkMovementMethodCompat.getInstance();
+ assertTrue(method0 instanceof LinkMovementMethodCompat);
+
+ MovementMethod method1 = LinkMovementMethodCompat.getInstance();
+ assertNotNull(method1);
+ assertSame(method0, method1);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnTouchEvent() {
+ assertSelection(mSpannable, -1);
+
+ // press on first line (Clickable)
+ assertTrue(pressOnLine(0));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ // release on first line
+ mClickable0.clearClickCount();
+ assertTrue(releaseOnLine(0));
+ mClickable0.assertClickCount(1);
+
+ // press on second line (unclickable)
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+ // just clear selection
+ pressOnLine(1);
+ assertSelection(mSpannable, -1);
+
+ // press on last line (Clickable)
+ assertTrue(pressOnLine(2));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ // release on last line
+ mClickable1.clearClickCount();
+ assertTrue(releaseOnLine(2));
+ mClickable1.assertClickCount(1);
+
+ // release on second line (unclickable)
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+ // just clear selection
+ releaseOnLine(1);
+ assertSelection(mSpannable, -1);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnTouchEvent_outsideLineBounds() {
+ assertSelection(mSpannable, -1);
+
+ // press on first line (clickable)
+ assertTrue(pressOnLine(0));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ // release above first line
+ mClickable0.clearClickCount();
+ float x = (mView.getLayout().getLineLeft(0) + mView.getLayout().getLineRight(0)) / 2f;
+ float y = -1f;
+ assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
+ mClickable0.assertClickCount(0);
+
+ // press on first line (clickable)
+ assertTrue(pressOnLine(0));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ // release to left of first line
+ mClickable0.clearClickCount();
+ x = mView.getLayout().getLineLeft(0) - 1f;
+ y = (mView.getLayout().getLineTop(0) + mView.getLayout().getLineBottom(0)) / 2f;
+ assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
+ mClickable0.assertClickCount(0);
+
+ // press on first line (clickable)
+ assertTrue(pressOnLine(0));
+ assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+ // release to right of first line
+ mClickable0.clearClickCount();
+ x = mView.getLayout().getLineRight(0) + 1f;
+ y = (mView.getLayout().getLineTop(0) + mView.getLayout().getLineBottom(0)) / 2f;
+ assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
+ mClickable0.assertClickCount(0);
+
+ // press on last line (clickable)
+ assertTrue(pressOnLine(2));
+ assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+ // release below last line
+ mClickable1.clearClickCount();
+ x = (mView.getLayout().getLineLeft(0) + mView.getLayout().getLineRight(0)) / 2f;
+ y = mView.getLayout().getHeight() + 1f;
+ assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
+ mClickable1.assertClickCount(0);
+ }
+
+ private MockClickableSpan markClickable(final int start, final int end) throws Throwable {
+ final MockClickableSpan clickableSpan = new MockClickableSpan();
+ mActivityRule.runOnUiThread(() -> mSpannable.setSpan(clickableSpan, start, end,
+ Spanned.SPAN_MARK_MARK));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ return clickableSpan;
+ }
+ private boolean performMotionAtPoint(float x, float y, int action) {
+ long now = SystemClock.uptimeMillis();
+ return mMethod.onTouchEvent(mView, mSpannable,
+ MotionEvent.obtain(now, now, action, x, y, 0));
+ }
+
+ private boolean performMotionOnLine(int line, int action) {
+ float x = (mView.getLayout().getLineLeft(line) + mView.getLayout().getLineRight(line)) / 2f;
+ float y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2f;
+ return performMotionAtPoint(x, y, action);
+ }
+
+ private boolean pressOnLine(int line) {
+ return performMotionOnLine(line, MotionEvent.ACTION_DOWN);
+ }
+
+ private boolean releaseOnLine(int line) {
+ return performMotionOnLine(line, MotionEvent.ACTION_UP);
+ }
+
+ private void assertSelection(Spannable spannable, int start, int end) {
+ assertEquals(start, Selection.getSelectionStart(spannable));
+ assertEquals(end, Selection.getSelectionEnd(spannable));
+ }
+
+ private void assertSelection(Spannable spannable, int position) {
+ assertSelection(spannable, position, position);
+ }
+
+ private void assertSelectClickableLeftToRight(Spannable spannable,
+ ClickableSpan clickableSpan) {
+ assertSelection(spannable, spannable.getSpanStart(clickableSpan),
+ spannable.getSpanEnd(clickableSpan));
+ }
+
+ public static class TextViewNoIme extends TextView {
+ public TextViewNoIme(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ return null;
+ }
+ }
+
+ public static class MockClickableSpan extends ClickableSpan {
+ private int mClickCount = 0;
+
+ @Override
+ public void onClick(@NonNull View widget) {
+ ++mClickCount;
+ }
+
+ public void assertClickCount(int expectedClickCount) {
+ assertEquals(expectedClickCount, mClickCount);
+ }
+
+ public void clearClickCount() {
+ mClickCount = 0;
+ }
+ }
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt
new file mode 100644
index 000000000..305dcdfb7
--- /dev/null
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.permission.util
+
+import com.android.permissioncontroller.permission.utils.ArrayUtils
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class ArrayUtilsTest {
+ @Test
+ fun appendString_appendToNull_returnsArrayWithString() {
+ assertThat(ArrayUtils.appendString(null, TEST_STRING))
+ .isEqualTo(arrayOf(TEST_STRING))
+ }
+
+ @Test
+ fun appendString_appendToNull_returnsArrayWithNull() {
+ val result = ArrayUtils.appendString(null, null)
+ assertThat(result.size).isEqualTo(1)
+ assertThat(result[0]).isEqualTo(null)
+ }
+
+ @Test
+ fun appendString_duplicatedString_returnsArray() {
+ val cur = arrayOf("a", "b", TEST_STRING)
+ assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(cur)
+ }
+
+ @Test
+ fun appendString_appendNull_returnsArray() {
+ val cur = arrayOf("a", "b", null)
+ assertThat(ArrayUtils.appendString(cur, null)).isEqualTo(cur)
+ }
+
+ @Test
+ fun appendString_appendToEmptyArray_returnsArrayWithNewString() {
+ val cur = arrayOf<String>()
+ val new = arrayOf(TEST_STRING)
+ assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new)
+ }
+
+ @Test
+ fun appendString_appendNullToEmptyArray_returnsArrayWithNewString() {
+ val cur = arrayOf<String>()
+ val result = ArrayUtils.appendString(cur, null)
+ assertThat(result.size).isEqualTo(1)
+ assertThat(result[0]).isNull()
+ }
+
+ @Test
+ fun appendString_appendNewString() {
+ val cur = arrayOf("old test")
+ val new = arrayOf("old test", TEST_STRING)
+ assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new)
+ }
+
+ companion object {
+ private const val TEST_STRING = "test"
+ }
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt
new file mode 100644
index 000000000..bfcb67166
--- /dev/null
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.permission.util
+
+import com.android.permissioncontroller.permission.utils.CollectionUtils
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class CollectionUtilsTest {
+ @Test
+ fun testContains_true() {
+ val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3)
+
+ assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_1)).isTrue()
+ }
+
+ @Test
+ fun testContains_false() {
+ val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3)
+
+ assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_4)).isFalse()
+ }
+
+ @Test
+ fun testContainsSubset_true() {
+ val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3)
+ val otherByteArrays = setOf(TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3)
+
+ assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isTrue()
+ }
+
+ @Test
+ fun testContainsSubset_false() {
+ val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3)
+ val otherByteArrays = setOf(TEST_BYTE_ARRAY_3, TEST_BYTE_ARRAY_4)
+
+ assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isFalse()
+ }
+
+ companion object {
+ private val TEST_BYTE_ARRAY_1 = "I".toByteArray()
+ private val TEST_BYTE_ARRAY_2 = "love".toByteArray()
+ private val TEST_BYTE_ARRAY_3 = "Google".toByteArray()
+ private val TEST_BYTE_ARRAY_4 = "Hello".toByteArray()
+ }
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt
new file mode 100644
index 000000000..8f54da579
--- /dev/null
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt
@@ -0,0 +1,165 @@
+/*
+ * 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.permission.util
+
+import android.Manifest.permission.READ_MEDIA_IMAGES
+import android.Manifest.permission.READ_MEDIA_VIDEO
+import android.content.Context
+import android.content.Intent
+import android.content.Intent.ACTION_SHOW_APP_INFO
+import android.content.Intent.EXTRA_PACKAGE_NAME
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.mock
+import kotlin.test.assertFailsWith
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Unit tests for [KotlinUtils].
+ */
+@RunWith(AndroidJUnit4::class)
+class KotlinUtilsTest {
+ private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
+
+ @Test
+ fun convertToBitmap_argb888BitmapDrawable_returnsSameBitmap() {
+ val bitmap = Bitmap.createBitmap(/* width= */ 5, /* height= */ 10, Bitmap.Config.ARGB_8888)
+ val drawable = BitmapDrawable(targetContext.resources, bitmap)
+
+ assertThat(KotlinUtils.convertToBitmap(drawable).sameAs(bitmap)).isTrue()
+ }
+
+ @Test
+ fun convertToBitmap_noIntrinsicSize_throws() {
+ val drawable = FakeDrawable(intrinsicSize = 0)
+ assertFailsWith<IllegalArgumentException> { KotlinUtils.convertToBitmap(drawable) }
+ }
+
+ class FakeDrawable(private val intrinsicSize: Int) : Drawable() {
+ override fun getIntrinsicWidth() = intrinsicSize
+ override fun getIntrinsicHeight() = intrinsicSize
+
+ override fun draw(canvas: Canvas) = Unit // no-op
+ override fun getOpacity() = throw UnsupportedOperationException()
+ override fun setAlpha(alpha: Int) = throw UnsupportedOperationException()
+ override fun setColorFilter(colorFilter: ColorFilter?) =
+ throw UnsupportedOperationException()
+ }
+
+ @Test
+ fun getAppStoreIntent_returnsResolvedIntent() {
+ val installerPackage = "installer"
+ val installerActivity = "activity"
+ val appPackage = "app"
+ val mockContext = mock(Context::class.java)
+ val mockPackageManager = mock(PackageManager::class.java)
+ whenever(mockContext.packageManager).thenReturn(mockPackageManager)
+ val installerIntent = Intent(ACTION_SHOW_APP_INFO).setPackage(installerPackage)
+ whenever(
+ mockPackageManager.resolveActivity(
+ argThat { intent -> intent.filterEquals(installerIntent) }, /* flags= */ anyInt()))
+ .thenReturn(ResolveInfo().apply {
+ activityInfo = ActivityInfo().apply {
+ packageName = installerPackage
+ name = installerActivity
+ }
+ })
+
+ val intent = KotlinUtils.getAppStoreIntent(mockContext, installerPackage, appPackage)
+
+ assertThat(intent).isNotNull()
+ with (intent!!) {
+ assertThat(action).isEqualTo(ACTION_SHOW_APP_INFO)
+ assertThat(component?.packageName).isEqualTo(installerPackage)
+ assertThat(component?.className).isEqualTo(installerActivity)
+ }
+ }
+
+ @Test
+ fun getAppStoreIntent_returnsAppPackageInExtras() {
+ val appPackage = "app"
+ val mockContext = mock(Context::class.java)
+ val mockPackageManager = mock(PackageManager::class.java)
+ whenever(mockContext.packageManager).thenReturn(mockPackageManager)
+ whenever(
+ mockPackageManager.resolveActivity(any(), /* flags= */ anyInt()))
+ .thenReturn(ResolveInfo().apply {
+ activityInfo = ActivityInfo().apply {
+ packageName = ""
+ name = ""
+ }
+ })
+
+ val intent = KotlinUtils.getAppStoreIntent(mockContext, "com.installer", appPackage)
+
+ assertThat(intent).isNotNull()
+ assertThat(intent?.extras?.getString(EXTRA_PACKAGE_NAME)).isEqualTo(appPackage)
+ }
+
+ @Test
+ fun getAppStoreIntent_returnsNullWhenInstallerNotResolved() {
+ val mockContext = mock(Context::class.java)
+ whenever(mockContext.packageManager).thenReturn(mock(PackageManager::class.java))
+ // Un-stubbed activity resolution will return null.
+
+ assertThat(KotlinUtils.getAppStoreIntent(mockContext, "com.installer", "com.app")).isNull()
+ }
+
+ @Test
+ fun getMimeTypeForPermissions_onlyReadMediaImages_returnsImage() {
+ assertThat(KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, "read memes")))
+ .isEqualTo("image/*")
+ }
+
+ @Test
+ fun getMimeTypeForPermissions_onlyReadMediaVideo_returnsVideo() {
+ assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("write memes", READ_MEDIA_VIDEO)))
+ .isEqualTo("video/*")
+ }
+
+ @Test
+ fun getMimeTypeForPermissions_bothReadMediaPermissions_returnsNull() {
+ assertThat(
+ KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO)))
+ .isNull()
+ }
+
+ @Test
+ fun getMimeTypeForPermissions_noReadMediaPermissions_returnsNull() {
+ assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("amazing permission"))).isNull()
+ }
+
+ @Test
+ fun getMimeTypeForPermissions_emptyList_returnsNull() {
+ assertThat(KotlinUtils.getMimeTypeForPermissions(emptyList())).isNull()
+ }
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt
new file mode 100644
index 000000000..64a13df60
--- /dev/null
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.permission.util
+
+import android.Manifest
+import android.app.AppOpsManager
+import android.health.connect.HealthPermissions
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.permissioncontroller.permission.utils.PermissionMapping
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class PermissionMappingTest {
+ @Test
+ fun testGetPlatformPermissionGroupForOp_healthPermissionGroup() {
+ assertThat(PermissionMapping.getPlatformPermissionGroupForOp(
+ AppOpsManager.OPSTR_READ_WRITE_HEALTH_DATA
+ )).isEqualTo(HealthPermissions.HEALTH_PERMISSION_GROUP)
+ }
+
+ @Test
+ fun testGetPlatformPermissionGroupForOp_microphone() {
+ assertThat(PermissionMapping.getPlatformPermissionGroupForOp(
+ AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE
+ )).isEqualTo(Manifest.permission_group.MICROPHONE)
+ }
+
+ @Test
+ fun testGetPlatformPermissionGroupForOp_camera() {
+ assertThat(
+ PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_PHONE_CALL_CAMERA)
+ ).isEqualTo(Manifest.permission_group.CAMERA)
+ }
+
+ @Test
+ fun testGetPlatformPermissionGroupForOp_readContacts() {
+ assertThat(
+ PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_READ_CONTACTS)
+ ).isEqualTo(
+ PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.READ_CONTACTS)
+ )
+ }
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
index c53f94195..15218024e 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
@@ -17,23 +17,201 @@
package com.android.permissioncontroller.permission.util
import android.Manifest.permission.READ_CONTACTS
+import android.Manifest.permission_group.ACTIVITY_RECOGNITION
+import android.Manifest.permission_group.CALENDAR
+import android.Manifest.permission_group.CALL_LOG
+import android.Manifest.permission_group.CAMERA
import android.Manifest.permission_group.CONTACTS
+import android.Manifest.permission_group.LOCATION
+import android.Manifest.permission_group.MICROPHONE
+import android.Manifest.permission_group.NEARBY_DEVICES
+import android.Manifest.permission_group.PHONE
+import android.Manifest.permission_group.READ_MEDIA_AURAL
+import android.Manifest.permission_group.READ_MEDIA_VISUAL
+import android.Manifest.permission_group.SENSORS
+import android.Manifest.permission_group.SMS
+import android.Manifest.permission_group.STORAGE
+import android.Manifest.permission_group.UNDEFINED
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.content.SharedPreferences
+import android.content.pm.PackageManager.NameNotFoundException
import android.content.res.Resources
import androidx.test.platform.app.InstrumentationRegistry
import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
import com.android.permissioncontroller.Constants.INVALID_SESSION_ID
+import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.privacysources.WorkPolicyInfo
import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
import org.junit.Test
-
+import kotlin.test.assertFailsWith
class UtilsTest {
- private val context = InstrumentationRegistry.getInstrumentation().context as Context
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext as Context
+
+ @Test
+ fun getAbsoluteTimeString_zero_returnsNull() {
+ assertThat(Utils.getAbsoluteTimeString(context, 0)).isNull()
+ }
+
+ @Test
+ fun getAbsoluteTimeString_currentTime_returnsTimeFormatString() {
+ val time = Utils.getAbsoluteTimeString(context, System.currentTimeMillis())
+ assertThat(time).isNotNull()
+ if (time != null) {
+ if (time.contains(":")) {
+ val times = time.split(":")
+ assertThat(times.size).isEqualTo(2)
+ val isTime = times[1].contains("am", true) || times[1].contains("pm", true)
+ assertThat(isTime).isTrue()
+ } else {
+ assertThat(time.contains(".")).isTrue()
+ val times = time.split(".")
+ assertThat(times.size).isEqualTo(3)
+ }
+ }
+ }
+
+ @Test
+ fun getAbsoluteTimeString_previousDateTime_returnsDateFormatString() {
+ val lastAccessTime = 1680739840723L
+ val time = Utils.getAbsoluteTimeString(context, lastAccessTime)
+ assertThat(time == "Apr 5, 2023" || time == "Apr 6, 2023").isTrue()
+ }
+
+ @Test
+ fun getBlockedIcon_invalidGroupName_returnsMinusOne() {
+ assertThat(Utils.getBlockedIcon(INVALID_GROUP_NAME)).isEqualTo(-1)
+ }
+
+ @Test
+ fun getBlockedIcon_validGroupName() {
+ assertThat(Utils.getBlockedIcon(CAMERA)).isEqualTo(R.drawable.ic_camera_blocked)
+ }
+
+ @Test
+ fun getBlockedTitle_invalidGroupName_returnsMinusOne() {
+ assertThat(Utils.getBlockedTitle(INVALID_GROUP_NAME)).isEqualTo(-1)
+ }
+ @Test
+ fun getBlockedTitle_validGroupName() {
+ assertThat(Utils.getBlockedTitle(CAMERA)).isEqualTo(R.string.blocked_camera_title)
+ }
+
+ @Test
+ fun getDeviceProtectedSharedPreferences() {
+ assertThat(Utils.getDeviceProtectedSharedPreferences(context))
+ .isInstanceOf(SharedPreferences::class.java)
+ }
+
+ @Test
+ @Ignore("b/277782895")
+ fun getEnterpriseString() {
+ assertThat(Utils.getEnterpriseString(context, WorkPolicyInfo.WORK_POLICY_TITLE,
+ R.string.work_policy_title)).isInstanceOf(String::class.java)
+ }
+
+ @Test
+ fun getOneTimePermissionsTimeout_returnsNonNegativeTimeout() {
+ assertThat(Utils.getOneTimePermissionsTimeout()).isGreaterThan(0L)
+ }
+
+ @Test
+ fun getOneTimePermissionsKilledDelaySelfRevoked() {
+ assertThat(Utils.getOneTimePermissionsKilledDelay(true)).isEqualTo(0)
+ }
+
+ @Test
+ fun getOneTimePermissionsKilledDelayNonSelfRevoked() {
+ assertThat(Utils.getOneTimePermissionsKilledDelay(false)).isAtLeast(0L)
+ }
@Test
- fun assertGetOrGenerateSessionIdExpectedSessionId() {
+ fun getPackageInfoForComponentName_NonExistComponent_throwsNameNotFoundException() {
+ val testComponent = ComponentName("com.test.package", "TestClass")
+ assertFailsWith<NameNotFoundException> {
+ Utils.getPackageInfoForComponentName(context, testComponent)
+ }
+ }
+
+ @Test
+ fun getPermissionGroupDescriptionString_undefinedPermissionGroup() {
+ val description = "test permission group description"
+ val resultString =
+ context.getString(R.string.permission_description_summary_generic, description)
+ assertThat(Utils.getPermissionGroupDescriptionString(context, UNDEFINED, description))
+ .isEqualTo(resultString)
+ }
+
+ @Test
+ fun getPermissionGroupDescriptionString_validPermissionGroup() {
+ val permissionGroupNames = listOf(ACTIVITY_RECOGNITION, CALENDAR, CALL_LOG,
+ CAMERA, CONTACTS, LOCATION, MICROPHONE, NEARBY_DEVICES, PHONE, READ_MEDIA_AURAL,
+ READ_MEDIA_VISUAL, SENSORS, SMS, STORAGE)
+ for (permissionGroupName in permissionGroupNames) {
+ assertThat(Utils.getPermissionGroupDescriptionString(context, permissionGroupName, ""))
+ .isNotNull()
+ }
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_lastAccessSummaryTimestampIsNull() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(null, context, LOCATION)
+ assertThat(result.first).isEqualTo("")
+ assertThat(result.second).isEqualTo(Utils.NOT_IN_LAST_7D)
+ assertThat(result.third).isEqualTo("")
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsToday() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(System.currentTimeMillis(),
+ context, LOCATION)
+ assertThat(result.first).isNotEmpty()
+ assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_TODAY)
+ assertThat(result.third).isNotEmpty()
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsYesterday() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 24 * 60 * 60 * 1000, context, LOCATION)
+ assertThat(result.first).isNotEmpty()
+ assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_YESTERDAY)
+ assertThat(result.third).isNotEmpty()
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsLast7Days() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 5 * 24 * 60 * 60 * 1000, context, LOCATION)
+ assertThat(result.first).isNotEmpty()
+ assertThat(result.second).isEqualTo(Utils.LAST_7D_SENSOR)
+ assertThat(result.third).isNotEmpty()
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIsLast24Hrs() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis(), context, STORAGE)
+ assertThat(result.first).isNotEmpty()
+ assertThat(result.second).isEqualTo(Utils.LAST_24H_CONTENT_PROVIDER)
+ assertThat(result.third).isNotEmpty()
+ }
+
+ @Test
+ fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIs7Days() {
+ val result = Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 5 * 60 * 60 * 24 * 1000, context, STORAGE)
+ assertThat(result.first).isNotEmpty()
+ assertThat(result.second).isEqualTo(Utils.LAST_7D_CONTENT_PROVIDER)
+ assertThat(result.third).isNotEmpty()
+ }
+
+ @Test
+ fun getOrGenerateSessionId_validSessionId() {
val intent = Intent()
intent.putExtra(EXTRA_SESSION_ID, VALID_SESSION_ID)
val sessionId = Utils.getOrGenerateSessionId(intent)
@@ -41,15 +219,15 @@ class UtilsTest {
}
@Test
- fun assertGetOrGenerateSessionIdRandomSessionId() {
+ fun getOrGenerateSessionId_invalidSessionId() {
val intent = Intent()
val sessionId = Utils.getOrGenerateSessionId(intent)
assertThat(sessionId).isNotEqualTo(INVALID_SESSION_ID)
}
@Test
- fun assertGetGroupPermissionInfosValidGroup() {
- val permissionInfos = Utils.getGroupPermissionInfos(GROUP_NAME, context)
+ fun getGroupPermissionInfos_validGroupName_returnsGroupPermissions() {
+ val permissionInfos = Utils.getGroupPermissionInfos(CONTACTS, context)
assertThat(permissionInfos).isNotNull()
val permissions = mutableListOf<String>()
for (permissionInfo in permissionInfos!!) {
@@ -59,25 +237,38 @@ class UtilsTest {
}
@Test
- fun assertGetGroupPermissionInfosInValidGroup() {
+ fun getGroupPermissionInfos_inValidGroup_returnsNull() {
assertThat(Utils.getGroupPermissionInfos(INVALID_GROUP_NAME, context)).isNull()
}
@Test
- fun assertGetColorResIdValidId() {
+ fun getGroupPermissionInfos_undefinedGroup_returnsAllSystemPermissions() {
+ val permissionInfos = Utils.getGroupPermissionInfos(UNDEFINED, context)
+ assertThat(permissionInfos).isNotNull()
+ }
+
+ @Test
+ fun getGroupPermissionInfo_permissionName_returnsSamePermission() {
+ val permissionInfos = Utils.getGroupPermissionInfos(READ_CONTACTS, context)
+ assertThat(permissionInfos).isNotNull()
+ assertThat(permissionInfos!!.size).isEqualTo(1)
+ assertThat(permissionInfos[0].name).isEqualTo(READ_CONTACTS)
+ }
+
+ @Test
+ fun getColorResId_validId_returnsNonZero() {
assertThat(Utils.getColorResId(context, android.R.attr.colorPrimary))
.isNotEqualTo(Resources.ID_NULL)
}
@Test
- fun assertGetColorResIdInValidId() {
+ fun getColorResId_inValidId_returnsZero() {
assertThat(Utils.getColorResId(context, INVALID_ATTR_ID)).isEqualTo(Resources.ID_NULL)
}
companion object {
private const val INVALID_ATTR_ID = 1000
private const val VALID_SESSION_ID = 10000L
- private const val GROUP_NAME = CONTACTS
private const val INVALID_GROUP_NAME = "invalid group name"
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/HealthConnectPrivacySourceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/HealthConnectPrivacySourceTest.kt
deleted file mode 100644
index c68f1cc67..000000000
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/HealthConnectPrivacySourceTest.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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.tests.mocking.privacysources
-
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.app.PendingIntent.FLAG_UPDATE_CURRENT
-import android.content.Context
-import android.content.ContextWrapper
-import android.content.Intent
-import android.os.Build
-import android.provider.DeviceConfig
-import android.provider.DeviceConfig.NAMESPACE_PRIVACY
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES
-import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetySourceStatus
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.android.dx.mockito.inline.extended.ExtendedMockito
-import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.Utils
-import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_REFRESH_REQUESTED
-import com.android.permissioncontroller.privacysources.v34.HealthConnectPrivacySource
-import com.android.permissioncontroller.privacysources.v34.HealthConnectPrivacySource.Companion.HEALTH_CONNECT_SOURCE_ID
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-import org.mockito.MockitoSession
-import org.mockito.quality.Strictness
-
-/** Tests for [HealthConnectPrivacySource]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
-class HealthConnectPrivacySourceTest {
-
- private lateinit var mockitoSession: MockitoSession
- private lateinit var healthConnectPrivacySource: HealthConnectPrivacySource
- private lateinit var context: Context
- @Mock lateinit var mockSafetyCenterManager: SafetyCenterManager
-
- @Before
- fun setup() {
- context = ApplicationProvider.getApplicationContext()
- MockitoAnnotations.initMocks(this)
- mockitoSession =
- ExtendedMockito.mockitoSession()
- .mockStatic(DeviceConfig::class.java)
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Utils::class.java)
- .strictness(Strictness.LENIENT)
- .startMocking()
- whenever(
- Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java),
- eq(SafetyCenterManager::class.java)
- )
- )
- .thenReturn(mockSafetyCenterManager)
-
- healthConnectPrivacySource = HealthConnectPrivacySource()
- }
-
- @After
- fun cleanup() {
- mockitoSession.finishMocking()
- }
-
- @Test
- fun safetyCenterEnabledChanged_enabled_doesNothing() {
- healthConnectPrivacySource.safetyCenterEnabledChanged(context, true)
-
- verifyZeroInteractions(mockSafetyCenterManager)
- }
-
- @Test
- fun safetyCenterEnabledChanged_disabled_doesNothing() {
- healthConnectPrivacySource.safetyCenterEnabledChanged(context, false)
-
- verifyZeroInteractions(mockSafetyCenterManager)
- }
-
- @Test
- fun rescanAndPushSafetyCenterData_healthPermissionUIEnabled_setsDataWithStatus() {
- val refreshIntent =
- Intent(ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_ID)
-
- healthConnectPrivacySource.rescanAndPushSafetyCenterData(
- context,
- refreshIntent,
- EVENT_REFRESH_REQUESTED
- )
-
- val expectedSafetySourceData =
- if (Utils.isHealthPermissionUiEnabled()) {
- SafetySourceData.Builder()
- .setStatus(
- SafetySourceStatus.Builder(
- HEALTH_CONNECT_TITLE,
- HEALTH_CONNECT_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
- )
- .setPendingIntent(
- PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- Intent(HEALTH_CONNECT_INTENT_ACTION),
- FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
- )
- )
- .build()
- )
- .build()
- } else {
- null
- }
-
- val expectedSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(REFRESH_ID)
- .build()
- verify(mockSafetyCenterManager)
- .setSafetySourceData(
- HEALTH_CONNECT_SOURCE_ID,
- expectedSafetySourceData,
- expectedSafetyEvent
- )
- }
-
- @Test
- fun rescanAndPushSafetyCenterData_healthPermissionUIDisabled_setsNullData() {
- setHealthPermissionUIEnabled(false)
- val refreshIntent =
- Intent(ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_ID)
-
- healthConnectPrivacySource.rescanAndPushSafetyCenterData(
- context,
- refreshIntent,
- EVENT_REFRESH_REQUESTED
- )
-
- val expectedSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(REFRESH_ID)
- .build()
- verify(mockSafetyCenterManager)
- .setSafetySourceData(HEALTH_CONNECT_SOURCE_ID, null, expectedSafetyEvent)
- }
-
- /** Companion object for [HealthConnectPrivacySourceTest]. */
- companion object {
- // Real context, used in order to avoid mocking resources.
- const val HEALTH_CONNECT_TITLE: String = "Health Connect"
- const val HEALTH_CONNECT_SUMMARY: String = "Manage app access to health data"
- const val REFRESH_ID: String = "refresh_id"
- const val HEALTH_CONNECT_INTENT_ACTION =
- "android.health.connect.action.HEALTH_HOME_SETTINGS"
-
- /** Sets the value for the Health Permission feature [DeviceConfig] property. */
- private fun setHealthPermissionUIEnabled(enabled: Boolean) {
- whenever(
- DeviceConfig.getBoolean(
- eq(NAMESPACE_PRIVACY),
- eq("health_permission_ui_enabled"),
- anyBoolean()
- )
- )
- .thenReturn(enabled)
- }
- }
-}
diff --git a/SafetyCenter/Resources/res/raw-v34/safety_center_config.xml b/SafetyCenter/Resources/res/raw-v34/safety_center_config.xml
index 5fbf6e9f2..1c3330c63 100644
--- a/SafetyCenter/Resources/res/raw-v34/safety_center_config.xml
+++ b/SafetyCenter/Resources/res/raw-v34/safety_center_config.xml
@@ -67,9 +67,9 @@
<dynamic-safety-source
id="AndroidHealthConnect"
profile="primary_profile_only"
- packageName="com.android.permissioncontroller"
+ packageName="com.android.healthconnect.controller"
initialDisplayState="hidden"
- refreshOnPageOpenAllowed="true"
+ refreshOnPageOpenAllowed="false"
title="@com.android.safetycenter.resources:string/health_connect_title"
searchTerms="@com.android.safetycenter.resources:string/health_connect_search_terms"/>
<dynamic-safety-source
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataFactory.java b/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
index 5d03fa299..5d2d1ca88 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
@@ -597,7 +597,7 @@ public final class SafetyCenterDataFactory {
}
PendingIntent entryPendingIntent = safetySourceStatus.getPendingIntent();
boolean enabled = safetySourceStatus.isEnabled() && !inQuietMode;
- if (entryPendingIntent == null) {
+ if (entryPendingIntent == null || inQuietMode) {
entryPendingIntent =
mPendingIntentFactory.getPendingIntent(
safetySource.getId(),
@@ -809,7 +809,15 @@ public final class SafetyCenterDataFactory {
mSafetyCenterDataManager.getSafetySourceDataInternal(key));
boolean inQuietMode = isUserManaged && !isManagedUserRunning;
if (safetySourceStatus != null) {
- PendingIntent pendingIntent = safetySourceStatus.getPendingIntent();
+ PendingIntent pendingIntent =
+ inQuietMode
+ ? mPendingIntentFactory.getPendingIntent(
+ safetySource.getId(),
+ safetySource.getIntentAction(),
+ safetySource.getPackageName(),
+ userId,
+ true)
+ : safetySourceStatus.getPendingIntent();
if (pendingIntent == null) {
// TODO(b/222838784): Decide strategy for static entries when the intent is
// null.
diff --git a/service/java/com/android/safetycenter/SafetyCenterFlags.java b/service/java/com/android/safetycenter/SafetyCenterFlags.java
index 39c9e1be8..1a9949523 100644
--- a/service/java/com/android/safetycenter/SafetyCenterFlags.java
+++ b/service/java/com/android/safetycenter/SafetyCenterFlags.java
@@ -131,6 +131,9 @@ public final class SafetyCenterFlags {
private static volatile String sIssueCategoryAllowlistDefault = "";
+ private static volatile String sRefreshOnPageOpenSourcesDefault =
+ "AndroidBiometrics,AndroidLockScreen";
+
static void init(SafetyCenterResourcesContext resourceContext) {
String untrackedSourcesDefault =
resourceContext.getOptionalStringByName("config_defaultUntrackedSources");
@@ -147,6 +150,11 @@ public final class SafetyCenterFlags {
if (issueCategoryAllowlistDefault != null) {
sIssueCategoryAllowlistDefault = issueCategoryAllowlistDefault;
}
+ String refreshOnPageOpenSourcesDefault =
+ resourceContext.getOptionalStringByName("config_defaultRefreshOnPageOpenSources");
+ if (refreshOnPageOpenSourcesDefault != null) {
+ sRefreshOnPageOpenSourcesDefault = refreshOnPageOpenSourcesDefault;
+ }
}
private static final Duration TEMP_HIDDEN_ISSUE_RESURFACE_DELAY_DEFAULT_DURATION =
@@ -468,7 +476,8 @@ public final class SafetyCenterFlags {
* refreshOnPageOpenAllowed is false (the default) in the XML config.
*/
static ArraySet<String> getOverrideRefreshOnPageOpenSourceIds() {
- return getCommaSeparatedStrings(PROPERTY_OVERRIDE_REFRESH_ON_PAGE_OPEN_SOURCES);
+ return getCommaSeparatedStrings(
+ PROPERTY_OVERRIDE_REFRESH_ON_PAGE_OPEN_SOURCES, sRefreshOnPageOpenSourcesDefault);
}
private static Duration getDuration(String property, Duration defaultValue) {