Home | History | Annotate | Download | only in settings
      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 android.app.Activity;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.RestrictionsManager;
     25 import android.os.Bundle;
     26 import android.os.PersistableBundle;
     27 import android.os.UserManager;
     28 
     29 /**
     30  * Base class for settings screens that should be pin protected when in restricted mode.
     31  * The constructor for this class will take the restriction key that this screen should be
     32  * locked by.  If {@link RestrictionsManager.hasRestrictionsProvider()} and
     33  * {@link UserManager.hasUserRestriction()}, then the user will have to enter the restrictions
     34  * pin before seeing the Settings screen.
     35  *
     36  * If this settings screen should be pin protected whenever
     37  * {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
     38  * {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
     39  */
     40 public class RestrictedSettingsFragment extends SettingsPreferenceFragment {
     41 
     42     protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";
     43 
     44     // No RestrictedSettingsFragment screens should use this number in startActivityForResult.
     45     private static final int REQUEST_PIN_CHALLENGE = 12309;
     46 
     47     private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
     48     private static final String KEY_CHALLENGE_REQUESTED = "chrq";
     49 
     50     // If the restriction PIN is entered correctly.
     51     private boolean mChallengeSucceeded;
     52     private boolean mChallengeRequested;
     53 
     54     private UserManager mUserManager;
     55     private RestrictionsManager mRestrictionsManager;
     56 
     57     private final String mRestrictionKey;
     58 
     59     // Receiver to clear pin status when the screen is turned off.
     60     private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
     61         @Override
     62         public void onReceive(Context context, Intent intent) {
     63             if (!mChallengeRequested) {
     64                 mChallengeSucceeded = false;
     65                 mChallengeRequested = false;
     66             }
     67         }
     68     };
     69 
     70     /**
     71      * @param restrictionKey The restriction key to check before pin protecting
     72      *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
     73      *            be protected whenever a restrictions provider is set. Pass in
     74      *            null if it should never be protected.
     75      */
     76     public RestrictedSettingsFragment(String restrictionKey) {
     77         mRestrictionKey = restrictionKey;
     78     }
     79 
     80     @Override
     81     public void onCreate(Bundle icicle) {
     82         super.onCreate(icicle);
     83 
     84         mRestrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
     85         mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
     86 
     87         if (icicle != null) {
     88             mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
     89             mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
     90         }
     91 
     92         IntentFilter offFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
     93         offFilter.addAction(Intent.ACTION_USER_PRESENT);
     94         getActivity().registerReceiver(mScreenOffReceiver, offFilter);
     95     }
     96 
     97     @Override
     98     public void onSaveInstanceState(Bundle outState) {
     99         super.onSaveInstanceState(outState);
    100 
    101         if (getActivity().isChangingConfigurations()) {
    102             outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
    103             outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
    104         }
    105     }
    106 
    107     @Override
    108     public void onResume() {
    109         super.onResume();
    110 
    111         if (shouldBeProviderProtected(mRestrictionKey)) {
    112             ensurePin();
    113         }
    114     }
    115 
    116     @Override
    117     public void onDestroy() {
    118         getActivity().unregisterReceiver(mScreenOffReceiver);
    119         super.onDestroy();
    120     }
    121 
    122     @Override
    123     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    124         if (requestCode == REQUEST_PIN_CHALLENGE) {
    125             if (resultCode == Activity.RESULT_OK) {
    126                 mChallengeSucceeded = true;
    127                 mChallengeRequested = false;
    128             } else {
    129                 mChallengeSucceeded = false;
    130             }
    131             return;
    132         }
    133 
    134         super.onActivityResult(requestCode, resultCode, data);
    135     }
    136 
    137     private void ensurePin() {
    138         if (!mChallengeSucceeded && !mChallengeRequested
    139                 && mRestrictionsManager.hasRestrictionsProvider()) {
    140             Intent intent = mRestrictionsManager.createLocalApprovalIntent();
    141             if (intent != null) {
    142                 mChallengeRequested = true;
    143                 mChallengeSucceeded = false;
    144                 PersistableBundle request = new PersistableBundle();
    145                 request.putString(RestrictionsManager.REQUEST_KEY_MESSAGE,
    146                         getResources().getString(R.string.restr_pin_enter_admin_pin));
    147                 intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, request);
    148                 startActivityForResult(intent, REQUEST_PIN_CHALLENGE);
    149             }
    150         }
    151     }
    152 
    153     /**
    154      * Returns true if this activity is restricted, but no restrictions provider has been set.
    155      * Used to determine if the settings UI should disable UI.
    156      */
    157     protected boolean isRestrictedAndNotProviderProtected() {
    158         if (mRestrictionKey == null || RESTRICT_IF_OVERRIDABLE.equals(mRestrictionKey)) {
    159             return false;
    160         }
    161         return mUserManager.hasUserRestriction(mRestrictionKey)
    162                 && !mRestrictionsManager.hasRestrictionsProvider();
    163     }
    164 
    165     protected boolean hasChallengeSucceeded() {
    166         return (mChallengeRequested && mChallengeSucceeded) || !mChallengeRequested;
    167     }
    168 
    169     /**
    170      * Returns true if this restrictions key is locked down.
    171      */
    172     protected boolean shouldBeProviderProtected(String restrictionKey) {
    173         if (restrictionKey == null) {
    174             return false;
    175         }
    176         boolean restricted = RESTRICT_IF_OVERRIDABLE.equals(restrictionKey)
    177                 || mUserManager.hasUserRestriction(mRestrictionKey);
    178         return restricted && mRestrictionsManager.hasRestrictionsProvider();
    179     }
    180 
    181     /**
    182      * Returns whether restricted or actionable UI elements should be removed or disabled.
    183      */
    184     protected boolean isUiRestricted() {
    185         return isRestrictedAndNotProviderProtected() || !hasChallengeSucceeded();
    186     }
    187 }
    188