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 */ RestrictedSettingsFragment(String restrictionKey)92 public RestrictedSettingsFragment(String restrictionKey) { 93 mRestrictionKey = restrictionKey; 94 } 95 96 @Override onCreate(Bundle icicle)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 onActivityCreated(Bundle savedInstanceState)115 public void onActivityCreated(Bundle savedInstanceState) { 116 super.onActivityCreated(savedInstanceState); 117 mAdminSupportDetails = initAdminSupportDetailsView(); 118 mEmptyTextView = initEmptyTextView(); 119 } 120 121 @Override onSaveInstanceState(Bundle outState)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 onResume()132 public void onResume() { 133 super.onResume(); 134 135 if (shouldBeProviderProtected(mRestrictionKey)) { 136 ensurePin(); 137 } 138 } 139 140 @Override onDestroy()141 public void onDestroy() { 142 getActivity().unregisterReceiver(mScreenOffReceiver); 143 super.onDestroy(); 144 } 145 146 @Override onActivityResult(int requestCode, int resultCode, Intent data)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 ensurePin()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 */ isRestrictedAndNotProviderProtected()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 hasChallengeSucceeded()189 protected boolean hasChallengeSucceeded() { 190 return (mChallengeRequested && mChallengeSucceeded) || !mChallengeRequested; 191 } 192 193 /** 194 * Returns true if this restrictions key is locked down. 195 */ shouldBeProviderProtected(String restrictionKey)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 initAdminSupportDetailsView()205 private View initAdminSupportDetailsView() { 206 return getActivity().findViewById(R.id.admin_support_details); 207 } 208 initEmptyTextView()209 protected TextView initEmptyTextView() { 210 TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty); 211 return emptyView; 212 } 213 getRestrictionEnforcedAdmin()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 getEmptyTextView()223 public TextView getEmptyTextView() { 224 return mEmptyTextView; 225 } 226 227 @Override onDataSetChanged()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 setIfOnlyAvailableForAdmins(boolean onlyForAdmins)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 */ isUiRestricted()248 protected boolean isUiRestricted() { 249 return isRestrictedAndNotProviderProtected() || !hasChallengeSucceeded() 250 || (!mIsAdminUser && mOnlyAvailableForAdmins); 251 } 252 isUiRestrictedByOnlyAdmin()253 protected boolean isUiRestrictedByOnlyAdmin() { 254 return isUiRestricted() && !mUserManager.hasBaseUserRestriction(mRestrictionKey, 255 UserHandle.of(UserHandle.myUserId())) && (mIsAdminUser || !mOnlyAvailableForAdmins); 256 } 257 } 258