1 package com.android.settings.location; 2 3 import static android.Manifest.permission.ACCESS_COARSE_LOCATION; 4 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 5 6 import android.content.BroadcastReceiver; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.content.IntentFilter; 10 import android.location.LocationManager; 11 import android.os.UserHandle; 12 import android.os.UserManager; 13 import android.permission.PermissionControllerManager; 14 15 import androidx.annotation.VisibleForTesting; 16 import androidx.preference.Preference; 17 18 import com.android.settings.R; 19 import com.android.settings.Utils; 20 import com.android.settings.core.BasePreferenceController; 21 import com.android.settingslib.core.lifecycle.LifecycleObserver; 22 import com.android.settingslib.core.lifecycle.events.OnStart; 23 import com.android.settingslib.core.lifecycle.events.OnStop; 24 import com.android.settingslib.utils.StringUtil; 25 26 import java.util.Arrays; 27 import java.util.List; 28 import java.util.concurrent.atomic.AtomicInteger; 29 30 public class TopLevelLocationPreferenceController extends BasePreferenceController implements 31 LifecycleObserver, OnStart, OnStop { 32 private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = 33 new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 34 private final LocationManager mLocationManager; 35 private int mNumTotalLoading = 0; 36 /** Summary text. */ 37 private static String sSummary = null; 38 private BroadcastReceiver mReceiver; 39 private Preference mPreference; 40 private AtomicInteger loadingInProgress = new AtomicInteger(0); 41 TopLevelLocationPreferenceController(Context context, String preferenceKey)42 public TopLevelLocationPreferenceController(Context context, String preferenceKey) { 43 super(context, preferenceKey); 44 mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 45 } 46 47 @Override getAvailabilityStatus()48 public int getAvailabilityStatus() { 49 return AVAILABLE; 50 } 51 52 @Override getSummary()53 public CharSequence getSummary() { 54 if (mLocationManager.isLocationEnabled()) { 55 if (sSummary == null) { 56 sSummary = mContext.getString( 57 R.string.location_settings_loading_app_permission_stats); 58 } 59 return sSummary; 60 } else { 61 return mContext.getString(R.string.location_settings_summary_location_off); 62 } 63 } 64 65 @VisibleForTesting setLocationAppCount(int numApps)66 void setLocationAppCount(int numApps) { 67 sSummary = StringUtil.getIcuPluralsString(mContext, numApps, 68 R.string.location_settings_summary_location_on); 69 refreshSummary(mPreference); 70 } 71 72 @Override updateState(Preference preference)73 public void updateState(Preference preference) { 74 super.updateState(preference); 75 mPreference = preference; 76 refreshSummary(preference); 77 // Bail out if location has been disabled, or there's another loading request in progress. 78 if (!mLocationManager.isLocationEnabled() || 79 loadingInProgress.get() != 0) { 80 return; 81 } 82 mNumTotalLoading = 0; 83 // Retrieve a list of users inside the current user profile group. 84 final List<UserHandle> users = mContext.getSystemService( 85 UserManager.class).getUserProfiles(); 86 loadingInProgress.set(users.size()); 87 for (UserHandle user : users) { 88 final Context userContext = Utils.createPackageContextAsUser(mContext, 89 user.getIdentifier()); 90 if (userContext == null) { 91 if (loadingInProgress.decrementAndGet() == 0) { 92 setLocationAppCount(mNumTotalLoading); 93 } 94 continue; 95 } 96 final PermissionControllerManager permController = 97 userContext.getSystemService(PermissionControllerManager.class); 98 permController.countPermissionApps( 99 Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), 100 PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED, 101 (numApps) -> { 102 mNumTotalLoading += numApps; 103 if (loadingInProgress.decrementAndGet() == 0) { 104 setLocationAppCount(mNumTotalLoading); 105 } 106 }, null); 107 } 108 } 109 110 @Override onStart()111 public void onStart() { 112 if (mReceiver == null) { 113 mReceiver = new BroadcastReceiver() { 114 @Override 115 public void onReceive(Context context, Intent intent) { 116 refreshLocationMode(); 117 } 118 }; 119 } 120 mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); 121 refreshLocationMode(); 122 } 123 124 @Override onStop()125 public void onStop() { 126 mContext.unregisterReceiver(mReceiver); 127 } 128 refreshLocationMode()129 private void refreshLocationMode() { 130 if (mPreference != null) { 131 updateState(mPreference); 132 } 133 } 134 } 135