Home | History | Annotate | Download | only in location
      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. */
     61         void onLocationModeChanged(int mode, boolean restricted);
     62     }
     63 
     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
     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
     92     public void onPause() {
     93         try {
     94             mContext.unregisterReceiver(mReceiver);
     95         } catch (RuntimeException e) {
     96             // Ignore exceptions caused by race condition
     97         }
     98     }
     99 
    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 
    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 
    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 
    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      */
    160     boolean isManagedProfileRestrictedByBase() {
    161         final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
    162         return managedProfile != null
    163                 && hasShareLocationRestriction(managedProfile.getIdentifier());
    164     }
    165 
    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 
    177     boolean hasShareLocationRestriction(int userId) {
    178         return RestrictedLockUtils.hasBaseUserRestriction(
    179                 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
    180     }
    181 
    182     private boolean isRestricted() {
    183         return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION);
    184     }
    185 }
    186