• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
RestrictedSettingsFragment(String restrictionKey)99     public RestrictedSettingsFragment(String restrictionKey) {
100         mRestrictionKey = restrictionKey;
101     }
102 
103     @Override
onCreate(Bundle icicle)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
onActivityCreated(Bundle savedInstanceState)122     public void onActivityCreated(Bundle savedInstanceState) {
123         super.onActivityCreated(savedInstanceState);
124         mEmptyTextView = initEmptyTextView();
125     }
126 
127     @Override
onSaveInstanceState(Bundle outState)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
onResume()138     public void onResume() {
139         super.onResume();
140 
141         if (shouldBeProviderProtected(mRestrictionKey)) {
142             ensurePin();
143         }
144     }
145 
146     @Override
onDestroy()147     public void onDestroy() {
148         getActivity().unregisterReceiver(mScreenOffReceiver);
149         super.onDestroy();
150     }
151 
152     @Override
onActivityResult(int requestCode, int resultCode, Intent data)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 
ensurePin()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      */
isRestrictedAndNotProviderProtected()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 
hasChallengeSucceeded()199     protected boolean hasChallengeSucceeded() {
200         return (mChallengeRequested && mChallengeSucceeded) || !mChallengeRequested;
201     }
202 
203     /**
204      * Returns true if this restrictions key is locked down.
205      */
shouldBeProviderProtected(String restrictionKey)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 
initEmptyTextView()215     protected TextView initEmptyTextView() {
216         TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
217         return emptyView;
218     }
219 
getRestrictionEnforcedAdmin()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 
getEmptyTextView()229     public TextView getEmptyTextView() {
230         return mEmptyTextView;
231     }
232 
233     @Override
onDataSetChanged()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 
setIfOnlyAvailableForAdmins(boolean onlyForAdmins)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      */
isUiRestricted()257     protected boolean isUiRestricted() {
258         return isRestrictedAndNotProviderProtected() || !hasChallengeSucceeded()
259                 || (!mIsAdminUser && mOnlyAvailableForAdmins);
260     }
261 
isUiRestrictedByOnlyAdmin()262     protected boolean isUiRestrictedByOnlyAdmin() {
263         return isUiRestricted() && !mUserManager.hasBaseUserRestriction(mRestrictionKey,
264                 UserHandle.of(UserHandle.myUserId())) && (mIsAdminUser || !mOnlyAvailableForAdmins);
265     }
266 }
267