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.app.admin.DevicePolicyManager;
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.RestrictionsManager;
     26 import android.os.Bundle;
     27 import android.os.PersistableBundle;
     28 import android.os.UserHandle;
     29 import android.os.UserManager;
     30 import android.view.Gravity;
     31 import android.view.View;
     32 import android.widget.TextView;
     33 
     34 import com.android.settingslib.RestrictedLockUtils;
     35 
     36 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     37 
     38 /**
     39  * Base class for settings screens that should be pin protected when in restricted mode or
     40  * that will display an admin support message in case an admin has disabled the options.
     41  * The constructor for this class will take the restriction key that this screen should be
     42  * locked by.  If {@link RestrictionsManager.hasRestrictionsProvider()} and
     43  * {@link UserManager.hasUserRestriction()}, then the user will have to enter the restrictions
     44  * pin before seeing the Settings screen.
     45  *
     46  * If this settings screen should be pin protected whenever
     47  * {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
     48  * {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
     49  */
     50 public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragment {
     51 
     52     protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";
     53 
     54     // No RestrictedSettingsFragment screens should use this number in startActivityForResult.
     55     private static final int REQUEST_PIN_CHALLENGE = 12309;
     56 
     57     private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
     58     private static final String KEY_CHALLENGE_REQUESTED = "chrq";
     59 
     60     // If the restriction PIN is entered correctly.
     61     private boolean mChallengeSucceeded;
     62     private boolean mChallengeRequested;
     63 
     64     private UserManager mUserManager;
     65     private RestrictionsManager mRestrictionsManager;
     66 
     67     private final String mRestrictionKey;
     68     private View mAdminSupportDetails;
     69     private EnforcedAdmin mEnforcedAdmin;
     70     private TextView mEmptyTextView;
     71 
     72     private boolean mOnlyAvailableForAdmins = false;
     73     private boolean mIsAdminUser;
     74 
     75     // Receiver to clear pin status when the screen is turned off.
     76     private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
     77         @Override
     78         public void onReceive(Context context, Intent intent) {
     79             if (!mChallengeRequested) {
     80                 mChallengeSucceeded = false;
     81                 mChallengeRequested = false;
     82             }
     83         }
     84     };
     85 
     86     /**
     87      * @param restrictionKey The restriction key to check before pin protecting
     88      *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
     89      *            be protected whenever a restrictions provider is set. Pass in
     90      *            null if it should never be protected.
     91      */
     92     public RestrictedSettingsFragment(String restrictionKey) {
     93         mRestrictionKey = restrictionKey;
     94     }
     95 
     96     @Override
     97     public void onCreate(Bundle icicle) {
     98         super.onCreate(icicle);
     99 
    100         mRestrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
    101         mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
    102         mIsAdminUser = mUserManager.isAdminUser();
    103 
    104         if (icicle != null) {
    105             mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
    106             mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
    107         }
    108 
    109         IntentFilter offFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    110         offFilter.addAction(Intent.ACTION_USER_PRESENT);
    111         getActivity().registerReceiver(mScreenOffReceiver, offFilter);
    112     }
    113 
    114     @Override
    115     public void onActivityCreated(Bundle savedInstanceState) {
    116         super.onActivityCreated(savedInstanceState);
    117         mAdminSupportDetails = initAdminSupportDetailsView();
    118         mEmptyTextView = initEmptyTextView();
    119     }
    120 
    121     @Override
    122     public void onSaveInstanceState(Bundle outState) {
    123         super.onSaveInstanceState(outState);
    124 
    125         if (getActivity().isChangingConfigurations()) {
    126             outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
    127             outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
    128         }
    129     }
    130 
    131     @Override
    132     public void onResume() {
    133         super.onResume();
    134 
    135         if (shouldBeProviderProtected(mRestrictionKey)) {
    136             ensurePin();
    137         }
    138     }
    139 
    140     @Override
    141     public void onDestroy() {
    142         getActivity().unregisterReceiver(mScreenOffReceiver);
    143         super.onDestroy();
    144     }
    145 
    146     @Override
    147     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    148         if (requestCode == REQUEST_PIN_CHALLENGE) {
    149             if (resultCode == Activity.RESULT_OK) {
    150                 mChallengeSucceeded = true;
    151                 mChallengeRequested = false;
    152             } else {
    153                 mChallengeSucceeded = false;
    154             }
    155             return;
    156         }
    157 
    158         super.onActivityResult(requestCode, resultCode, data);
    159     }
    160 
    161     private void ensurePin() {
    162         if (!mChallengeSucceeded && !mChallengeRequested
    163                 && mRestrictionsManager.hasRestrictionsProvider()) {
    164             Intent intent = mRestrictionsManager.createLocalApprovalIntent();
    165             if (intent != null) {
    166                 mChallengeRequested = true;
    167                 mChallengeSucceeded = false;
    168                 PersistableBundle request = new PersistableBundle();
    169                 request.putString(RestrictionsManager.REQUEST_KEY_MESSAGE,
    170                         getResources().getString(R.string.restr_pin_enter_admin_pin));
    171                 intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, request);
    172                 startActivityForResult(intent, REQUEST_PIN_CHALLENGE);
    173             }
    174         }
    175     }
    176 
    177     /**
    178      * Returns true if this activity is restricted, but no restrictions provider has been set.
    179      * Used to determine if the settings UI should disable UI.
    180      */
    181     protected boolean isRestrictedAndNotProviderProtected() {
    182         if (mRestrictionKey == null || RESTRICT_IF_OVERRIDABLE.equals(mRestrictionKey)) {
    183             return false;
    184         }
    185         return mUserManager.hasUserRestriction(mRestrictionKey)
    186                 && !mRestrictionsManager.hasRestrictionsProvider();
    187     }
    188 
    189     protected boolean hasChallengeSucceeded() {
    190         return (mChallengeRequested && mChallengeSucceeded) || !mChallengeRequested;
    191     }
    192 
    193     /**
    194      * Returns true if this restrictions key is locked down.
    195      */
    196     protected boolean shouldBeProviderProtected(String restrictionKey) {
    197         if (restrictionKey == null) {
    198             return false;
    199         }
    200         boolean restricted = RESTRICT_IF_OVERRIDABLE.equals(restrictionKey)
    201                 || mUserManager.hasUserRestriction(mRestrictionKey);
    202         return restricted && mRestrictionsManager.hasRestrictionsProvider();
    203     }
    204 
    205     private View initAdminSupportDetailsView() {
    206         return getActivity().findViewById(R.id.admin_support_details);
    207     }
    208 
    209     protected TextView initEmptyTextView() {
    210         TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
    211         return emptyView;
    212     }
    213 
    214     public EnforcedAdmin getRestrictionEnforcedAdmin() {
    215         mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
    216                 mRestrictionKey, UserHandle.myUserId());
    217         if (mEnforcedAdmin != null && mEnforcedAdmin.userId == UserHandle.USER_NULL) {
    218             mEnforcedAdmin.userId = UserHandle.myUserId();
    219         }
    220         return mEnforcedAdmin;
    221     }
    222 
    223     public TextView getEmptyTextView() {
    224         return mEmptyTextView;
    225     }
    226 
    227     @Override
    228     protected void onDataSetChanged() {
    229         highlightPreferenceIfNeeded();
    230         if (mAdminSupportDetails != null && isUiRestrictedByOnlyAdmin()) {
    231             final EnforcedAdmin admin = getRestrictionEnforcedAdmin();
    232             ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(),
    233                     mAdminSupportDetails, admin, false);
    234             setEmptyView(mAdminSupportDetails);
    235         } else if (mEmptyTextView != null) {
    236             setEmptyView(mEmptyTextView);
    237         }
    238         super.onDataSetChanged();
    239     }
    240 
    241     public void setIfOnlyAvailableForAdmins(boolean onlyForAdmins) {
    242         mOnlyAvailableForAdmins = onlyForAdmins;
    243     }
    244 
    245     /**
    246      * Returns whether restricted or actionable UI elements should be removed or disabled.
    247      */
    248     protected boolean isUiRestricted() {
    249         return isRestrictedAndNotProviderProtected() || !hasChallengeSucceeded()
    250                 || (!mIsAdminUser && mOnlyAvailableForAdmins);
    251     }
    252 
    253     protected boolean isUiRestrictedByOnlyAdmin() {
    254         return isUiRestricted() && !mUserManager.hasBaseUserRestriction(mRestrictionKey,
    255                 UserHandle.of(UserHandle.myUserId())) && (mIsAdminUser || !mOnlyAvailableForAdmins);
    256     }
    257 }
    258