1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.location;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.location.LocationManager;
24 import android.os.Bundle;
25 import android.os.UserManager;
26 import android.provider.Settings;
27 import android.util.Log;
28 
29 import com.android.settings.SettingsPreferenceFragment;
30 
31 /**
32  * A base class that listens to location settings change and modifies location
33  * settings.
34  */
35 public abstract class LocationSettingsBase extends SettingsPreferenceFragment {
36     private static final String TAG = "LocationSettingsBase";
37     /** Broadcast intent action when the location mode is about to change. */
38     private static final String MODE_CHANGING_ACTION =
39             "com.android.settings.location.MODE_CHANGING";
40     private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
41     private static final String NEW_MODE_KEY = "NEW_MODE";
42 
43     private int mCurrentMode;
44     private BroadcastReceiver mReceiver;
45 
46     /**
47      * Whether the fragment is actively running.
48      */
49     private boolean mActive = false;
50 
51     @Override
onCreate(Bundle icicle)52     public void onCreate(Bundle icicle) {
53         super.onCreate(icicle);
54         mReceiver = new BroadcastReceiver() {
55             @Override
56             public void onReceive(Context context, Intent intent) {
57                 if (Log.isLoggable(TAG, Log.DEBUG)) {
58                     Log.d(TAG, "Received location mode change intent: " + intent);
59                 }
60                 refreshLocationMode();
61             }
62         };
63     }
64 
65     @Override
onResume()66     public void onResume() {
67         super.onResume();
68         mActive = true;
69         IntentFilter filter = new IntentFilter();
70         filter.addAction(LocationManager.MODE_CHANGED_ACTION);
71         getActivity().registerReceiver(mReceiver, filter);
72     }
73 
74     @Override
onPause()75     public void onPause() {
76         try {
77             getActivity().unregisterReceiver(mReceiver);
78         } catch (RuntimeException e) {
79             // Ignore exceptions caused by race condition
80         }
81         super.onPause();
82         mActive = false;
83     }
84 
85     /** Called when location mode has changed. */
onModeChanged(int mode, boolean restricted)86     public abstract void onModeChanged(int mode, boolean restricted);
87 
isRestricted()88     private boolean isRestricted() {
89         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
90         return um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION);
91     }
92 
setLocationMode(int mode)93     public void setLocationMode(int mode) {
94         if (isRestricted()) {
95             // Location toggling disabled by user restriction. Read the current location mode to
96             // update the location master switch.
97             if (Log.isLoggable(TAG, Log.INFO)) {
98                 Log.i(TAG, "Restricted user, not setting location mode");
99             }
100             mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
101                     Settings.Secure.LOCATION_MODE_OFF);
102             if (mActive) {
103                 onModeChanged(mode, true);
104             }
105             return;
106         }
107         Intent intent = new Intent(MODE_CHANGING_ACTION);
108         intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
109         intent.putExtra(NEW_MODE_KEY, mode);
110         getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
111         Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
112         refreshLocationMode();
113     }
114 
refreshLocationMode()115     public void refreshLocationMode() {
116         if (mActive) {
117             int mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
118                     Settings.Secure.LOCATION_MODE_OFF);
119             mCurrentMode = mode;
120             if (Log.isLoggable(TAG, Log.INFO)) {
121                 Log.i(TAG, "Location mode has been changed");
122             }
123             onModeChanged(mode, isRestricted());
124         }
125     }
126 }
127