1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 package com.android.settings.location; 15 16 import android.content.Context; 17 import android.os.Bundle; 18 import android.os.UserHandle; 19 import android.os.UserManager; 20 import android.provider.DeviceConfig; 21 import android.provider.Settings; 22 23 import androidx.annotation.VisibleForTesting; 24 import androidx.preference.Preference; 25 import androidx.preference.PreferenceCategory; 26 import androidx.preference.PreferenceScreen; 27 28 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 29 import com.android.settings.R; 30 import com.android.settings.applications.appinfo.AppInfoDashboardFragment; 31 import com.android.settings.core.SubSettingLauncher; 32 import com.android.settings.dashboard.DashboardFragment; 33 import com.android.settings.dashboard.profileselector.ProfileSelectFragment; 34 import com.android.settingslib.location.RecentLocationApps; 35 import com.android.settingslib.widget.AppPreference; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 40 public class RecentLocationRequestPreferenceController extends LocationBasePreferenceController { 41 42 public static final int MAX_APPS = 3; 43 @VisibleForTesting 44 RecentLocationApps mRecentLocationApps; 45 private PreferenceCategory mCategoryRecentLocationRequests; 46 private int mType = ProfileSelectFragment.ProfileType.ALL; 47 48 /** Used in this class and {@link RecentLocationRequestSeeAllPreferenceController} */ 49 static class PackageEntryClickedListener implements Preference.OnPreferenceClickListener { 50 private final DashboardFragment mFragment; 51 private final String mPackage; 52 private final UserHandle mUserHandle; 53 PackageEntryClickedListener(DashboardFragment fragment, String packageName, UserHandle userHandle)54 public PackageEntryClickedListener(DashboardFragment fragment, String packageName, 55 UserHandle userHandle) { 56 mFragment = fragment; 57 mPackage = packageName; 58 mUserHandle = userHandle; 59 } 60 61 @Override onPreferenceClick(Preference preference)62 public boolean onPreferenceClick(Preference preference) { 63 // start new fragment to display extended information 64 final Bundle args = new Bundle(); 65 args.putString(AppInfoDashboardFragment.ARG_PACKAGE_NAME, mPackage); 66 new SubSettingLauncher(mFragment.getContext()) 67 .setDestination(AppInfoDashboardFragment.class.getName()) 68 .setArguments(args) 69 .setTitleRes(R.string.application_info_label) 70 .setUserHandle(mUserHandle) 71 .setSourceMetricsCategory(mFragment.getMetricsCategory()) 72 .launch(); 73 return true; 74 } 75 } 76 RecentLocationRequestPreferenceController(Context context, String key)77 public RecentLocationRequestPreferenceController(Context context, String key) { 78 super(context, key); 79 mRecentLocationApps = new RecentLocationApps(context); 80 } 81 82 @Override displayPreference(PreferenceScreen screen)83 public void displayPreference(PreferenceScreen screen) { 84 super.displayPreference(screen); 85 mCategoryRecentLocationRequests = screen.findPreference(getPreferenceKey()); 86 final Context prefContext = mCategoryRecentLocationRequests.getContext(); 87 final List<RecentLocationApps.Request> recentLocationRequests = new ArrayList<>(); 88 final UserManager userManager = UserManager.get(mContext); 89 final boolean showSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, 90 SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false) 91 ? Settings.Secure.getInt(mContext.getContentResolver(), 92 Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1 93 : false; 94 95 for (RecentLocationApps.Request request : mRecentLocationApps.getAppListSorted( 96 showSystem)) { 97 if (isRequestMatchesProfileType(userManager, request, mType)) { 98 recentLocationRequests.add(request); 99 if (recentLocationRequests.size() == MAX_APPS) { 100 break; 101 } 102 } 103 } 104 105 if (recentLocationRequests.size() > 0) { 106 // Add preferences to container in original order (already sorted by recency). 107 for (RecentLocationApps.Request request : recentLocationRequests) { 108 mCategoryRecentLocationRequests.addPreference( 109 createAppPreference(prefContext, request, mFragment)); 110 } 111 } else { 112 // If there's no item to display, add a "No recent apps" item. 113 final Preference banner = new AppPreference(prefContext); 114 banner.setTitle(R.string.location_no_recent_apps); 115 banner.setSelectable(false); 116 mCategoryRecentLocationRequests.addPreference(banner); 117 } 118 } 119 120 @Override onLocationModeChanged(int mode, boolean restricted)121 public void onLocationModeChanged(int mode, boolean restricted) { 122 mCategoryRecentLocationRequests.setEnabled(mLocationEnabler.isEnabled(mode)); 123 } 124 125 /** 126 * Initialize {@link ProfileSelectFragment.ProfileType} of the controller 127 * 128 * @param type {@link ProfileSelectFragment.ProfileType} of the controller. 129 */ setProfileType(@rofileSelectFragment.ProfileType int type)130 public void setProfileType(@ProfileSelectFragment.ProfileType int type) { 131 mType = type; 132 } 133 134 /** 135 * Create a {@link AppPreference} 136 */ createAppPreference(Context prefContext, RecentLocationApps.Request request, DashboardFragment fragment)137 public static AppPreference createAppPreference(Context prefContext, 138 RecentLocationApps.Request request, DashboardFragment fragment) { 139 final AppPreference pref = new AppPreference(prefContext); 140 pref.setIcon(request.icon); 141 pref.setTitle(request.label); 142 pref.setOnPreferenceClickListener(new PackageEntryClickedListener( 143 fragment, request.packageName, request.userHandle)); 144 return pref; 145 } 146 147 /** 148 * Return if the {@link RecentLocationApps.Request} matches current UI 149 * {@ProfileSelectFragment.ProfileType} 150 */ isRequestMatchesProfileType(UserManager userManager, RecentLocationApps.Request request, @ProfileSelectFragment.ProfileType int type)151 public static boolean isRequestMatchesProfileType(UserManager userManager, 152 RecentLocationApps.Request request, @ProfileSelectFragment.ProfileType int type) { 153 final boolean isWorkProfile = userManager.isManagedProfile( 154 request.userHandle.getIdentifier()); 155 if (isWorkProfile && (type & ProfileSelectFragment.ProfileType.WORK) != 0) { 156 return true; 157 } 158 if (!isWorkProfile && (type & ProfileSelectFragment.ProfileType.PERSONAL) != 0) { 159 return true; 160 } 161 return false; 162 } 163 } 164