LocationEnabler.java revision 1949600132d05da7e3785412b7fd8fc336c8205b
19ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling/* 29ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * Copyright (C) 2017 The Android Open Source Project 39ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * 49ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 59ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * except in compliance with the License. You may obtain a copy of the License at 69ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * 79ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * http://www.apache.org/licenses/LICENSE-2.0 89ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * 99ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * Unless required by applicable law or agreed to in writing, software distributed under the 109ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 119ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * KIND, either express or implied. See the License for the specific language governing 129ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * permissions and limitations under the License. 139ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling */ 149ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingpackage com.android.settings.location; 159ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 161949600132d05da7e3785412b7fd8fc336c8205bMaggieimport android.app.ActivityManager; 179ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.Manifest.permission; 189ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.content.BroadcastReceiver; 199ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.content.Context; 209ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.content.Intent; 219ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.content.IntentFilter; 229ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.location.LocationManager; 239ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.os.UserHandle; 249ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.os.UserManager; 259ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.provider.Settings; 269ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.support.annotation.VisibleForTesting; 279ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport android.util.Log; 289ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 299ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settings.Utils; 309ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settingslib.RestrictedLockUtils; 319ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settingslib.core.lifecycle.Lifecycle; 329ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settingslib.core.lifecycle.LifecycleObserver; 339ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settingslib.core.lifecycle.events.OnPause; 349ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingimport com.android.settingslib.core.lifecycle.events.OnResume; 359ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 361949600132d05da7e3785412b7fd8fc336c8205bMaggieimport static com.android.settingslib.Utils.updateLocationMode; 371949600132d05da7e3785412b7fd8fc336c8205bMaggie 389ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling/** 399ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * A class that listens to location settings change and modifies location settings 409ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * settings. 419ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling */ 429ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingpublic class LocationEnabler implements LifecycleObserver, OnResume, OnPause { 439ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 449ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private static final String TAG = "LocationEnabler"; 459ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @VisibleForTesting 469ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = 479ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 489ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 499ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final Context mContext; 509ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final UserManager mUserManager; 519ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final LocationModeChangeListener mListener; 529ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 539ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @VisibleForTesting 549ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling BroadcastReceiver mReceiver; 559ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 569ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public interface LocationModeChangeListener { 579ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling /** Called when location mode has changed. */ 589ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void onLocationModeChanged(int mode, boolean restricted); 599ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 609ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 619ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public LocationEnabler(Context context, LocationModeChangeListener listener, 629ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Lifecycle lifecycle) { 639ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext = context; 649ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener = listener; 659ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 669ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (lifecycle != null) { 679ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling lifecycle.addObserver(this); 689ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 699ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 709ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 719ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 729ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onResume() { 739ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mReceiver == null) { 749ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mReceiver = new BroadcastReceiver() { 759ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 769ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onReceive(Context context, Intent intent) { 779ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.DEBUG)) { 789ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.d(TAG, "Received location mode change intent: " + intent); 799ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 809ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 819ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 829ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling }; 839ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 849ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); 859ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 869ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 879ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 889ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 899ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onPause() { 909ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling try { 919ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext.unregisterReceiver(mReceiver); 929ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } catch (RuntimeException e) { 939ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // Ignore exceptions caused by race condition 949ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 959ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 969ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 979ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void refreshLocationMode() { 989ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final int mode = Settings.Secure.getInt(mContext.getContentResolver(), 999ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 1009ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.INFO)) { 1019ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.i(TAG, "Location mode has been changed"); 1029ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1039ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mListener != null) { 1049ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener.onLocationModeChanged(mode, isRestricted()); 1059ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1069ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1079ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1089ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void setLocationMode(int mode) { 1099ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(), 1109ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 1119ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (isRestricted()) { 1129ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // Location toggling disabled by user restriction. Read the current location mode to 1139ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // update the location master switch. 1149ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.INFO)) { 1159ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.i(TAG, "Restricted user, not setting location mode"); 1169ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1179ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mListener != null) { 1189ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener.onLocationModeChanged(currentMode, true); 1199ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1209ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return; 1219ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1229ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1231949600132d05da7e3785412b7fd8fc336c8205bMaggie updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser()); 1249ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 1259ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1269ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1279ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean isEnabled(int mode) { 1289ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return mode != Settings.Secure.LOCATION_MODE_OFF && !isRestricted(); 1299ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1309ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1319ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling /** 1329ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * Checking if device policy has put a location access lock-down on the managed profile. 1339ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * 1349ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * @return true if device policy has put a location access lock-down on the managed profile 1359ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling */ 1369ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean isManagedProfileRestrictedByBase() { 1379ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final UserHandle managedProfile = Utils.getManagedProfile(mUserManager); 1389ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return managedProfile != null 1399ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling && hasShareLocationRestriction(managedProfile.getIdentifier()); 1409ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1419ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1429ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) { 1439ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return RestrictedLockUtils.checkIfRestrictionEnforced( 1449ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 1459ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1469ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1479ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean hasShareLocationRestriction(int userId) { 1489ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return RestrictedLockUtils.hasBaseUserRestriction( 1499ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 1509ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1519ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1529ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private boolean isRestricted() { 1539ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); 1549ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1559ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling} 156