1e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard/*
2e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * Copyright (C) 2013 The Android Open Source Project
3e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard *
4e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * Licensed under the Apache License, Version 2.0 (the "License");
5e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * you may not use this file except in compliance with the License.
6e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * You may obtain a copy of the License at
7e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard *
8e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard *      http://www.apache.org/licenses/LICENSE-2.0
9e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard *
10e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * Unless required by applicable law or agreed to in writing, software
11e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * distributed under the License is distributed on an "AS IS" BASIS,
12e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * See the License for the specific language governing permissions and
14e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * limitations under the License.
15e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard */
16e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
17e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardpackage com.android.settings;
18e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
19e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardimport android.app.Activity;
204453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthallimport android.content.BroadcastReceiver;
21e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardimport android.content.Context;
22e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardimport android.content.Intent;
234453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthallimport android.content.IntentFilter;
241a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynoldsimport android.content.RestrictionsManager;
25e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardimport android.os.Bundle;
261a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynoldsimport android.os.PersistableBundle;
27e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaardimport android.os.UserManager;
28e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
29e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard/**
301a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * Base class for settings screens that should be pin protected when in restricted mode.
31e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard * The constructor for this class will take the restriction key that this screen should be
321a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * locked by.  If {@link RestrictionsManager.hasRestrictionsProvider()} and
331a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * {@link UserManager.hasUserRestriction()}, then the user will have to enter the restrictions
341a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * pin before seeing the Settings screen.
35e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard *
36fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard * If this settings screen should be pin protected whenever
371a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
381a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds * {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
39e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard */
408a963babe2e36b7a41f77b8d2598c97658196e58Chris Wrenpublic abstract class RestrictedSettingsFragment extends SettingsPreferenceFragment {
414453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall
421a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";
43e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
441a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    // No RestrictedSettingsFragment screens should use this number in startActivityForResult.
45e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private static final int REQUEST_PIN_CHALLENGE = 12309;
46e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
47e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
48e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private static final String KEY_CHALLENGE_REQUESTED = "chrq";
49e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
50e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    // If the restriction PIN is entered correctly.
51e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private boolean mChallengeSucceeded;
52e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private boolean mChallengeRequested;
53e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
54e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private UserManager mUserManager;
551a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    private RestrictionsManager mRestrictionsManager;
56e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
57e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    private final String mRestrictionKey;
58e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
594453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall    // Receiver to clear pin status when the screen is turned off.
604453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall    private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
614453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall        @Override
624453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall        public void onReceive(Context context, Intent intent) {
631a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            if (!mChallengeRequested) {
641a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeSucceeded = false;
651a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeRequested = false;
664453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall            }
674453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall        }
684453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall    };
694453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall
70fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard    /**
71fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard     * @param restrictionKey The restriction key to check before pin protecting
721a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
731a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     *            be protected whenever a restrictions provider is set. Pass in
741a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     *            null if it should never be protected.
75fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard     */
76fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard    public RestrictedSettingsFragment(String restrictionKey) {
77fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard        mRestrictionKey = restrictionKey;
78e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
79e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
80e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    @Override
81e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    public void onCreate(Bundle icicle) {
82e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        super.onCreate(icicle);
83e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
841a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        mRestrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
85fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
86fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard
87e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        if (icicle != null) {
88e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
89e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
901a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        }
911a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds
921a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        IntentFilter offFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
931a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        offFilter.addAction(Intent.ACTION_USER_PRESENT);
941a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        getActivity().registerReceiver(mScreenOffReceiver, offFilter);
95e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
96e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
97e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    @Override
98e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    public void onSaveInstanceState(Bundle outState) {
99e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        super.onSaveInstanceState(outState);
100e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
101e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        if (getActivity().isChangingConfigurations()) {
1021a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
103e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
104e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        }
105e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
106e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
107e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    @Override
108e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    public void onResume() {
109e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        super.onResume();
110d6e493f6499c3be4a0a5af14eb433dec2ab725d3Julia Reynolds
111d6e493f6499c3be4a0a5af14eb433dec2ab725d3Julia Reynolds        if (shouldBeProviderProtected(mRestrictionKey)) {
112d6e493f6499c3be4a0a5af14eb433dec2ab725d3Julia Reynolds            ensurePin();
113e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        }
1144453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall    }
1154453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall
1164453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall    @Override
1171a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    public void onDestroy() {
1184453496448feaf9152aca7ebffd952ad05a97fddMaggie Benthall        getActivity().unregisterReceiver(mScreenOffReceiver);
1191a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        super.onDestroy();
120e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
121e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
122e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    @Override
123e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    public void onActivityResult(int requestCode, int resultCode, Intent data) {
124e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        if (requestCode == REQUEST_PIN_CHALLENGE) {
125e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            if (resultCode == Activity.RESULT_OK) {
126e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard                mChallengeSucceeded = true;
1271a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeRequested = false;
1281a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            } else {
1291a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeSucceeded = false;
130e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            }
131e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            return;
132e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        }
133e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
134e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        super.onActivityResult(requestCode, resultCode, data);
135e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
136e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
1371a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    private void ensurePin() {
1381a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        if (!mChallengeSucceeded && !mChallengeRequested
1391a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                && mRestrictionsManager.hasRestrictionsProvider()) {
140375baea4563f475e3ae1d1a43518362b0a53f302Amith Yamasani            Intent intent = mRestrictionsManager.createLocalApprovalIntent();
1411a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            if (intent != null) {
1421a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeRequested = true;
1431a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                mChallengeSucceeded = false;
1441a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                PersistableBundle request = new PersistableBundle();
1451a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                request.putString(RestrictionsManager.REQUEST_KEY_MESSAGE,
1461a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                        getResources().getString(R.string.restr_pin_enter_admin_pin));
1471a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, request);
1481a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                startActivityForResult(intent, REQUEST_PIN_CHALLENGE);
149e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard            }
150e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        }
151e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
152e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard
153e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    /**
1541a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     * Returns true if this activity is restricted, but no restrictions provider has been set.
155e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard     * Used to determine if the settings UI should disable UI.
156e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard     */
1571a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    protected boolean isRestrictedAndNotProviderProtected() {
1581a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        if (mRestrictionKey == null || RESTRICT_IF_OVERRIDABLE.equals(mRestrictionKey)) {
159fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard            return false;
160fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard        }
161e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard        return mUserManager.hasUserRestriction(mRestrictionKey)
1621a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                && !mRestrictionsManager.hasRestrictionsProvider();
1631a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    }
1641a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds
1651a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    protected boolean hasChallengeSucceeded() {
1661a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        return (mChallengeRequested && mChallengeSucceeded) || !mChallengeRequested;
167e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard    }
168fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard
169fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard    /**
1701a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     * Returns true if this restrictions key is locked down.
171fe21d9aaa8a8c7f8a759805ba021b59dd821e4feGeoffrey Borggaard     */
1721a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    protected boolean shouldBeProviderProtected(String restrictionKey) {
1731a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        if (restrictionKey == null) {
1741a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds            return false;
1751a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        }
1761a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        boolean restricted = RESTRICT_IF_OVERRIDABLE.equals(restrictionKey)
1771a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds                || mUserManager.hasUserRestriction(mRestrictionKey);
1781a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        return restricted && mRestrictionsManager.hasRestrictionsProvider();
1791a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    }
1806e1102d9faf1b8f038857709412c291ef6140aa9Geoffrey Borggaard
1816e1102d9faf1b8f038857709412c291ef6140aa9Geoffrey Borggaard    /**
1821a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds     * Returns whether restricted or actionable UI elements should be removed or disabled.
1836e1102d9faf1b8f038857709412c291ef6140aa9Geoffrey Borggaard     */
1841a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    protected boolean isUiRestricted() {
1851a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds        return isRestrictedAndNotProviderProtected() || !hasChallengeSucceeded();
1861a0297c544cb15ed4b56e70575b169b3889543b7Julia Reynolds    }
187e38ea38002290da8ed16f07ea45f0ebfb41b38cdGeoffrey Borggaard}
188