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