2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
19 import java.util.HashSet;
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;
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.
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.
42 public class RestrictedSettingsFragment extends SettingsPreferenceFragment {
44 protected static final String RESTRICTIONS_PIN_SET = "restrictions_pin_set";
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;
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";
55 // If the restriction PIN is entered correctly.
56 private boolean mChallengeSucceeded;
57 private boolean mChallengeRequested;
58 private Bundle mResumeActionBundle;
60 private UserManager mUserManager;
62 private final String mRestrictionKey;
64 private final HashSet<Preference> mProtectedByRestictionsPrefs = new HashSet<Preference>();
66 // Receiver to clear pin status when the screen is turned off.
67 private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
69 public void onReceive(Context context, Intent intent) {
70 mChallengeSucceeded = false;
71 if (shouldBePinProtected(mRestrictionKey)) {
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.
83 public RestrictedSettingsFragment(String restrictionKey) {
84 mRestrictionKey = restrictionKey;
88 public void onCreate(Bundle icicle) {
89 super.onCreate(icicle);
91 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
94 mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
95 mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
96 mResumeActionBundle = icicle.getBundle(KEY_RESUME_ACTION_BUNDLE);
101 public void onSaveInstanceState(Bundle outState) {
102 super.onSaveInstanceState(outState);
104 outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
105 if (mResumeActionBundle != null) {
106 outState.putBundle(KEY_RESUME_ACTION_BUNDLE, mResumeActionBundle);
108 if (getActivity().isChangingConfigurations()) {
109 outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
114 public void onResume() {
116 if (shouldBePinProtected(mRestrictionKey)) {
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;
123 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
124 filter.addAction(Intent.ACTION_USER_PRESENT);
125 getActivity().registerReceiver(mScreenOffReceiver, filter);
129 public void onPause() {
131 getActivity().unregisterReceiver(mScreenOffReceiver);
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);
147 // Make sure the checkbox state is the same as it was when we launched the
149 if (pref instanceof CheckBoxPreference
150 && resumeActionBundle.containsKey(EXTRA_CHECKBOX_STATE)) {
152 resumeActionBundle.getBoolean(EXTRA_CHECKBOX_STATE, false);
153 ((CheckBoxPreference)pref).setChecked(isChecked);
155 if (!onPreferenceTreeClick(getPreferenceScreen(), pref)) {
156 Intent prefIntent = pref.getIntent();
157 if (prefIntent != null) {
158 pref.getContext().startActivity(prefIntent);
163 } else if (!isDetached()) {
169 super.onActivityResult(requestCode, resultCode, data);
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());
185 Intent requestPin = new Intent(Intent.ACTION_RESTRICTIONS_CHALLENGE);
186 startActivityForResult(requestPin, REQUEST_PIN_CHALLENGE);
187 mChallengeRequested = true;
191 mChallengeSucceeded = false;
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.
198 protected boolean isRestrictedAndNotPinProtected() {
199 if (mRestrictionKey == null || RESTRICTIONS_PIN_SET.equals(mRestrictionKey)) {
202 return mUserManager.hasUserRestriction(mRestrictionKey)
203 && !mUserManager.hasRestrictionsChallenge();
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.
211 protected boolean restrictionsPinCheck(String restrictionsKey, Preference preference) {
212 if (shouldBePinProtected(restrictionsKey) && !mChallengeSucceeded) {
213 ensurePin(preference);
220 protected boolean hasChallengeSucceeded() {
221 return mChallengeSucceeded;
225 * Returns true if this restrictions key is locked down.
227 protected boolean shouldBePinProtected(String restrictionKey) {
228 if (restrictionKey == null) {
231 boolean restricted = RESTRICTIONS_PIN_SET.equals(restrictionKey)
232 || mUserManager.hasUserRestriction(restrictionKey);
233 return restricted && mUserManager.hasRestrictionsChallenge();
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.
242 boolean ensurePinRestrictedPreference(Preference preference) {
243 return mProtectedByRestictionsPrefs.contains(preference)
244 && !restrictionsPinCheck(RESTRICTIONS_PIN_SET, preference);
248 * Call this with any preferences that should require the PIN to be entered
249 * before they are accessible.
251 protected void protectByRestrictions(Preference pref) {
253 mProtectedByRestictionsPrefs.add(pref);
257 protected void protectByRestrictions(String key) {
258 Preference pref = findPreference(key);
259 protectByRestrictions(pref);