| package com.android.settings.location; |
| |
| import static android.Manifest.permission.ACCESS_COARSE_LOCATION; |
| import static android.Manifest.permission.ACCESS_FINE_LOCATION; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.location.LocationManager; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.permission.PermissionControllerManager; |
| |
| import androidx.annotation.VisibleForTesting; |
| import androidx.preference.Preference; |
| |
| import com.android.settings.R; |
| import com.android.settings.Utils; |
| import com.android.settings.core.BasePreferenceController; |
| import com.android.settingslib.core.lifecycle.LifecycleObserver; |
| import com.android.settingslib.core.lifecycle.events.OnStart; |
| import com.android.settingslib.core.lifecycle.events.OnStop; |
| import com.android.settingslib.utils.StringUtil; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| public class TopLevelLocationPreferenceController extends BasePreferenceController implements |
| LifecycleObserver, OnStart, OnStop { |
| private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = |
| new IntentFilter(LocationManager.MODE_CHANGED_ACTION); |
| private final LocationManager mLocationManager; |
| private int mNumTotalLoading = 0; |
| /** Summary text. */ |
| private static String sSummary = null; |
| private BroadcastReceiver mReceiver; |
| private Preference mPreference; |
| private AtomicInteger loadingInProgress = new AtomicInteger(0); |
| |
| public TopLevelLocationPreferenceController(Context context, String preferenceKey) { |
| super(context, preferenceKey); |
| mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); |
| } |
| |
| @Override |
| public int getAvailabilityStatus() { |
| return AVAILABLE; |
| } |
| |
| @Override |
| public CharSequence getSummary() { |
| if (mLocationManager.isLocationEnabled()) { |
| if (sSummary == null) { |
| sSummary = mContext.getString( |
| R.string.location_settings_loading_app_permission_stats); |
| } |
| return sSummary; |
| } else { |
| return mContext.getString(R.string.location_settings_summary_location_off); |
| } |
| } |
| |
| @VisibleForTesting |
| void setLocationAppCount(int numApps) { |
| sSummary = StringUtil.getIcuPluralsString(mContext, numApps, |
| R.string.location_settings_summary_location_on); |
| refreshSummary(mPreference); |
| } |
| |
| @Override |
| public void updateState(Preference preference) { |
| super.updateState(preference); |
| mPreference = preference; |
| refreshSummary(preference); |
| // Bail out if location has been disabled, or there's another loading request in progress. |
| if (!mLocationManager.isLocationEnabled() || |
| loadingInProgress.get() != 0) { |
| return; |
| } |
| mNumTotalLoading = 0; |
| // Retrieve a list of users inside the current user profile group. |
| final List<UserHandle> users = mContext.getSystemService( |
| UserManager.class).getUserProfiles(); |
| loadingInProgress.set(users.size()); |
| for (UserHandle user : users) { |
| final Context userContext = Utils.createPackageContextAsUser(mContext, |
| user.getIdentifier()); |
| if (userContext == null) { |
| if (loadingInProgress.decrementAndGet() == 0) { |
| setLocationAppCount(mNumTotalLoading); |
| } |
| continue; |
| } |
| final PermissionControllerManager permController = |
| userContext.getSystemService(PermissionControllerManager.class); |
| permController.countPermissionApps( |
| Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), |
| PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED, |
| (numApps) -> { |
| mNumTotalLoading += numApps; |
| if (loadingInProgress.decrementAndGet() == 0) { |
| setLocationAppCount(mNumTotalLoading); |
| } |
| }, null); |
| } |
| } |
| |
| @Override |
| public void onStart() { |
| if (mReceiver == null) { |
| mReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| refreshLocationMode(); |
| } |
| }; |
| } |
| mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); |
| refreshLocationMode(); |
| } |
| |
| @Override |
| public void onStop() { |
| mContext.unregisterReceiver(mReceiver); |
| } |
| |
| private void refreshLocationMode() { |
| if (mPreference != null) { |
| updateState(mPreference); |
| } |
| } |
| } |