blob: 20c228024ff7932cee918430d5c4c54801352f02 [file] [log] [blame]
Doris Ling9ed29a22017-11-02 16:42:45 -07001/*
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 */
14package com.android.settings.location;
15
Philip P. Moltmanne3f72112018-08-28 15:01:43 -070016import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced;
Fan Zhangc7162cd2018-06-18 15:21:41 -070017import static com.android.settingslib.Utils.updateLocationEnabled;
18import static com.android.settingslib.Utils.updateLocationMode;
19
Maggie19496002017-11-30 10:50:50 -080020import android.app.ActivityManager;
Doris Ling9ed29a22017-11-02 16:42:45 -070021import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.location.LocationManager;
26import android.os.UserHandle;
27import android.os.UserManager;
28import android.provider.Settings;
Doris Ling9ed29a22017-11-02 16:42:45 -070029import android.util.Log;
30
Fan Zhang23f8d592018-08-28 15:11:40 -070031import androidx.annotation.VisibleForTesting;
32
Doris Ling9ed29a22017-11-02 16:42:45 -070033import com.android.settings.Utils;
34import com.android.settingslib.RestrictedLockUtils;
Philip P. Moltmanne3f72112018-08-28 15:01:43 -070035import com.android.settingslib.RestrictedLockUtilsInternal;
Doris Ling9ed29a22017-11-02 16:42:45 -070036import com.android.settingslib.core.lifecycle.Lifecycle;
37import com.android.settingslib.core.lifecycle.LifecycleObserver;
38import com.android.settingslib.core.lifecycle.events.OnPause;
39import com.android.settingslib.core.lifecycle.events.OnResume;
40
Maggie85e2f612018-01-04 15:35:49 -080041
Doris Ling9ed29a22017-11-02 16:42:45 -070042/**
43 * A class that listens to location settings change and modifies location settings
44 * settings.
45 */
46public class LocationEnabler implements LifecycleObserver, OnResume, OnPause {
47
48 private static final String TAG = "LocationEnabler";
49 @VisibleForTesting
Doris Ling9ed29a22017-11-02 16:42:45 -070050 static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED =
51 new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
52
53 private final Context mContext;
54 private final UserManager mUserManager;
55 private final LocationModeChangeListener mListener;
56
57 @VisibleForTesting
58 BroadcastReceiver mReceiver;
59
60 public interface LocationModeChangeListener {
61 /** Called when location mode has changed. */
62 void onLocationModeChanged(int mode, boolean restricted);
63 }
64
65 public LocationEnabler(Context context, LocationModeChangeListener listener,
66 Lifecycle lifecycle) {
67 mContext = context;
68 mListener = listener;
69 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
70 if (lifecycle != null) {
71 lifecycle.addObserver(this);
72 }
73 }
74
75 @Override
76 public void onResume() {
77 if (mReceiver == null) {
78 mReceiver = new BroadcastReceiver() {
79 @Override
80 public void onReceive(Context context, Intent intent) {
81 if (Log.isLoggable(TAG, Log.DEBUG)) {
82 Log.d(TAG, "Received location mode change intent: " + intent);
83 }
84 refreshLocationMode();
85 }
86 };
87 }
88 mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED);
89 refreshLocationMode();
90 }
91
92 @Override
93 public void onPause() {
94 try {
95 mContext.unregisterReceiver(mReceiver);
96 } catch (RuntimeException e) {
97 // Ignore exceptions caused by race condition
98 }
99 }
100
101 void refreshLocationMode() {
102 final int mode = Settings.Secure.getInt(mContext.getContentResolver(),
103 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
104 if (Log.isLoggable(TAG, Log.INFO)) {
105 Log.i(TAG, "Location mode has been changed");
106 }
107 if (mListener != null) {
108 mListener.onLocationModeChanged(mode, isRestricted());
109 }
110 }
111
Maggie85e2f612018-01-04 15:35:49 -0800112 void setLocationEnabled(boolean enabled) {
113 final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
114 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
115
116 if (isRestricted()) {
117 // Location toggling disabled by user restriction. Read the current location mode to
118 // update the location master switch.
119 if (Log.isLoggable(TAG, Log.INFO)) {
120 Log.i(TAG, "Restricted user, not setting location mode");
121 }
122 if (mListener != null) {
123 mListener.onLocationModeChanged(currentMode, true);
124 }
125 return;
126 }
Lifu Tange6032be2018-01-23 21:12:14 -0800127 updateLocationEnabled(mContext, enabled, UserHandle.myUserId(),
128 Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
Maggie85e2f612018-01-04 15:35:49 -0800129 refreshLocationMode();
130 }
131
Doris Ling9ed29a22017-11-02 16:42:45 -0700132 void setLocationMode(int mode) {
133 final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
134 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
135 if (isRestricted()) {
136 // Location toggling disabled by user restriction. Read the current location mode to
137 // update the location master switch.
138 if (Log.isLoggable(TAG, Log.INFO)) {
139 Log.i(TAG, "Restricted user, not setting location mode");
140 }
141 if (mListener != null) {
142 mListener.onLocationModeChanged(currentMode, true);
143 }
144 return;
145 }
146
Lifu Tange6032be2018-01-23 21:12:14 -0800147 updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
148 Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
Doris Ling9ed29a22017-11-02 16:42:45 -0700149 refreshLocationMode();
150 }
151
152 boolean isEnabled(int mode) {
153 return mode != Settings.Secure.LOCATION_MODE_OFF && !isRestricted();
154 }
155
156 /**
157 * Checking if device policy has put a location access lock-down on the managed profile.
158 *
159 * @return true if device policy has put a location access lock-down on the managed profile
160 */
161 boolean isManagedProfileRestrictedByBase() {
162 final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
163 return managedProfile != null
164 && hasShareLocationRestriction(managedProfile.getIdentifier());
165 }
166
167 RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) {
yuemingw754ca512018-01-03 18:09:31 +0000168 RestrictedLockUtils.EnforcedAdmin admin = checkIfRestrictionEnforced(
Doris Ling9ed29a22017-11-02 16:42:45 -0700169 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
yuemingw754ca512018-01-03 18:09:31 +0000170
171 if (admin == null) {
Philip P. Moltmanne3f72112018-08-28 15:01:43 -0700172 admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
yuemingwa1416d22018-02-01 17:52:50 +0000173 mContext, UserManager.DISALLOW_CONFIG_LOCATION, userId);
yuemingw754ca512018-01-03 18:09:31 +0000174 }
175 return admin;
Doris Ling9ed29a22017-11-02 16:42:45 -0700176 }
177
178 boolean hasShareLocationRestriction(int userId) {
Philip P. Moltmanne3f72112018-08-28 15:01:43 -0700179 return RestrictedLockUtilsInternal.hasBaseUserRestriction(
Doris Ling9ed29a22017-11-02 16:42:45 -0700180 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
181 }
182
183 private boolean isRestricted() {
184 return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION);
185 }
Doris Ling9ed29a22017-11-02 16:42:45 -0700186}