OSDN Git Service

am ad541608: am ad0f0edb: Merge "Call to equals() comparing different types"
[android-x86/packages-apps-Settings.git] / src / com / android / settings / RestrictedSettingsFragment.java
1 /*
2  * Copyright (C) 2013 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;
18
19 import java.util.HashSet;
20
21 import android.app.Activity;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.os.Bundle;
27 import android.os.UserManager;
28 import android.preference.CheckBoxPreference;
29 import android.preference.Preference;
30
31 /**
32  * Base class for settings activities that should be pin protected when in restricted mode.
33  * The constructor for this class will take the restriction key that this screen should be
34  * locked by.  If {@link UserManager.hasRestrictionsPin()} and
35  * {@link UserManager.hasUserRestriction(String)} returns true for the restriction key, then
36  * the user will have to enter the restrictions pin before seeing the Settings screen.
37  *
38  * If this settings screen should be pin protected whenever
39  * {@link UserManager.hasUserRestriction(String)} returns true, pass in
40  * {@link RESTRICTIONS_PIN_SET} to the constructor instead of a restrictions key.
41  */
42 public class RestrictedSettingsFragment extends SettingsPreferenceFragment {
43
44     protected static final String RESTRICTIONS_PIN_SET = "restrictions_pin_set";
45
46     private static final String EXTRA_PREFERENCE = "pref";
47     private static final String EXTRA_CHECKBOX_STATE = "isChecked";
48     // Should be unique across all settings screens that use this.
49     private static final int REQUEST_PIN_CHALLENGE = 12309;
50
51     private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
52     private static final String KEY_CHALLENGE_REQUESTED = "chrq";
53     private static final String KEY_RESUME_ACTION_BUNDLE = "rsmb";
54
55     // If the restriction PIN is entered correctly.
56     private boolean mChallengeSucceeded;
57     private boolean mChallengeRequested;
58     private Bundle mResumeActionBundle;
59
60     private UserManager mUserManager;
61
62     private final String mRestrictionKey;
63
64     private final HashSet<Preference> mProtectedByRestictionsPrefs = new HashSet<Preference>();
65
66     // Receiver to clear pin status when the screen is turned off.
67     private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
68         @Override
69         public void onReceive(Context context, Intent intent) {
70             mChallengeSucceeded = false;
71             if (shouldBePinProtected(mRestrictionKey)) {
72                 ensurePin(null);
73             }
74         }
75     };
76
77     /**
78      * @param restrictionKey The restriction key to check before pin protecting
79      *            this settings page. Pass in {@link RESTRICTIONS_PIN_SET} if it should
80      *            be PIN protected whenever a restrictions pin is set. Pass in
81      *            null if it should never be PIN protected.
82      */
83     public RestrictedSettingsFragment(String restrictionKey) {
84         mRestrictionKey = restrictionKey;
85     }
86
87     @Override
88     public void onCreate(Bundle icicle) {
89         super.onCreate(icicle);
90
91         mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
92
93         if (icicle != null) {
94             mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
95             mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
96             mResumeActionBundle = icicle.getBundle(KEY_RESUME_ACTION_BUNDLE);
97         }
98     }
99
100     @Override
101     public void onSaveInstanceState(Bundle outState) {
102         super.onSaveInstanceState(outState);
103
104         outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
105         if (mResumeActionBundle != null) {
106             outState.putBundle(KEY_RESUME_ACTION_BUNDLE, mResumeActionBundle);
107         }
108         if (getActivity().isChangingConfigurations()) {
109             outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
110         }
111     }
112
113     @Override
114     public void onResume() {
115         super.onResume();
116         if (shouldBePinProtected(mRestrictionKey)) {
117             ensurePin(null);
118         } else {
119             // If the whole screen is not pin protected, reset mChallengeSucceeded so next
120             // time user uses a protected preference, they are prompted for pin again.
121             mChallengeSucceeded = false;
122         }
123         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
124         filter.addAction(Intent.ACTION_USER_PRESENT);
125         getActivity().registerReceiver(mScreenOffReceiver, filter);
126     }
127
128     @Override
129     public void onPause() {
130         super.onPause();
131         getActivity().unregisterReceiver(mScreenOffReceiver);
132     }
133
134     @Override
135     public void onActivityResult(int requestCode, int resultCode, Intent data) {
136         if (requestCode == REQUEST_PIN_CHALLENGE) {
137             Bundle resumeActionBundle = mResumeActionBundle;
138             mResumeActionBundle = null;
139             mChallengeRequested = false;
140             if (resultCode == Activity.RESULT_OK) {
141                 mChallengeSucceeded = true;
142                 String prefKey = resumeActionBundle == null ?
143                         null : resumeActionBundle.getString(EXTRA_PREFERENCE);
144                 if (prefKey != null) {
145                     Preference pref = findPreference(prefKey);
146                     if (pref != null) {
147                         // Make sure the checkbox state is the same as it was when we launched the
148                         // pin challenge.
149                         if (pref instanceof CheckBoxPreference
150                                 && resumeActionBundle.containsKey(EXTRA_CHECKBOX_STATE)) {
151                             boolean isChecked =
152                                     resumeActionBundle.getBoolean(EXTRA_CHECKBOX_STATE, false);
153                             ((CheckBoxPreference)pref).setChecked(isChecked);
154                         }
155                         if (!onPreferenceTreeClick(getPreferenceScreen(), pref)) {
156                             Intent prefIntent = pref.getIntent();
157                             if (prefIntent != null) {
158                                 pref.getContext().startActivity(prefIntent);
159                             }
160                         }
161                     }
162                 }
163             } else if (!isDetached()) {
164                 finishFragment();
165             }
166             return;
167         }
168
169         super.onActivityResult(requestCode, resultCode, data);
170     }
171
172     private void ensurePin(Preference preference) {
173         if (!mChallengeSucceeded) {
174             final UserManager um = UserManager.get(getActivity());
175             if (!mChallengeRequested) {
176                 if (um.hasRestrictionsChallenge()) {
177                     mResumeActionBundle = new Bundle();
178                     if (preference != null) {
179                         mResumeActionBundle.putString(EXTRA_PREFERENCE, preference.getKey());
180                         if (preference instanceof CheckBoxPreference) {
181                             mResumeActionBundle.putBoolean(EXTRA_CHECKBOX_STATE,
182                                     ((CheckBoxPreference)preference).isChecked());
183                         }
184                     }
185                     Intent requestPin = new Intent(Intent.ACTION_RESTRICTIONS_CHALLENGE);
186                     startActivityForResult(requestPin, REQUEST_PIN_CHALLENGE);
187                     mChallengeRequested = true;
188                 }
189             }
190         }
191         mChallengeSucceeded = false;
192     }
193
194     /**
195      * Returns true if this activity is restricted, but no restriction pin has been set.
196      * Used to determine if the settings UI should disable UI.
197      */
198     protected boolean isRestrictedAndNotPinProtected() {
199         if (mRestrictionKey == null || RESTRICTIONS_PIN_SET.equals(mRestrictionKey)) {
200             return false;
201         }
202         return mUserManager.hasUserRestriction(mRestrictionKey)
203                 && !mUserManager.hasRestrictionsChallenge();
204     }
205
206     /**
207      * Called to trigger the pin entry if the given restriction key is locked down.
208      * @param restrictionsKey The restriction key or {@link RESTRICTIONS_PIN_SET} if
209      *          pin entry should get triggered if there is a pin set.
210      */
211    protected boolean restrictionsPinCheck(String restrictionsKey, Preference preference) {
212        if (shouldBePinProtected(restrictionsKey) && !mChallengeSucceeded) {
213            ensurePin(preference);
214            return false;
215        } else {
216            return true;
217        }
218    }
219
220    protected boolean hasChallengeSucceeded() {
221        return mChallengeSucceeded;
222    }
223
224    /**
225     * Returns true if this restrictions key is locked down.
226     */
227    protected boolean shouldBePinProtected(String restrictionKey) {
228        if (restrictionKey == null) {
229            return false;
230        }
231        boolean restricted = RESTRICTIONS_PIN_SET.equals(restrictionKey)
232                || mUserManager.hasUserRestriction(restrictionKey);
233        return restricted && mUserManager.hasRestrictionsChallenge();
234    }
235
236    /**
237     * If the preference is one that was added by protectByRestrictions(), then it will
238     * prompt the user for the restrictions pin if they haven't entered it already.
239     * Intended to be called at the top of onPreferenceTreeClick.  If this function returns
240     * true, then onPreferenceTreeClick should return true.
241     */
242    boolean ensurePinRestrictedPreference(Preference preference) {
243        return mProtectedByRestictionsPrefs.contains(preference)
244                && !restrictionsPinCheck(RESTRICTIONS_PIN_SET, preference);
245    }
246
247     /**
248      * Call this with any preferences that should require the PIN to be entered
249      * before they are accessible.
250      */
251    protected void protectByRestrictions(Preference pref) {
252        if (pref != null) {
253            mProtectedByRestictionsPrefs.add(pref);
254        }
255    }
256
257    protected void protectByRestrictions(String key) {
258        Preference pref = findPreference(key);
259        protectByRestrictions(pref);
260    }
261 }