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
17package com.android.settings.location;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.location.LocationManager;
24import android.os.Bundle;
25import android.os.UserManager;
26import android.provider.Settings;
27import android.util.Log;
28
29import com.android.settings.SettingsPreferenceFragment;
30
31/**
32 * A base class that listens to location settings change and modifies location
33 * settings.
34 */
35public 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
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
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
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. */
86    public abstract void onModeChanged(int mode, boolean restricted);
87
88    private boolean isRestricted() {
89        final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
90        return um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION);
91    }
92
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
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