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 static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced; 17 import static com.android.settingslib.Utils.updateLocationEnabled; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.location.LocationManager; 24 import android.os.UserHandle; 25 import android.os.UserManager; 26 import android.provider.Settings; 27 import android.util.Log; 28 29 import androidx.annotation.VisibleForTesting; 30 31 import com.android.settings.Utils; 32 import com.android.settingslib.RestrictedLockUtils; 33 import com.android.settingslib.RestrictedLockUtilsInternal; 34 import com.android.settingslib.core.lifecycle.Lifecycle; 35 import com.android.settingslib.core.lifecycle.LifecycleObserver; 36 import com.android.settingslib.core.lifecycle.events.OnStart; 37 import com.android.settingslib.core.lifecycle.events.OnStop; 38 39 40 /** 41 * A class that listens to location settings change and modifies location settings 42 * settings. 43 */ 44 public class LocationEnabler implements LifecycleObserver, OnStart, OnStop { 45 46 private static final String TAG = "LocationEnabler"; 47 @VisibleForTesting 48 static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = 49 new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 50 51 private final Context mContext; 52 private final UserManager mUserManager; 53 private final LocationModeChangeListener mListener; 54 55 @VisibleForTesting 56 BroadcastReceiver mReceiver; 57 58 public interface LocationModeChangeListener { 59 /** Called when location mode has changed. */ onLocationModeChanged(int mode, boolean restricted)60 void onLocationModeChanged(int mode, boolean restricted); 61 } 62 LocationEnabler(Context context, LocationModeChangeListener listener, Lifecycle lifecycle)63 public LocationEnabler(Context context, LocationModeChangeListener listener, 64 Lifecycle lifecycle) { 65 mContext = context; 66 mListener = listener; 67 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 68 if (lifecycle != null) { 69 lifecycle.addObserver(this); 70 } 71 } 72 73 @Override onStart()74 public void onStart() { 75 if (mReceiver == null) { 76 mReceiver = new BroadcastReceiver() { 77 @Override 78 public void onReceive(Context context, Intent intent) { 79 if (Log.isLoggable(TAG, Log.DEBUG)) { 80 Log.d(TAG, "Received location mode change intent: " + intent); 81 } 82 refreshLocationMode(); 83 } 84 }; 85 } 86 mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); 87 refreshLocationMode(); 88 } 89 90 @Override onStop()91 public void onStop() { 92 mContext.unregisterReceiver(mReceiver); 93 } 94 refreshLocationMode()95 void refreshLocationMode() { 96 final int mode = Settings.Secure.getInt(mContext.getContentResolver(), 97 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 98 if (Log.isLoggable(TAG, Log.INFO)) { 99 Log.i(TAG, "Location mode has been changed"); 100 } 101 if (mListener != null) { 102 mListener.onLocationModeChanged(mode, isRestricted()); 103 } 104 } 105 setLocationEnabled(boolean enabled)106 void setLocationEnabled(boolean enabled) { 107 final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(), 108 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 109 110 if (isRestricted()) { 111 // Location toggling disabled by user restriction. Read the current location mode to 112 // update the location master switch. 113 if (Log.isLoggable(TAG, Log.INFO)) { 114 Log.i(TAG, "Restricted user, not setting location mode"); 115 } 116 if (mListener != null) { 117 mListener.onLocationModeChanged(currentMode, true); 118 } 119 return; 120 } 121 updateLocationEnabled(mContext, enabled, UserHandle.myUserId(), 122 Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS); 123 refreshLocationMode(); 124 } 125 isEnabled(int mode)126 boolean isEnabled(int mode) { 127 return mode != Settings.Secure.LOCATION_MODE_OFF && !isRestricted(); 128 } 129 130 /** 131 * Checking if device policy has put a location access lock-down on the managed profile. 132 * 133 * @return true if device policy has put a location access lock-down on the managed profile 134 */ isManagedProfileRestrictedByBase()135 boolean isManagedProfileRestrictedByBase() { 136 final UserHandle managedProfile = Utils.getManagedProfile(mUserManager); 137 return managedProfile != null 138 && hasShareLocationRestriction(managedProfile.getIdentifier()); 139 } 140 getShareLocationEnforcedAdmin(int userId)141 RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) { 142 RestrictedLockUtils.EnforcedAdmin admin = checkIfRestrictionEnforced( 143 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 144 145 if (admin == null) { 146 admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( 147 mContext, UserManager.DISALLOW_CONFIG_LOCATION, userId); 148 } 149 return admin; 150 } 151 hasShareLocationRestriction(int userId)152 boolean hasShareLocationRestriction(int userId) { 153 return RestrictedLockUtilsInternal.hasBaseUserRestriction( 154 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 155 } 156 isRestricted()157 private boolean isRestricted() { 158 return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); 159 } 160 } 161