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