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; 3785e2f61b2d349125e4bd5d7677cfa09ba09983caMaggieimport static com.android.settingslib.Utils.updateLocationEnabled; 38754ca518422a2a633fc4d49436db7b15b4be0e84yuemingwimport static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced; 391949600132d05da7e3785412b7fd8fc336c8205bMaggie 4085e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie 419ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling/** 429ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * A class that listens to location settings change and modifies location settings 439ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * settings. 449ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling */ 459ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Lingpublic class LocationEnabler implements LifecycleObserver, OnResume, OnPause { 469ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 479ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private static final String TAG = "LocationEnabler"; 489ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @VisibleForTesting 499ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = 509ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling new IntentFilter(LocationManager.MODE_CHANGED_ACTION); 519ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 529ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final Context mContext; 539ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final UserManager mUserManager; 549ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private final LocationModeChangeListener mListener; 559ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 569ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @VisibleForTesting 579ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling BroadcastReceiver mReceiver; 589ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 599ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public interface LocationModeChangeListener { 609ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling /** Called when location mode has changed. */ 619ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void onLocationModeChanged(int mode, boolean restricted); 629ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 639ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 649ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public LocationEnabler(Context context, LocationModeChangeListener listener, 659ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Lifecycle lifecycle) { 669ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext = context; 679ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener = listener; 689ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 699ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (lifecycle != null) { 709ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling lifecycle.addObserver(this); 719ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 729ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 739ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 749ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 759ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onResume() { 769ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mReceiver == null) { 779ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mReceiver = new BroadcastReceiver() { 789ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 799ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onReceive(Context context, Intent intent) { 809ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.DEBUG)) { 819ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.d(TAG, "Received location mode change intent: " + intent); 829ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 839ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 849ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 859ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling }; 869ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 879ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); 889ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 899ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 909ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 919ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling @Override 929ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling public void onPause() { 939ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling try { 949ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext.unregisterReceiver(mReceiver); 959ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } catch (RuntimeException e) { 969ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // Ignore exceptions caused by race condition 979ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 989ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 999ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1009ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void refreshLocationMode() { 1019ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final int mode = Settings.Secure.getInt(mContext.getContentResolver(), 1029ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 1039ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.INFO)) { 1049ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.i(TAG, "Location mode has been changed"); 1059ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1069ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mListener != null) { 1079ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener.onLocationModeChanged(mode, isRestricted()); 1089ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1099ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1109ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 11185e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie void setLocationEnabled(boolean enabled) { 11285e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(), 11385e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 11485e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie 11585e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie if (isRestricted()) { 11685e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie // Location toggling disabled by user restriction. Read the current location mode to 11785e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie // update the location master switch. 11885e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie if (Log.isLoggable(TAG, Log.INFO)) { 11985e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie Log.i(TAG, "Restricted user, not setting location mode"); 12085e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie } 12185e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie if (mListener != null) { 12285e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie mListener.onLocationModeChanged(currentMode, true); 12385e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie } 12485e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie return; 12585e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie } 126e6032be8516fc0edfc5824093706349c6945e090Lifu Tang updateLocationEnabled(mContext, enabled, UserHandle.myUserId(), 127e6032be8516fc0edfc5824093706349c6945e090Lifu Tang Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS); 12885e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie refreshLocationMode(); 12985e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie } 13085e2f61b2d349125e4bd5d7677cfa09ba09983caMaggie 1319ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling void setLocationMode(int mode) { 1329ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(), 1339ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 1349ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (isRestricted()) { 1359ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // Location toggling disabled by user restriction. Read the current location mode to 1369ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling // update the location master switch. 1379ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (Log.isLoggable(TAG, Log.INFO)) { 1389ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling Log.i(TAG, "Restricted user, not setting location mode"); 1399ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1409ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling if (mListener != null) { 1419ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mListener.onLocationModeChanged(currentMode, true); 1429ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1439ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return; 1449ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1459ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 146e6032be8516fc0edfc5824093706349c6945e090Lifu Tang updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(), 147e6032be8516fc0edfc5824093706349c6945e090Lifu Tang Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS); 1489ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling refreshLocationMode(); 1499ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1509ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1519ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean isEnabled(int mode) { 1529ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return mode != Settings.Secure.LOCATION_MODE_OFF && !isRestricted(); 1539ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1549ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1559ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling /** 1569ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * Checking if device policy has put a location access lock-down on the managed profile. 1579ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * 1589ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling * @return true if device policy has put a location access lock-down on the managed profile 1599ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling */ 1609ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean isManagedProfileRestrictedByBase() { 1619ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling final UserHandle managedProfile = Utils.getManagedProfile(mUserManager); 1629ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return managedProfile != null 1639ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling && hasShareLocationRestriction(managedProfile.getIdentifier()); 1649ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1659ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1669ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) { 167754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw RestrictedLockUtils.EnforcedAdmin admin = checkIfRestrictionEnforced( 1689ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 169754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw 170754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw if (admin == null) { 171754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw admin = RestrictedLockUtils.checkIfRestrictionEnforced( 172a1416d2849e866e6a9a53c13af82608ca876454fyuemingw mContext, UserManager.DISALLOW_CONFIG_LOCATION, userId); 173754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw } 174754ca518422a2a633fc4d49436db7b15b4be0e84yuemingw return admin; 1759ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1769ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1779ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling boolean hasShareLocationRestriction(int userId) { 1789ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return RestrictedLockUtils.hasBaseUserRestriction( 1799ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling mContext, UserManager.DISALLOW_SHARE_LOCATION, userId); 1809ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1819ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling 1829ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling private boolean isRestricted() { 1839ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); 1849ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling } 1859ed29a2e57bb6e0ad1626afdfb0517ba643ccc9fDoris Ling} 186