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