1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.settings.location; 18 19 import android.car.drivingstate.CarUxRestrictions; 20 import android.content.Context; 21 22 import androidx.preference.PreferenceCategory; 23 24 import com.android.car.settings.R; 25 import com.android.car.settings.common.FragmentController; 26 import com.android.car.ui.preference.CarUiPreference; 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.settingslib.applications.RecentAppOpsAccess; 29 30 import java.util.HashSet; 31 import java.util.List; 32 import java.util.Set; 33 34 /** 35 * This controller displays a list of apps that recently access the location. Driver assistance apps 36 * are also included. 37 */ 38 public class LocationRecentAccessesPreferenceController 39 extends LocationStateListenerBasePreferenceController<PreferenceCategory> { 40 41 private final Set<CarUiPreference> mAddedPreferences = new HashSet<>(); 42 43 private final RecentAppOpsAccess mRecentLocationAccesses; 44 private final int mRecentAppsMaxCount; 45 LocationRecentAccessesPreferenceController( Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)46 public LocationRecentAccessesPreferenceController( 47 Context context, 48 String preferenceKey, 49 FragmentController fragmentController, 50 CarUxRestrictions uxRestrictions) { 51 this( 52 context, 53 preferenceKey, 54 fragmentController, 55 uxRestrictions, 56 RecentAppOpsAccess.createForLocation(context), 57 context.getResources().getInteger( 58 R.integer.recent_location_access_apps_list_count)); 59 } 60 61 @VisibleForTesting LocationRecentAccessesPreferenceController( Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, RecentAppOpsAccess recentLocationAccesses, int recentAppsMaxCount)62 LocationRecentAccessesPreferenceController( 63 Context context, 64 String preferenceKey, 65 FragmentController fragmentController, 66 CarUxRestrictions uxRestrictions, 67 RecentAppOpsAccess recentLocationAccesses, 68 int recentAppsMaxCount) { 69 super(context, preferenceKey, fragmentController, uxRestrictions); 70 mRecentLocationAccesses = recentLocationAccesses; 71 mRecentAppsMaxCount = recentAppsMaxCount; 72 } 73 74 @Override getPreferenceType()75 protected Class<PreferenceCategory> getPreferenceType() { 76 return PreferenceCategory.class; 77 } 78 79 @Override onCreateInternal()80 protected void onCreateInternal() { 81 if (LocationUtil.isDriverWithAdasApps(getContext())) { 82 addDefaultBypassLocationStateListener(); 83 } 84 addDefaultMainLocationStateListener(); 85 } 86 87 @Override updateState(PreferenceCategory preference)88 protected void updateState(PreferenceCategory preference) { 89 boolean isVisible = getVisibility(); 90 preference.setVisible(isVisible); 91 if (isVisible) { 92 updateUi(loadData()); 93 } 94 } 95 getVisibility()96 private boolean getVisibility() { 97 boolean isVisible = getLocationManager().isLocationEnabled(); 98 if (LocationUtil.isDriverWithAdasApps(getContext())) { 99 isVisible = isVisible || getLocationManager().isAdasGnssLocationEnabled(); 100 } 101 return isVisible; 102 } 103 loadData()104 private List<RecentAppOpsAccess.Access> loadData() { 105 return mRecentLocationAccesses.getAppListSorted(/* showSystem= */ false); 106 } 107 hasAtLeastOneRecentAppAccess()108 private boolean hasAtLeastOneRecentAppAccess() { 109 return !mRecentLocationAccesses.getAppListSorted(/* showSystem= */ true).isEmpty(); 110 } 111 updateUi(List<RecentAppOpsAccess.Access> sortedRecentLocationAccesses)112 private void updateUi(List<RecentAppOpsAccess.Access> sortedRecentLocationAccesses) { 113 // remove any already added preferences 114 for (CarUiPreference addedPreference : mAddedPreferences) { 115 getPreference().removePreference(addedPreference); 116 } 117 mAddedPreferences.clear(); 118 119 if (sortedRecentLocationAccesses.isEmpty()) { 120 CarUiPreference emptyPreference = createNoRecentAccessPreference(); 121 getPreference().addPreference(emptyPreference); 122 mAddedPreferences.add(emptyPreference); 123 } else { 124 int count = Math.min(sortedRecentLocationAccesses.size(), mRecentAppsMaxCount); 125 for (int i = 0; i < count; i++) { 126 RecentAppOpsAccess.Access request = sortedRecentLocationAccesses.get(i); 127 CarUiPreference appPreference = 128 LocationRecentAccessUtil.createAppPreference(getContext(), request); 129 getPreference().addPreference(appPreference); 130 mAddedPreferences.add(appPreference); 131 } 132 } 133 134 if (hasAtLeastOneRecentAppAccess()) { 135 CarUiPreference viewAllPreference = createViewAllPreference(); 136 getPreference().addPreference(viewAllPreference); 137 mAddedPreferences.add(viewAllPreference); 138 } 139 } 140 createNoRecentAccessPreference()141 private CarUiPreference createNoRecentAccessPreference() { 142 CarUiPreference preference = new CarUiPreference(getContext()); 143 preference.setTitle(R.string.location_no_recent_access); 144 preference.setSelectable(false); 145 return preference; 146 } 147 createViewAllPreference()148 private CarUiPreference createViewAllPreference() { 149 CarUiPreference preference = new CarUiPreference(getContext()); 150 preference.setTitle(R.string.location_settings_recently_accessed_view_all_title); 151 preference.setIcon(R.drawable.ic_apps); 152 preference.setOnPreferenceClickListener( 153 p -> { 154 getFragmentController() 155 .launchFragment(new LocationRecentAccessViewAllFragment()); 156 return true; 157 }); 158 return preference; 159 } 160 } 161