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.BroadcastReceiver; 17 import android.content.Context; 18 import android.content.Intent; 19 import android.content.IntentFilter; 20 import android.location.SettingInjectorService; 21 import android.os.UserHandle; 22 import android.util.Log; 23 24 import androidx.annotation.VisibleForTesting; 25 import androidx.preference.Preference; 26 import androidx.preference.PreferenceCategory; 27 import androidx.preference.PreferenceScreen; 28 29 import com.android.settings.Utils; 30 import com.android.settings.widget.RestrictedAppPreference; 31 import com.android.settingslib.core.lifecycle.Lifecycle; 32 import com.android.settingslib.core.lifecycle.LifecycleObserver; 33 import com.android.settingslib.core.lifecycle.events.OnPause; 34 import com.android.settingslib.core.lifecycle.events.OnResume; 35 36 import java.util.List; 37 import java.util.Map; 38 39 public class LocationServicePreferenceController extends LocationBasePreferenceController 40 implements LifecycleObserver, OnResume, OnPause { 41 42 private static final String TAG = "LocationServicePrefCtrl"; 43 /** Key for preference category "Location services" */ 44 private static final String KEY_LOCATION_SERVICES = "location_services"; 45 /** Key for preference category "Location services for work" */ 46 private static final String KEY_LOCATION_SERVICES_MANAGED = "location_services_managed_profile"; 47 @VisibleForTesting 48 static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED = 49 new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED); 50 51 private PreferenceCategory mCategoryLocationServices; 52 private PreferenceCategory mCategoryLocationServicesManaged; 53 private final LocationSettings mFragment; 54 private final AppSettingsInjector mInjector; 55 /** Receives UPDATE_INTENT */ 56 @VisibleForTesting 57 BroadcastReceiver mInjectedSettingsReceiver; 58 LocationServicePreferenceController(Context context, LocationSettings fragment, Lifecycle lifecycle)59 public LocationServicePreferenceController(Context context, LocationSettings fragment, 60 Lifecycle lifecycle) { 61 this(context, fragment, lifecycle, new AppSettingsInjector(context)); 62 } 63 64 @VisibleForTesting LocationServicePreferenceController(Context context, LocationSettings fragment, Lifecycle lifecycle, AppSettingsInjector injector)65 LocationServicePreferenceController(Context context, LocationSettings fragment, 66 Lifecycle lifecycle, AppSettingsInjector injector) { 67 super(context, lifecycle); 68 mFragment = fragment; 69 mInjector = injector; 70 if (lifecycle != null) { 71 lifecycle.addObserver(this); 72 } 73 } 74 75 @Override getPreferenceKey()76 public String getPreferenceKey() { 77 return KEY_LOCATION_SERVICES; 78 } 79 80 @Override displayPreference(PreferenceScreen screen)81 public void displayPreference(PreferenceScreen screen) { 82 super.displayPreference(screen); 83 mCategoryLocationServices = screen.findPreference(KEY_LOCATION_SERVICES); 84 mCategoryLocationServicesManaged = screen.findPreference(KEY_LOCATION_SERVICES_MANAGED); 85 } 86 87 @Override updateState(Preference preference)88 public void updateState(Preference preference) { 89 mCategoryLocationServices.removeAll(); 90 mCategoryLocationServicesManaged.removeAll(); 91 final Map<Integer, List<Preference>> prefs = getLocationServices(); 92 boolean showPrimary = false; 93 boolean showManaged = false; 94 for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) { 95 for (Preference pref : entry.getValue()) { 96 if (pref instanceof RestrictedAppPreference) { 97 ((RestrictedAppPreference) pref).checkRestrictionAndSetDisabled(); 98 } 99 } 100 if (entry.getKey() == UserHandle.myUserId()) { 101 LocationSettings.addPreferencesSorted(entry.getValue(), mCategoryLocationServices); 102 showPrimary = true; 103 } else { 104 LocationSettings.addPreferencesSorted(entry.getValue(), 105 mCategoryLocationServicesManaged); 106 showManaged = true; 107 } 108 } 109 mCategoryLocationServices.setVisible(showPrimary); 110 mCategoryLocationServicesManaged.setVisible(showManaged); 111 } 112 113 @Override onLocationModeChanged(int mode, boolean restricted)114 public void onLocationModeChanged(int mode, boolean restricted) { 115 // As a safety measure, also reloads on location mode change to ensure the settings are 116 // up-to-date even if an affected app doesn't send the setting changed broadcast. 117 mInjector.reloadStatusMessages(); 118 } 119 120 @Override onResume()121 public void onResume() { 122 if (mInjectedSettingsReceiver == null) { 123 mInjectedSettingsReceiver = new BroadcastReceiver() { 124 @Override 125 public void onReceive(Context context, Intent intent) { 126 if (Log.isLoggable(TAG, Log.DEBUG)) { 127 Log.d(TAG, "Received settings change intent: " + intent); 128 } 129 mInjector.reloadStatusMessages(); 130 } 131 }; 132 } 133 mContext.registerReceiver( 134 mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED); 135 } 136 137 @Override onPause()138 public void onPause() { 139 mContext.unregisterReceiver(mInjectedSettingsReceiver); 140 } 141 getLocationServices()142 private Map<Integer, List<Preference>> getLocationServices() { 143 // If location access is locked down by device policy then we only show injected settings 144 // for the primary profile. 145 final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId()); 146 147 return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(), 148 (profileUserId != UserHandle.USER_NULL 149 && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null) 150 ? UserHandle.myUserId() : UserHandle.USER_CURRENT); 151 } 152 } 153