1 /* 2 * Copyright (C) 2018 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 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 25 import androidx.annotation.VisibleForTesting; 26 import androidx.preference.Preference; 27 import androidx.preference.PreferenceGroup; 28 29 import com.android.car.settings.R; 30 import com.android.car.settings.applications.ApplicationDetailsFragment; 31 import com.android.car.settings.common.FragmentController; 32 import com.android.car.settings.common.PreferenceController; 33 import com.android.car.ui.preference.CarUiPreference; 34 import com.android.settingslib.location.RecentLocationApps; 35 import com.android.settingslib.location.RecentLocationApps.Request; 36 37 import java.util.List; 38 39 /** 40 * Displays all apps that have requested location recently. 41 */ 42 public class RecentLocationRequestsPreferenceController extends 43 PreferenceController<PreferenceGroup> { 44 private RecentLocationApps mRecentLocationApps; 45 // This list will always be sorted by most recent first. 46 private List<Request> mRecentLocationRequests; 47 RecentLocationRequestsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)48 public RecentLocationRequestsPreferenceController(Context context, String preferenceKey, 49 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 50 super(context, preferenceKey, fragmentController, uxRestrictions); 51 mRecentLocationApps = new RecentLocationApps(context); 52 } 53 54 @VisibleForTesting setRecentLocationApps(RecentLocationApps apps)55 void setRecentLocationApps(RecentLocationApps apps) { 56 mRecentLocationApps = apps; 57 } 58 59 @Override getPreferenceType()60 protected Class<PreferenceGroup> getPreferenceType() { 61 return PreferenceGroup.class; 62 } 63 64 @Override updateState(PreferenceGroup group)65 protected void updateState(PreferenceGroup group) { 66 if (mRecentLocationRequests == null) { 67 // First time displaying a list. 68 mRecentLocationRequests = 69 mRecentLocationApps.getAppListSorted(/* showSystemApps= */ true); 70 } else { 71 // If preferences were already added to the screen, get a new list 72 // and only update the displayed app-list if there is a difference. 73 List<Request> newRequests = mRecentLocationApps.getAppListSorted(true); 74 // listsEqual compares by elements' package names only, using List.equals() will 75 // not work because it will always return false since it also compares the time. 76 if (listsEqual(newRequests, mRecentLocationRequests)) { 77 return; 78 } 79 mRecentLocationRequests = newRequests; 80 } 81 if (mRecentLocationRequests.isEmpty()) { 82 CarUiPreference emptyMessagePref = new CarUiPreference(getContext()); 83 emptyMessagePref.setTitle(R.string.location_settings_recent_requests_empty_message); 84 group.addPreference(emptyMessagePref); 85 } else { 86 group.removeAll(); 87 for (Request request : mRecentLocationRequests) { 88 Preference appPref = createPreference(request); 89 group.addPreference(appPref); 90 } 91 } 92 } 93 createPreference(Request request)94 private Preference createPreference(Request request) { 95 CarUiPreference pref = new CarUiPreference(getContext()); 96 pref.setSummary(request.contentDescription); 97 pref.setIcon(request.icon); 98 pref.setTitle(request.label); 99 Intent intent = new Intent(); 100 intent.setPackage(request.packageName); 101 ResolveInfo resolveInfo = getContext().getPackageManager().resolveActivity(intent, 102 PackageManager.MATCH_DEFAULT_ONLY); 103 pref.setOnPreferenceClickListener(p -> { 104 getFragmentController().launchFragment( 105 ApplicationDetailsFragment.getInstance(resolveInfo.activityInfo.packageName)); 106 return true; 107 }); 108 return pref; 109 } 110 111 /** 112 * Compares two {@link Request} lists by the elements' package names. 113 * 114 * @param a The first list. 115 * @param b The second list. 116 * @return {@code true} if both lists have the same elements (by package name) and order. 117 */ listsEqual(List<Request> a, List<Request> b)118 private boolean listsEqual(List<Request> a, List<Request> b) { 119 if (a.size() != b.size()) { 120 return false; 121 } 122 for (int i = 0; i < a.size(); i++) { 123 if (!a.get(i).packageName.equals(b.get(i).packageName)) { 124 return false; 125 } 126 } 127 return true; 128 } 129 } 130