summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-07-25 15:48:22 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-07-25 15:48:22 +0000
commitcf49f66e16d9dcbf4fbecc6917a31156c86dc178 (patch)
tree960ccb8b68e9fd72b883444bca15e94250fd6ff1
parentbced3294893b3ad108b9b4b33f37cdabf9873772 (diff)
parent8e9c95fb2e77f922f6499e64b8803823daae9f30 (diff)
downloadSettings-android13-mainline-go-os-statsd-release.tar.gz
Snap for 8866753 from 8e9c95fb2e77f922f6499e64b8803823daae9f30 to mainline-go-os-statsd-releaseaml_go_sta_330911000android13-mainline-go-os-statsd-release
Change-Id: I8e3025a3723b4947628f1a67603b24c3cfe38d38
-rw-r--r--res/values/integers.xml3
-rw-r--r--res/values/overlayable.xml10
-rw-r--r--res/values/preference_keys.xml8
-rw-r--r--res/values/preference_screen_keys.xml2
-rw-r--r--res/values/strings.xml16
-rw-r--r--res/xml/location_recent_accessed_view_all_fragment.xml24
-rw-r--r--res/xml/location_recent_requests_fragment.xml24
-rw-r--r--res/xml/location_settings_fragment.xml12
-rw-r--r--src/com/android/car/settings/location/LocationRecentAccessUtil.java72
-rw-r--r--src/com/android/car/settings/location/LocationRecentAccessViewAllFragment.java78
-rw-r--r--src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceController.java112
-rw-r--r--src/com/android/car/settings/location/LocationRecentAccessesPreferenceController.java189
-rw-r--r--src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceController.java78
-rw-r--r--src/com/android/car/settings/location/RecentLocationRequestsFragment.java34
-rw-r--r--src/com/android/car/settings/location/RecentLocationRequestsPreferenceController.java137
-rw-r--r--src/com/android/car/settings/wifi/WifiRequestToggleActivity.java4
-rw-r--r--tests/unit/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceControllerTest.java189
-rw-r--r--tests/unit/src/com/android/car/settings/location/LocationRecentAccessesPreferenceControllerTest.java303
-rw-r--r--tests/unit/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceControllerTest.java139
-rw-r--r--tests/unit/src/com/android/car/settings/location/RecentLocationRequestsPreferenceControllerTest.java125
-rw-r--r--tests/unit/src/com/android/car/settings/privacy/MicrophoneRecentAccessViewAllPreferenceControllerTest.java3
21 files changed, 1005 insertions, 557 deletions
diff --git a/res/values/integers.xml b/res/values/integers.xml
index 436948a83..0467d3bc5 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -61,6 +61,9 @@
<!-- Maximum number of apps to be shown in RecentNotificationsAppsPreferenceController -->
<integer name="recent_notifications_apps_list_count">3</integer>
+ <!-- Maximum number of apps to be shown in LocationRecentAccessesPreferenceController -->
+ <integer name="recent_location_access_apps_list_count">2</integer>
+
<!-- Maximum number of apps to be shown in MicrophoneRecentAccessesPreferenceController -->
<integer name="recent_microphone_access_apps_list_count">2</integer>
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
index b1ff8e7e8..e4f2a48c7 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -543,6 +543,7 @@ REGENERATE USING packages/apps/Car/libs/tools/rro/generate-overlayable.py
<item type="integer" name="recent_apps_days_threshold"/>
<item type="integer" name="recent_apps_max_count"/>
<item type="integer" name="recent_camera_access_apps_list_count"/>
+ <item type="integer" name="recent_location_access_apps_list_count"/>
<item type="integer" name="recent_microphone_access_apps_list_count"/>
<item type="integer" name="recent_notifications_apps_list_count"/>
<item type="integer" name="recent_notifications_days_threshold"/>
@@ -1054,8 +1055,11 @@ REGENERATE USING packages/apps/Car/libs/tools/rro/generate-overlayable.py
<item type="string" name="location_driver_assistance_toggle_title"/>
<item type="string" name="location_settings_app_permissions_title"/>
<item type="string" name="location_settings_footer"/>
- <item type="string" name="location_settings_recent_requests_empty_message"/>
- <item type="string" name="location_settings_recent_requests_title"/>
+ <item type="string" name="location_settings_recently_accessed_title"/>
+ <item type="string" name="location_recently_accessed"/>
+ <item type="string" name="location_settings_recently_accessed_view_all_title"/>
+ <item type="string" name="location_no_recent_access"/>
+ <item type="string" name="driver_assistance_label"/>
<item type="string" name="location_settings_services_title"/>
<item type="string" name="location_settings_title"/>
<item type="string" name="location_state_switch_content_description"/>
@@ -1605,8 +1609,8 @@ REGENERATE USING packages/apps/Car/libs/tools/rro/generate-overlayable.py
<item type="xml" name="language_picker_fragment"/>
<item type="xml" name="languages_and_input_fragment"/>
<item type="xml" name="legal_information_fragment"/>
- <item type="xml" name="location_recent_requests_fragment"/>
<item type="xml" name="location_settings_fragment"/>
+ <item type="xml" name="location_recent_accessed_view_all_fragment"/>
<item type="xml" name="manage_domain_urls_fragment"/>
<item type="xml" name="microphone_recent_requests_view_all_fragment"/>
<item type="xml" name="mobile_network_fragment"/>
diff --git a/res/values/preference_keys.xml b/res/values/preference_keys.xml
index 7b94fc929..3373f624a 100644
--- a/res/values/preference_keys.xml
+++ b/res/values/preference_keys.xml
@@ -370,11 +370,11 @@
<string name="pk_units_pressure" translatable="false">units_pressure</string>
<!-- Location Settings -->
- <string name="pk_location_recent_requests_entry" translatable="false">
- location_recent_requests_entry
+ <string name="pk_location_recent_accesses_category" translatable="false">
+ location_recent_accesses_category
</string>
- <string name="pk_location_recent_requests" translatable="false">
- location_recent_requests
+ <string name="pk_location_recently_accessed" translatable="false">
+ location_recently_accessed
</string>
<string name="pk_location_app_permissions" translatable="false">location_app_permissions
</string>
diff --git a/res/values/preference_screen_keys.xml b/res/values/preference_screen_keys.xml
index cd1fa8223..a03c32487 100644
--- a/res/values/preference_screen_keys.xml
+++ b/res/values/preference_screen_keys.xml
@@ -64,7 +64,7 @@
<string name="psk_language_picker" translatable="false">language_picker_screen</string>
<string name="psk_languages_and_input" translatable="false">languages_and_input_screen</string>
<string name="psk_legal_information" translatable="false">legal_information_screen</string>
- <string name="psk_location_recent_requests" translatable="false">location_recent_requests_screen</string>
+ <string name="psk_location_recently_accessed" translatable="false">location_recently_accessed_screen</string>
<string name="psk_location_settings" translatable="false">location_settings_screen</string>
<string name="psk_adas_settings" translatable="false">adas_settings_screen</string>
<string name="psk_microphone_recent_requests" translatable="false">microphone_recent_requests_screen</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d32b9124d..0e310a839 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -922,10 +922,16 @@
<string name="driver_assistance_warning_confirm_label">
Turn off anyway
</string>
- <!-- Title of Recent Location Requests setting [CHAR LIMIT=60] -->
- <string name="location_settings_recent_requests_title">Recent Location Requests</string>
- <!-- Message indicating that no apps have requested location recently [CHAR LIMIT=60] -->
- <string name="location_settings_recent_requests_empty_message">No recent location requests</string>
+ <!-- Title of Recent Location Accesses category [CHAR LIMIT=60] -->
+ <string name="location_recently_accessed">Recently accessed</string>
+ <!-- Title of Location Recently Accessed setting [CHAR LIMIT=60] -->
+ <string name="location_settings_recently_accessed_title">Recently accessed</string>
+ <!-- Title of preference name to view all apps that recently accessed location [CHAR LIMIT=60] -->
+ <string name="location_settings_recently_accessed_view_all_title">View all</string>
+ <!-- Message indicating that no apps have accessed location recently [CHAR LIMIT=60] -->
+ <string name="location_no_recent_access">No recent apps</string>
+ <!-- Label for driver assistance apps that recently accessed location [CHAR LIMIT=60] -->
+ <string name="driver_assistance_label"><xliff:g id="time" example="1 min. ago">%1$s</xliff:g> \u2022 Driver Assistance</string>
<!-- Title of Location App-level Permissions setting [CHAR LIMIT=60] -->
<string name="location_settings_app_permissions_title">App-level permissions</string>
<!-- Title of Location Services category [CHAR LIMIT=60] -->
@@ -978,7 +984,7 @@
</string>
<!-- Title of Recent Microphone Requests setting [CHAR LIMIT=60] -->
<string name="microphone_settings_recent_requests_title">Recently accessed</string>
- <!-- Title of Recent Microphone Requests setting [CHAR LIMIT=60] -->
+ <!-- Title of preference name to view all apps that recently accessed microphone [CHAR LIMIT=60] -->
<string name="microphone_settings_recent_requests_view_all_title">View all</string>
<!-- Microphone settings, loading the number of apps which have microphone permission [CHAR LIMIT=30] -->
<string name="microphone_settings_loading_app_permission_stats">Loading\u2026</string>
diff --git a/res/xml/location_recent_accessed_view_all_fragment.xml b/res/xml/location_recent_accessed_view_all_fragment.xml
new file mode 100644
index 000000000..c29a1ec8c
--- /dev/null
+++ b/res/xml/location_recent_accessed_view_all_fragment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="@string/psk_location_recently_accessed"
+ android:title="@string/location_settings_recently_accessed_title">
+ <com.android.car.settings.common.LogicalPreferenceGroup
+ android:key="@string/pk_location_recently_accessed"
+ settings:controller="com.android.car.settings.location.LocationRecentAccessViewAllPreferenceController"/>
+</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/location_recent_requests_fragment.xml b/res/xml/location_recent_requests_fragment.xml
deleted file mode 100644
index af494cc63..000000000
--- a/res/xml/location_recent_requests_fragment.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:key="@string/psk_location_recent_requests"
- android:title="@string/location_settings_recent_requests_title">
- <com.android.car.settings.common.LogicalPreferenceGroup
- android:key="@string/pk_location_recent_requests"
- settings:controller="com.android.car.settings.location.RecentLocationRequestsPreferenceController"/>
-</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/location_settings_fragment.xml b/res/xml/location_settings_fragment.xml
index 2dd4bb100..95c25dac0 100644
--- a/res/xml/location_settings_fragment.xml
+++ b/res/xml/location_settings_fragment.xml
@@ -35,11 +35,13 @@
settings:controller="com.android.car.settings.location.AdasLocationSwitchPreferenceController"
settings:searchable="true"/>
<com.android.car.settings.common.DividerPreference/>
- <Preference
- android:fragment="com.android.car.settings.location.RecentLocationRequestsFragment"
- android:key="@string/pk_location_recent_requests_entry"
- android:title="@string/location_settings_recent_requests_title"
- settings:controller="com.android.car.settings.location.RecentLocationRequestsEntryPreferenceController"/>
+ <PreferenceCategory
+ android:key="@string/pk_location_recent_accesses_category"
+ android:title="@string/location_recently_accessed"
+ settings:controller="com.android.car.settings.location.LocationRecentAccessesPreferenceController">
+ <com.android.car.settings.common.DividerPreference
+ android:order="999"/>
+ </PreferenceCategory>
<Preference
android:key="@string/pk_location_app_permissions"
android:title="@string/location_settings_app_permissions_title"
diff --git a/src/com/android/car/settings/location/LocationRecentAccessUtil.java b/src/com/android/car/settings/location/LocationRecentAccessUtil.java
new file mode 100644
index 000000000..25e92a423
--- /dev/null
+++ b/src/com/android/car/settings/location/LocationRecentAccessUtil.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.icu.text.RelativeDateTimeFormatter;
+
+import com.android.car.settings.R;
+import com.android.car.ui.preference.CarUiPreference;
+import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.applications.RecentAppOpsAccess;
+import com.android.settingslib.utils.StringUtil;
+
+/** Utilities related to location recent access. */
+public final class LocationRecentAccessUtil {
+ private LocationRecentAccessUtil() {}
+
+ /**
+ * Create a {@link CarUiPreference} for an app with it's last access time and a link to its
+ * location permission settings.
+ */
+ public static CarUiPreference createAppPreference(
+ Context prefContext, RecentAppOpsAccess.Access access) {
+ CarUiPreference pref = new CarUiPreference(prefContext);
+ pref.setIcon(access.icon);
+ pref.setTitle(access.label);
+ String summary =
+ StringUtil.formatRelativeTime(
+ prefContext,
+ System.currentTimeMillis() - access.accessFinishTime,
+ /* withSeconds= */ false,
+ RelativeDateTimeFormatter.Style.SHORT)
+ .toString();
+ if (ArrayUtils.contains(
+ prefContext
+ .getResources()
+ .getStringArray(
+ com.android.internal.R.array
+ .config_locationDriverAssistancePackageNames),
+ access.packageName)) {
+ summary =
+ prefContext.getResources().getString(R.string.driver_assistance_label, summary);
+ }
+ pref.setSummary(summary);
+ pref.setOnPreferenceClickListener(
+ preference -> {
+ Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+ intent.putExtra(
+ Intent.EXTRA_PERMISSION_GROUP_NAME, Manifest.permission_group.LOCATION);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, access.packageName);
+ intent.putExtra(Intent.EXTRA_USER, access.userHandle);
+ prefContext.startActivity(intent);
+ return true;
+ });
+ return pref;
+ }
+}
diff --git a/src/com/android/car/settings/location/LocationRecentAccessViewAllFragment.java b/src/com/android/car/settings/location/LocationRecentAccessViewAllFragment.java
new file mode 100644
index 000000000..7e2196d32
--- /dev/null
+++ b/src/com/android/car/settings/location/LocationRecentAccessViewAllFragment.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.SettingsFragment;
+import com.android.car.ui.toolbar.MenuItem;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** All apps that have recently accessed location. */
+public class LocationRecentAccessViewAllFragment extends SettingsFragment {
+
+ private boolean mShowSystem = false;
+ private MenuItem mShowHideSystemMenu;
+ private LocationRecentAccessViewAllPreferenceController mController;
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.location_recent_accessed_view_all_fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mShowHideSystemMenu =
+ new MenuItem.Builder(getContext())
+ .setTitle(R.string.show_system)
+ .setOnClickListener(i -> setShowSystem(!mShowSystem))
+ .build();
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mController =
+ use(
+ LocationRecentAccessViewAllPreferenceController.class,
+ R.string.pk_location_recently_accessed);
+ }
+
+ @Override
+ protected List<MenuItem> getToolbarMenuItems() {
+ return Arrays.asList(mShowHideSystemMenu);
+ }
+
+ private void setShowSystem(boolean showSystem) {
+ if (showSystem != mShowSystem) {
+ mShowSystem = showSystem;
+ mController.setShowSystem(showSystem);
+ updateMenu();
+ }
+ }
+
+ private void updateMenu() {
+ mShowHideSystemMenu.setTitle(mShowSystem ? R.string.hide_system : R.string.show_system);
+ }
+}
diff --git a/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceController.java b/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceController.java
new file mode 100644
index 000000000..fa9e1b1dd
--- /dev/null
+++ b/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceController.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.LogicalPreferenceGroup;
+import com.android.car.settings.common.PreferenceController;
+import com.android.car.ui.preference.CarUiPreference;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.applications.RecentAppOpsAccess;
+
+import java.util.List;
+
+/**
+ * This controller displays a list of apps recently accessing location. Driver assistance apps are
+ * also included.
+ */
+public class LocationRecentAccessViewAllPreferenceController
+ extends PreferenceController<LogicalPreferenceGroup> {
+
+ private final RecentAppOpsAccess mRecentLocationAccesses;
+ private boolean mShowSystem = false;
+
+ public LocationRecentAccessViewAllPreferenceController(
+ Context context,
+ String preferenceKey,
+ FragmentController fragmentController,
+ CarUxRestrictions uxRestrictions) {
+ this(
+ context,
+ preferenceKey,
+ fragmentController,
+ uxRestrictions,
+ RecentAppOpsAccess.createForLocation(context));
+ }
+
+ @VisibleForTesting
+ LocationRecentAccessViewAllPreferenceController(
+ Context context,
+ String preferenceKey,
+ FragmentController fragmentController,
+ CarUxRestrictions uxRestrictions,
+ RecentAppOpsAccess recentLocationAccesses) {
+ super(context, preferenceKey, fragmentController, uxRestrictions);
+ mRecentLocationAccesses = recentLocationAccesses;
+ }
+
+ @Override
+ protected Class<LogicalPreferenceGroup> getPreferenceType() {
+ return LogicalPreferenceGroup.class;
+ }
+
+ @Override
+ public void updateState(LogicalPreferenceGroup preference) {
+ super.updateState(preference);
+ List<RecentAppOpsAccess.Access> recentLocationAccesses = loadData();
+ updateUi(recentLocationAccesses);
+ }
+
+ /**
+ * Rebuilds the preference list to show system applications if {@code showSystem} is true.
+ * System applications will be hidden otherwise.
+ */
+ public void setShowSystem(boolean showSystem) {
+ if (mShowSystem != showSystem) {
+ mShowSystem = showSystem;
+ refreshUi();
+ }
+ }
+
+ private List<RecentAppOpsAccess.Access> loadData() {
+ return mRecentLocationAccesses.getAppListSorted(mShowSystem);
+ }
+
+ private void updateUi(List<RecentAppOpsAccess.Access> recentLocationAccesses) {
+ getPreference().removeAll();
+ if (recentLocationAccesses.isEmpty()) {
+ getPreference().addPreference(createNoRecentAccessPreference());
+ } else {
+ for (RecentAppOpsAccess.Access access : recentLocationAccesses) {
+ CarUiPreference appPreference =
+ LocationRecentAccessUtil.createAppPreference(getContext(), access);
+ getPreference().addPreference(appPreference);
+ }
+ }
+ }
+
+ private CarUiPreference createNoRecentAccessPreference() {
+ CarUiPreference preference = new CarUiPreference(getContext());
+ preference.setTitle(R.string.location_no_recent_access);
+ preference.setSelectable(false);
+ return preference;
+ }
+}
diff --git a/src/com/android/car/settings/location/LocationRecentAccessesPreferenceController.java b/src/com/android/car/settings/location/LocationRecentAccessesPreferenceController.java
new file mode 100644
index 000000000..a1b141512
--- /dev/null
+++ b/src/com/android/car/settings/location/LocationRecentAccessesPreferenceController.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.LocationManager;
+
+import androidx.preference.PreferenceCategory;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceController;
+import com.android.car.ui.preference.CarUiPreference;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.applications.RecentAppOpsAccess;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This controller displays a list of apps that recently access the location. Driver assistance apps
+ * are also included.
+ */
+public class LocationRecentAccessesPreferenceController
+ extends PreferenceController<PreferenceCategory> {
+
+ private final LocationManager mLocationManager;
+ private final BroadcastReceiver mAdasReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ refreshUi();
+ }
+ };
+ private final BroadcastReceiver mLocationReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ refreshUi();
+ }
+ };
+
+ private static final IntentFilter INTENT_FILTER_ADAS_GNSS_ENABLED_CHANGED =
+ new IntentFilter(LocationManager.ACTION_ADAS_GNSS_ENABLED_CHANGED);
+
+ private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED =
+ new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
+
+ private final Set<CarUiPreference> mAddedPreferences = new HashSet<>();
+
+ private final RecentAppOpsAccess mRecentLocationAccesses;
+ private final int mRecentAppsMaxCount;
+
+ public LocationRecentAccessesPreferenceController(
+ Context context,
+ String preferenceKey,
+ FragmentController fragmentController,
+ CarUxRestrictions uxRestrictions) {
+ this(
+ context,
+ preferenceKey,
+ fragmentController,
+ uxRestrictions,
+ RecentAppOpsAccess.createForLocation(context),
+ context.getResources().getInteger(R.integer.recent_location_access_apps_list_count),
+ context.getSystemService(LocationManager.class));
+ }
+
+ @VisibleForTesting
+ LocationRecentAccessesPreferenceController(
+ Context context,
+ String preferenceKey,
+ FragmentController fragmentController,
+ CarUxRestrictions uxRestrictions,
+ RecentAppOpsAccess recentLocationAccesses,
+ int recentAppsMaxCount,
+ LocationManager locationManager) {
+ super(context, preferenceKey, fragmentController, uxRestrictions);
+ mRecentLocationAccesses = recentLocationAccesses;
+ mRecentAppsMaxCount = recentAppsMaxCount;
+ mLocationManager = locationManager;
+ }
+
+ @Override
+ protected Class<PreferenceCategory> getPreferenceType() {
+ return PreferenceCategory.class;
+ }
+
+ @Override
+ protected void onStartInternal() {
+ getContext().registerReceiver(mAdasReceiver, INTENT_FILTER_ADAS_GNSS_ENABLED_CHANGED);
+ getContext().registerReceiver(mLocationReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED);
+ }
+
+ @Override
+ protected void onStopInternal() {
+ getContext().unregisterReceiver(mAdasReceiver);
+ getContext().unregisterReceiver(mLocationReceiver);
+ }
+
+ @Override
+ public void updateState(PreferenceCategory preference) {
+ super.updateState(preference);
+
+ if (!mLocationManager.isLocationEnabled()
+ && !mLocationManager.isAdasGnssLocationEnabled()) {
+ getPreference().setVisible(false);
+ return;
+ }
+ getPreference().setVisible(true);
+ updateUi(loadData());
+ }
+
+ private List<RecentAppOpsAccess.Access> loadData() {
+ return mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false);
+ }
+
+ private boolean hasAtLeastOneRecentAppAccess() {
+ return !mRecentLocationAccesses.getAppListSorted(/* showSystem= */ true).isEmpty();
+ }
+
+ private void updateUi(List<RecentAppOpsAccess.Access> sortedRecentLocationAccesses) {
+ // remove any already added preferences
+ for (CarUiPreference addedPreference : mAddedPreferences) {
+ getPreference().removePreference(addedPreference);
+ }
+ mAddedPreferences.clear();
+
+ if (sortedRecentLocationAccesses.isEmpty()) {
+ CarUiPreference emptyPreference = createNoRecentAccessPreference();
+ getPreference().addPreference(emptyPreference);
+ mAddedPreferences.add(emptyPreference);
+ } else {
+ int count = Math.min(sortedRecentLocationAccesses.size(), mRecentAppsMaxCount);
+ for (int i = 0; i < count; i++) {
+ RecentAppOpsAccess.Access request = sortedRecentLocationAccesses.get(i);
+ CarUiPreference appPreference =
+ LocationRecentAccessUtil.createAppPreference(getContext(), request);
+ getPreference().addPreference(appPreference);
+ mAddedPreferences.add(appPreference);
+ }
+ }
+
+ if (hasAtLeastOneRecentAppAccess()) {
+ CarUiPreference viewAllPreference = createViewAllPreference();
+ getPreference().addPreference(viewAllPreference);
+ mAddedPreferences.add(viewAllPreference);
+ }
+ }
+
+ private CarUiPreference createNoRecentAccessPreference() {
+ CarUiPreference preference = new CarUiPreference(getContext());
+ preference.setTitle(R.string.location_no_recent_access);
+ preference.setSelectable(false);
+ return preference;
+ }
+
+ private CarUiPreference createViewAllPreference() {
+ CarUiPreference preference = new CarUiPreference(getContext());
+ preference.setTitle(R.string.location_settings_recently_accessed_view_all_title);
+ preference.setIcon(R.drawable.ic_apps);
+ preference.setOnPreferenceClickListener(
+ p -> {
+ getFragmentController()
+ .launchFragment(new LocationRecentAccessViewAllFragment());
+ return true;
+ });
+ return preference;
+ }
+}
diff --git a/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceController.java b/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceController.java
deleted file mode 100644
index c6025dde2..000000000
--- a/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settings.location;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.PreferenceController;
-
-/**
- * Disables Recent Location Requests entry when location is off.
- */
-public class RecentLocationRequestsEntryPreferenceController extends
- PreferenceController<Preference> {
-
- private final LocationManager mLocationManager;
-
- @VisibleForTesting
- static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED =
- new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
-
- @VisibleForTesting
- final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- refreshUi();
- }
- };
-
- public RecentLocationRequestsEntryPreferenceController(Context context, String preferenceKey,
- FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
- super(context, preferenceKey, fragmentController, uxRestrictions);
- mLocationManager = getContext().getSystemService(LocationManager.class);
- }
-
-
- @Override
- protected Class<Preference> getPreferenceType() {
- return Preference.class;
- }
-
- @Override
- protected void updateState(Preference preference) {
- preference.setEnabled(mLocationManager.isLocationEnabled());
- }
-
- @Override
- protected void onStartInternal() {
- getContext().registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED);
- }
-
- @Override
- protected void onStopInternal() {
- getContext().unregisterReceiver(mReceiver);
- }
-}
diff --git a/src/com/android/car/settings/location/RecentLocationRequestsFragment.java b/src/com/android/car/settings/location/RecentLocationRequestsFragment.java
deleted file mode 100644
index 592225a57..000000000
--- a/src/com/android/car/settings/location/RecentLocationRequestsFragment.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settings.location;
-
-import androidx.annotation.XmlRes;
-
-import com.android.car.settings.R;
-import com.android.car.settings.common.SettingsFragment;
-
-/**
- * Shows a list of applications that have requested location recently.
- */
-public class RecentLocationRequestsFragment extends SettingsFragment {
-
- @Override
- @XmlRes
- protected int getPreferenceScreenResId() {
- return R.xml.location_recent_requests_fragment;
- }
-}
diff --git a/src/com/android/car/settings/location/RecentLocationRequestsPreferenceController.java b/src/com/android/car/settings/location/RecentLocationRequestsPreferenceController.java
deleted file mode 100644
index 69036efc0..000000000
--- a/src/com/android/car/settings/location/RecentLocationRequestsPreferenceController.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settings.location;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-
-import com.android.car.settings.R;
-import com.android.car.settings.applications.ApplicationDetailsFragment;
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.PreferenceController;
-import com.android.car.ui.preference.CarUiPreference;
-import com.android.settingslib.location.RecentLocationApps;
-import com.android.settingslib.location.RecentLocationApps.Request;
-
-import java.util.List;
-
-/**
- * Displays all apps that have requested location recently.
- */
-public class RecentLocationRequestsPreferenceController extends
- PreferenceController<PreferenceGroup> {
- private final PackageManager mPackageManager;
- private RecentLocationApps mRecentLocationApps;
- // This list will always be sorted by most recent first.
- private List<Request> mRecentLocationRequests;
-
- public RecentLocationRequestsPreferenceController(Context context, String preferenceKey,
- FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
- super(context, preferenceKey, fragmentController, uxRestrictions);
- mRecentLocationApps = new RecentLocationApps(context);
- mPackageManager = context.getPackageManager();
- }
-
- @VisibleForTesting
- void setRecentLocationApps(RecentLocationApps apps) {
- mRecentLocationApps = apps;
- }
-
- @Override
- protected Class<PreferenceGroup> getPreferenceType() {
- return PreferenceGroup.class;
- }
-
- @Override
- protected void updateState(PreferenceGroup group) {
- if (mRecentLocationRequests == null) {
- // First time displaying a list.
- mRecentLocationRequests =
- mRecentLocationApps.getAppListSorted(/* showSystemApps= */ true);
- } else {
- // If preferences were already added to the screen, get a new list
- // and only update the displayed app-list if there is a difference.
- List<Request> newRequests = mRecentLocationApps.getAppListSorted(true);
- // listsEqual compares by elements' package names only, using List.equals() will
- // not work because it will always return false since it also compares the time.
- if (listsEqual(newRequests, mRecentLocationRequests)) {
- return;
- }
- mRecentLocationRequests = newRequests;
- }
- if (mRecentLocationRequests.isEmpty()) {
- CarUiPreference emptyMessagePref = new CarUiPreference(getContext());
- emptyMessagePref.setTitle(R.string.location_settings_recent_requests_empty_message);
- group.addPreference(emptyMessagePref);
- } else {
- group.removeAll();
- for (Request request : mRecentLocationRequests) {
- Preference appPref = createPreference(request);
- group.addPreference(appPref);
- }
- }
- }
-
- private Preference createPreference(Request request) {
- CarUiPreference pref = new CarUiPreference(getContext());
- pref.setSummary(request.contentDescription);
- pref.setIcon(request.icon);
- pref.setTitle(request.label);
- if (isPackageInstalled(request.packageName)) {
- pref.setOnPreferenceClickListener(p -> {
- getFragmentController().launchFragment(
- ApplicationDetailsFragment.getInstance(
- request.packageName));
- return true;
- });
- }
- return pref;
- }
-
- private boolean isPackageInstalled(String packageName) {
- try {
- mPackageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- return true;
- }
-
- /**
- * Compares two {@link Request} lists by the elements' package names.
- *
- * @param a The first list.
- * @param b The second list.
- * @return {@code true} if both lists have the same elements (by package name) and order.
- */
- private boolean listsEqual(List<Request> a, List<Request> b) {
- if (a.size() != b.size()) {
- return false;
- }
- for (int i = 0; i < a.size(); i++) {
- if (!a.get(i).packageName.equals(b.get(i).packageName)) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/src/com/android/car/settings/wifi/WifiRequestToggleActivity.java b/src/com/android/car/settings/wifi/WifiRequestToggleActivity.java
index 7a9a7c8d7..20b65a55c 100644
--- a/src/com/android/car/settings/wifi/WifiRequestToggleActivity.java
+++ b/src/com/android/car/settings/wifi/WifiRequestToggleActivity.java
@@ -107,10 +107,10 @@ public class WifiRequestToggleActivity extends FragmentActivity {
try {
PackageManager pm = getPackageManager();
- ApplicationInfo ai = pm.getApplicationInfo(getCallingPackage(), /* flags= */ 0);
+ ApplicationInfo ai = pm.getApplicationInfo(getLaunchedFromPackage(), /* flags= */ 0);
mAppLabel = pm.getApplicationLabel(ai);
} catch (PackageManager.NameNotFoundException e) {
- LOG.e("Couldn't find app with package name " + getCallingPackage());
+ LOG.e("Couldn't find app with package name " + getLaunchedFromPackage());
finish();
return;
}
diff --git a/tests/unit/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceControllerTest.java
new file mode 100644
index 000000000..ee519b8de
--- /dev/null
+++ b/tests/unit/src/com/android/car/settings/location/LocationRecentAccessViewAllPreferenceControllerTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.LogicalPreferenceGroup;
+import com.android.car.settings.common.PreferenceControllerTestUtil;
+import com.android.car.settings.testutils.TestLifecycleOwner;
+import com.android.settingslib.applications.RecentAppOpsAccess;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.time.Clock;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class LocationRecentAccessViewAllPreferenceControllerTest {
+
+ private final Context mContext = Mockito.spy(ApplicationProvider.getApplicationContext());
+ private LifecycleOwner mLifecycleOwner;
+ private LogicalPreferenceGroup mPreference;
+ private LocationRecentAccessViewAllPreferenceController mPreferenceController;
+
+ @Mock private FragmentController mFragmentController;
+ @Mock private RecentAppOpsAccess mRecentLocationAccesses;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mLifecycleOwner = new TestLifecycleOwner();
+ CarUxRestrictions carUxRestrictions =
+ new CarUxRestrictions.Builder(
+ /* reqOpt= */ true,
+ CarUxRestrictions.UX_RESTRICTIONS_BASELINE,
+ /* timestamp= */ 0)
+ .build();
+
+ PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+ mPreference = new LogicalPreferenceGroup(mContext);
+ screen.addPreference(mPreference);
+ mPreferenceController =
+ new LocationRecentAccessViewAllPreferenceController(
+ mContext,
+ "key",
+ mFragmentController,
+ carUxRestrictions,
+ mRecentLocationAccesses);
+ PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
+ doNothing().when(mContext).startActivity(any());
+ }
+
+ @Test
+ public void updateState_noSystemAppsByDefault() {
+ initializePreference();
+ verify(mRecentLocationAccesses, never()).getAppListSorted(/* showSystem= */ true);
+ }
+
+ @Test
+ public void setShowSystem_showsSystemApps() {
+ initializePreference();
+ mPreferenceController.setShowSystem(true);
+ verify(mRecentLocationAccesses).getAppListSorted(/* showSystem= */ true);
+ }
+
+ @Test
+ public void refreshUi_noRecentAccesses_showsEmptyState() {
+ initializePreference();
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false))
+ .thenReturn(Collections.emptyList());
+ mPreferenceController.refreshUi();
+
+ assertThat(mPreference.getPreference(0).getTitle())
+ .isEqualTo(mContext.getString(R.string.location_no_recent_access));
+ }
+
+ @Test
+ public void refreshUi_someRecentAccesses_displaysAppInformation() {
+ initializePreference();
+
+ String fakeLabel = "Test app 1";
+ RecentAppOpsAccess.Access fakeAccess =
+ new RecentAppOpsAccess.Access(
+ "com.test",
+ UserHandle.CURRENT,
+ mock(Drawable.class),
+ fakeLabel,
+ "fake contentDescription",
+ Clock.systemDefaultZone().millis());
+ List<RecentAppOpsAccess.Access> list = Collections.singletonList(fakeAccess);
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list);
+ mPreferenceController.refreshUi();
+
+ assertThat(mPreference.getPreference(0).getTitle()).isEqualTo(fakeLabel);
+ assertThat(mPreference.getPreference(0).getSummary().toString()).contains("min. ago");
+ }
+
+ @Test
+ public void refreshUi_recentAccesses_launchLocationSettings() {
+ initializePreference();
+
+ List<RecentAppOpsAccess.Access> list =
+ Collections.singletonList(mock(RecentAppOpsAccess.Access.class));
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list);
+ mPreferenceController.refreshUi();
+
+ mPreference.getPreference(0).performClick();
+
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(captor.capture());
+
+ Intent intent = captor.getValue();
+ assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSION);
+ assertThat(intent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME))
+ .isEqualTo(Manifest.permission_group.LOCATION);
+ }
+
+ @Test
+ public void refreshUi_newRecentAccesses_listIsUpdated() {
+ initializePreference();
+
+ List<RecentAppOpsAccess.Access> list1 =
+ Collections.singletonList(mock(RecentAppOpsAccess.Access.class));
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list1);
+
+ List<RecentAppOpsAccess.Access> list2 = new ArrayList<>(list1);
+ list2.add(mock(RecentAppOpsAccess.Access.class));
+
+ mPreferenceController.refreshUi();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(list1.size());
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list2);
+ mPreferenceController.refreshUi();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(list2.size());
+ }
+
+ private void initializePreference() {
+ mPreferenceController.onCreate(mLifecycleOwner);
+ mPreferenceController.onStart(mLifecycleOwner);
+ }
+}
diff --git a/tests/unit/src/com/android/car/settings/location/LocationRecentAccessesPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/location/LocationRecentAccessesPreferenceControllerTest.java
new file mode 100644
index 000000000..d07b8975e
--- /dev/null
+++ b/tests/unit/src/com/android/car/settings/location/LocationRecentAccessesPreferenceControllerTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2022 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.car.settings.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Drawable;
+import android.location.LocationManager;
+import android.os.UserHandle;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceControllerTestUtil;
+import com.android.car.settings.testutils.TestLifecycleOwner;
+import com.android.settingslib.applications.RecentAppOpsAccess;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.time.Clock;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class LocationRecentAccessesPreferenceControllerTest {
+ private static final int RECENT_APPS_MAX_COUNT = 2;
+
+ private final Context mContext = Mockito.spy(ApplicationProvider.getApplicationContext());
+ private LifecycleOwner mLifecycleOwner;
+ private PreferenceCategory mPreference;
+ private LocationRecentAccessesPreferenceController mPreferenceController;
+
+ @Mock private FragmentController mFragmentController;
+ @Mock private RecentAppOpsAccess mRecentLocationAccesses;
+ @Mock private LocationManager mMockLocationManager;
+ @Captor private ArgumentCaptor<BroadcastReceiver> mAdasReceiver;
+ @Captor private ArgumentCaptor<BroadcastReceiver> mLocationReceiver;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mLifecycleOwner = new TestLifecycleOwner();
+ CarUxRestrictions carUxRestrictions =
+ new CarUxRestrictions.Builder(
+ /* reqOpt= */ true,
+ CarUxRestrictions.UX_RESTRICTIONS_BASELINE,
+ /* timestamp= */ 0)
+ .build();
+
+ PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+ mPreference = new PreferenceCategory(mContext);
+ screen.addPreference(mPreference);
+ mPreferenceController =
+ new LocationRecentAccessesPreferenceController(
+ mContext,
+ "key",
+ mFragmentController,
+ carUxRestrictions,
+ mRecentLocationAccesses,
+ RECENT_APPS_MAX_COUNT,
+ mMockLocationManager);
+ PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
+ doNothing().when(mContext).startActivity(any());
+ mPreferenceController.onCreate(mLifecycleOwner);
+ }
+
+ @Test
+ public void locationAndAdasOff_preferenceIsHidden() {
+ setIsLocationEnabled(false);
+ setIsAdasGnssLocationEnabled(false);
+
+ initializePreference();
+
+ assertThat(mPreference.isVisible()).isFalse();
+ }
+
+ @Test
+ public void locationAndAdasOn_preferenceIsShown() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ initializePreference();
+
+ assertThat(mPreference.isVisible()).isTrue();
+ }
+
+ @Test
+ public void adasOnOnly_preferenceIsShown() {
+ setIsLocationEnabled(false);
+ setIsAdasGnssLocationEnabled(true);
+
+ initializePreference();
+
+ assertThat(mPreference.isVisible()).isTrue();
+ }
+
+ @Test
+ public void refreshUi_noRecentRequests_messageDisplayed() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false))
+ .thenReturn(Collections.emptyList());
+ mPreferenceController.refreshUi();
+
+ assertThat(mPreference.getPreference(0).getTitle())
+ .isEqualTo(mContext.getString(R.string.location_no_recent_access));
+ }
+
+ @Test
+ public void refreshUi_noRecentRequests_exceptForSomeRecentSystemAppRequests_showsViewAll() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false))
+ .thenReturn(Collections.emptyList());
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ true))
+ .thenReturn(Collections.singletonList(mock(RecentAppOpsAccess.Access.class)));
+ mPreferenceController.refreshUi();
+
+ // includes preference for "View all"
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(2);
+ assertThat(mPreference.getPreference(1).getTitle())
+ .isEqualTo(
+ mContext.getString(
+ R.string.location_settings_recently_accessed_view_all_title));
+ }
+
+ @Test
+ @UiThreadTest
+ public void refreshUi_clickViewAll_launchesFragment() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ true))
+ .thenReturn(Collections.singletonList(mock(RecentAppOpsAccess.Access.class)));
+ mPreferenceController.refreshUi();
+
+ // click on the "View all" preference
+ mPreference.getPreference(1).performClick();
+ verify(mFragmentController).launchFragment(any(LocationRecentAccessViewAllFragment.class));
+ }
+
+ @Test
+ public void refreshUi_noRecentAccesses_includingNoSystemAppAccesses_doesNotShowViewAll() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false))
+ .thenReturn(Collections.emptyList());
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ true))
+ .thenReturn(Collections.emptyList());
+ mPreferenceController.refreshUi();
+
+ // no preference for "View all"
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreference.getPreference(0).getTitle())
+ .isEqualTo(mContext.getString(R.string.location_no_recent_access));
+ }
+
+ @Test
+ public void refreshUi_someRecentAccesses_displaysAppInformation() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ String fakeLabel = "Test app 1";
+ RecentAppOpsAccess.Access fakeAccess =
+ new RecentAppOpsAccess.Access(
+ "com.test",
+ UserHandle.CURRENT,
+ mock(Drawable.class),
+ fakeLabel,
+ "fake contentDescription",
+ Clock.systemDefaultZone().millis());
+ List<RecentAppOpsAccess.Access> list = Collections.singletonList(fakeAccess);
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list);
+ mPreferenceController.refreshUi();
+
+ assertThat(mPreference.getPreference(0).getTitle()).isEqualTo(fakeLabel);
+ assertThat(mPreference.getPreference(0).getSummary().toString()).contains("min. ago");
+ }
+
+ @Test
+ public void refreshUi_someRecentAcesses_preferencesAddedToScreen_capsAtMax() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ List<RecentAppOpsAccess.Access> list =
+ Arrays.asList(
+ mock(RecentAppOpsAccess.Access.class),
+ mock(RecentAppOpsAccess.Access.class),
+ mock(RecentAppOpsAccess.Access.class));
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list);
+ mPreferenceController.refreshUi();
+
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(RECENT_APPS_MAX_COUNT);
+ }
+
+ @Test
+ public void refreshUi_recentRequests_launchLocationSettings() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ List<RecentAppOpsAccess.Access> list =
+ Collections.singletonList(mock(RecentAppOpsAccess.Access.class));
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list);
+ mPreferenceController.refreshUi();
+
+ mPreference.getPreference(0).performClick();
+
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(captor.capture());
+
+ Intent intent = captor.getValue();
+ assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSION);
+ }
+
+ @Test
+ public void refreshUi_newRecentRequests_listIsUpdated() {
+ setIsLocationEnabled(true);
+ setIsAdasGnssLocationEnabled(true);
+
+ List<RecentAppOpsAccess.Access> list1 =
+ Collections.singletonList(mock(RecentAppOpsAccess.Access.class));
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list1);
+
+ List<RecentAppOpsAccess.Access> list2 = new ArrayList<>(list1);
+ list2.add(mock(RecentAppOpsAccess.Access.class));
+
+ mPreferenceController.refreshUi();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(list1.size());
+
+ when(mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false)).thenReturn(list2);
+ mPreferenceController.refreshUi();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(list2.size());
+ }
+
+ private void initializePreference() {
+ mPreferenceController.onCreate(mLifecycleOwner);
+ mPreferenceController.onStart(mLifecycleOwner);
+
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverArgumentCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mContext, times(2))
+ .registerReceiver(
+ broadcastReceiverArgumentCaptor.capture(), intentFilterCaptor.capture());
+ }
+
+ private void setIsLocationEnabled(boolean isEnabled) {
+ when(mMockLocationManager.isLocationEnabled()).thenReturn(isEnabled);
+ }
+
+ private void setIsAdasGnssLocationEnabled(boolean isEnabled) {
+ when(mMockLocationManager.isAdasGnssLocationEnabled()).thenReturn(isEnabled);
+ }
+}
diff --git a/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceControllerTest.java
deleted file mode 100644
index 3e41c87d1..000000000
--- a/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsEntryPreferenceControllerTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settings.location;
-
-import static com.android.car.settings.location.RecentLocationRequestsEntryPreferenceController.INTENT_FILTER_LOCATION_MODE_CHANGED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.location.LocationManager;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.Preference;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.PreferenceControllerTestUtil;
-import com.android.car.settings.testutils.TestLifecycleOwner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RecentLocationRequestsEntryPreferenceControllerTest {
- private static final long TIMEOUT_MS = 5000;
-
- private Context mContext = spy(ApplicationProvider.getApplicationContext());
- private LifecycleOwner mLifecycleOwner;
- private Preference mPreference;
- private RecentLocationRequestsEntryPreferenceController mPreferenceController;
- private CarUxRestrictions mCarUxRestrictions;
-
- @Mock
- private FragmentController mFragmentController;
- @Mock
- private LocationManager mLocationManager;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLifecycleOwner = new TestLifecycleOwner();
- mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
- CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
-
- when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager);
-
- mPreference = new Preference(mContext);
- mPreferenceController = new RecentLocationRequestsEntryPreferenceController(mContext,
- "key", mFragmentController, mCarUxRestrictions);
- PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
-
- mPreferenceController.onCreate(mLifecycleOwner);
- }
-
- @Test
- public void onStart_registersBroadcastReceiver() {
- mPreferenceController.onStart(mLifecycleOwner);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class),
- eq(INTENT_FILTER_LOCATION_MODE_CHANGED));
- }
-
- @Test
- public void onStop_unregistersBroadcastReceiver() {
- mPreferenceController.onStart(mLifecycleOwner);
- ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(
- BroadcastReceiver.class);
- verify(mContext).registerReceiver(captor.capture(),
- eq(INTENT_FILTER_LOCATION_MODE_CHANGED));
-
- mPreferenceController.onStop(mLifecycleOwner);
- verify(mContext).unregisterReceiver(captor.getValue());
- }
-
- @Test
- public void refreshUi_locationOn_preferenceIsEnabled() {
- when(mLocationManager.isLocationEnabled()).thenReturn(true);
- mPreferenceController.refreshUi();
-
- assertThat(mPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void refreshUi_locationOff_preferenceIsDisabled() {
- when(mLocationManager.isLocationEnabled()).thenReturn(false);
- mPreferenceController.refreshUi();
-
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void locationModeChangedBroadcastSent_locationOff_preferenceIsDisabled() {
- mPreferenceController.onStart(mLifecycleOwner);
- when(mLocationManager.isLocationEnabled()).thenReturn(true);
- mPreferenceController.refreshUi();
- when(mLocationManager.isLocationEnabled()).thenReturn(false);
- mPreferenceController.mReceiver.onReceive(mContext, new Intent());
-
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void locationModeChangedBroadcastSent_locationOn_preferenceIsEnabled() {
- mPreferenceController.onStart(mLifecycleOwner);
- when(mLocationManager.isLocationEnabled()).thenReturn(false);
- mPreferenceController.refreshUi();
- when(mLocationManager.isLocationEnabled()).thenReturn(true);
- mPreferenceController.mReceiver.onReceive(mContext, new Intent());
-
- assertThat(mPreference.isEnabled()).isTrue();
- }
-}
diff --git a/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsPreferenceControllerTest.java
deleted file mode 100644
index e3e686693..000000000
--- a/tests/unit/src/com/android/car/settings/location/RecentLocationRequestsPreferenceControllerTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settings.location;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.settings.R;
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.LogicalPreferenceGroup;
-import com.android.car.settings.common.PreferenceControllerTestUtil;
-import com.android.car.settings.testutils.TestLifecycleOwner;
-import com.android.settingslib.location.RecentLocationApps;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public class RecentLocationRequestsPreferenceControllerTest {
- private Context mContext = ApplicationProvider.getApplicationContext();
- private LifecycleOwner mLifecycleOwner;
- private PreferenceGroup mPreferenceGroup;
- private RecentLocationRequestsPreferenceController mPreferenceController;
- private CarUxRestrictions mCarUxRestrictions;
-
- @Mock
- private FragmentController mFragmentController;
- @Mock
- private RecentLocationApps mRecentLocationApps;
-
- @Before
- @UiThreadTest
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLifecycleOwner = new TestLifecycleOwner();
- mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
- CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
-
- PreferenceManager preferenceManager = new PreferenceManager(mContext);
- PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
- mPreferenceGroup = new LogicalPreferenceGroup(mContext);
- screen.addPreference(mPreferenceGroup);
- mPreferenceController = new RecentLocationRequestsPreferenceController(mContext,
- "key", mFragmentController, mCarUxRestrictions);
- mPreferenceController.setRecentLocationApps(mRecentLocationApps);
- PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
- mPreferenceController.onCreate(mLifecycleOwner);
- }
-
- @Test
- public void refreshUi_noRecentRequests_messageDisplayed() {
- when(mRecentLocationApps.getAppListSorted(true)).thenReturn(Collections.emptyList());
- mPreferenceController.refreshUi();
-
- assertThat(mPreferenceGroup.getPreference(0).getTitle()).isEqualTo(
- mContext.getString(R.string.location_settings_recent_requests_empty_message));
- }
-
- @Test
- public void refreshUi_someRecentRequests_preferencesAddedToScreen() {
- List<RecentLocationApps.Request> list = Arrays.asList(
- mock(RecentLocationApps.Request.class),
- mock(RecentLocationApps.Request.class),
- mock(RecentLocationApps.Request.class));
- when(mRecentLocationApps.getAppListSorted(true)).thenReturn(list);
- mPreferenceController.refreshUi();
-
- assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(list.size());
- }
-
- @Test
- public void refreshUi_newRecentRequests_listIsUpdated() {
- List<RecentLocationApps.Request> list1 = Arrays.asList(
- mock(RecentLocationApps.Request.class),
- mock(RecentLocationApps.Request.class),
- mock(RecentLocationApps.Request.class));
- when(mRecentLocationApps.getAppListSorted(true)).thenReturn(list1);
-
- List<RecentLocationApps.Request> list2 = new ArrayList<>(list1);
- list2.add(mock(RecentLocationApps.Request.class));
-
- mPreferenceController.refreshUi();
- assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(list1.size());
-
- when(mRecentLocationApps.getAppListSorted(true)).thenReturn(list2);
- mPreferenceController.refreshUi();
-
- assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(list2.size());
- }
-}
diff --git a/tests/unit/src/com/android/car/settings/privacy/MicrophoneRecentAccessViewAllPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/privacy/MicrophoneRecentAccessViewAllPreferenceControllerTest.java
index 7a543890b..99b6f280f 100644
--- a/tests/unit/src/com/android/car/settings/privacy/MicrophoneRecentAccessViewAllPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/car/settings/privacy/MicrophoneRecentAccessViewAllPreferenceControllerTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.Manifest;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.Intent;
@@ -149,6 +150,8 @@ public class MicrophoneRecentAccessViewAllPreferenceControllerTest {
Intent intent = captor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSION);
+ assertThat(intent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME))
+ .isEqualTo(Manifest.permission_group.MICROPHONE);
}
@Test