165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.users;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.Activity;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.Fragment;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.BroadcastReceiver;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.RestrictionEntry;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.UserHandle;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.UserManager;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
316e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.R;
326e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.dialog.DialogFragment;
336e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.dialog.DialogFragment.Action;
346e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Arrays;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.HashSet;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List;
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Handles all aspects of DialogFragment Actions for setting individual app restrictions.
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneclass AppRestrictionsManager implements Action.Listener {
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    interface Listener {
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        void onRestrictionActionsLoaded(String packageName, ArrayList<Action> actions);
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final boolean DEBUG = false;
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String TAG = "RestrictedProfile";
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_PACKAGE_NAME = "AppRestrictionsManager.package_name";
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_RESTRICTIONS = "AppRestrictionsManager.restrictions";
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_USER_HANDLE = "user_handle";
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_ENABLED = "enabled";
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_RESTRICTION_KEY = "restriction_key";
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String EXTRA_CHOICE_VALUE = "choice_value";
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_CUSTOM_CONFIGURATION = "action_custom_configuration";
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_TRUE = "action_true";
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_FALSE = "action_false";
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_CHANGE_RESTRICTION = "action_change_restriction";
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_CHOICE = "action_choice";
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACTION_MULTI_CHOICE = "action_multi_choice";
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int MUTUALLY_EXCLUSIVE_CHOICE_CHECK_SET_ID = 1;
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Fragment mFragment;
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final UserManager mUserManager;
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final UserHandle mUserHandle;
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final String mPackageName;
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Listener mListener;
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private static final String CUSTOM_RESTRICTIONS_INTENT = Intent.EXTRA_RESTRICTIONS_INTENT;
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void onReceive(Context context, Intent intent) {
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Bundle results = getResultExtras(true);
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRestrictions = results.getParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST);
786e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler            mRestrictionsIntent = results.getParcelable(CUSTOM_RESTRICTIONS_INTENT);
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (mRestrictions != null && mRestrictionsIntent == null) {
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                saveRestrictions();
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (mRestrictionsIntent != null) {
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                getRestrictionActions();
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private ArrayList<RestrictionEntry> mRestrictions;
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Intent mRestrictionsIntent;
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private DialogFragment mCurrentDialogFragment;
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param fragment THe fragment for which DialogFragment actions are being managed.
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param userHandle the user whose app restrictions are being set.
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param userManager the user manager for setting app restrictions.
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param packageName settings' package name (for special case restrictions).
976e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler     * @param listener a listener for when restriction actions are ready to be displayed.
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    AppRestrictionsManager(Fragment fragment, UserHandle userHandle, UserManager userManager,
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String packageName, Listener listener) {
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mFragment = fragment;
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUserHandle = userHandle;
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUserManager = userManager;
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mPackageName = packageName;
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mListener = listener;
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void loadRestrictionActions() {
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mPackageName.equals(mFragment.getActivity().getPackageName())) {
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // Settings, fake it by using user restrictions
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRestrictions = RestrictionUtils.getRestrictions(mFragment.getActivity(), mUserHandle);
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRestrictionsIntent = null;
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            getRestrictionActions();
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            requestRestrictionsForApp();
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onActionClicked(Action action) {
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String restrictionEntryKey = action.getIntent().getStringExtra(EXTRA_RESTRICTION_KEY);
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        RestrictionEntry entry = restrictionEntryKey != null ? findRestriction(restrictionEntryKey)
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                : null;
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (ACTION_CUSTOM_CONFIGURATION.equals(action.getKey())) {
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mFragment.startActivityForResult(action.getIntent(), 1);
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (ACTION_CHANGE_RESTRICTION.equals(action.getKey())) {
1286e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler            ArrayList<Action> actions = new ArrayList<>();
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            switch (entry.getType()) {
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                case RestrictionEntry.TYPE_BOOLEAN:
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    actions.add(new Action.Builder()
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .key(ACTION_TRUE)
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(Boolean.toString(true))
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .checked(entry.getSelectedState())
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .checkSetId(MUTUALLY_EXCLUSIVE_CHOICE_CHECK_SET_ID)
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .intent(action.getIntent())
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build());
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    actions.add(new Action.Builder()
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .key(ACTION_FALSE)
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(Boolean.toString(false))
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .checked(!entry.getSelectedState())
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .checkSetId(MUTUALLY_EXCLUSIVE_CHOICE_CHECK_SET_ID)
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .intent(action.getIntent())
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build());
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    break;
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                case RestrictionEntry.TYPE_CHOICE:
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                case RestrictionEntry.TYPE_CHOICE_LEVEL:
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                {
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    String value = entry.getSelectedString();
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (value == null) {
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        value = entry.getDescription();
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    String[] choiceEntries = entry.getChoiceEntries();
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    String[] choiceValues = entry.getChoiceValues();
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    boolean useValue = (choiceEntries == null
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            || choiceEntries.length != choiceValues.length);
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    for (int i = 0; i < choiceValues.length; i++) {
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String choiceValue = choiceValues[i];
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String title = useValue ? choiceValue : choiceEntries[i];
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        Intent intent = new Intent(action.getIntent());
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        intent.putExtra(EXTRA_CHOICE_VALUE, choiceValue);
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        actions.add(new Action.Builder()
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .key(ACTION_CHOICE)
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(title)
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .checked(choiceValue.equals(value))
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .checkSetId(MUTUALLY_EXCLUSIVE_CHOICE_CHECK_SET_ID)
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .intent(intent)
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build());
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    break;
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                case RestrictionEntry.TYPE_MULTI_SELECT:
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                {
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    List<String> selectedChoiceValues = Arrays.asList(
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            entry.getAllSelectedStrings());
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    String[] choiceEntries = entry.getChoiceEntries();
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    String[] choiceValues = entry.getChoiceValues();
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    boolean useValues = (choiceEntries == null
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            || choiceEntries.length != choiceValues.length);
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    for (int i = 0; i < choiceValues.length; i++) {
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String choiceValue = choiceValues[i];
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String title = useValues ? choiceValue : choiceEntries[i];
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        Intent intent = new Intent(action.getIntent());
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        intent.putExtra(EXTRA_CHOICE_VALUE, choiceValue);
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        actions.add(new Action.Builder()
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .key(ACTION_MULTI_CHOICE)
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(title)
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .checked(selectedChoiceValues.contains(choiceValue))
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .intent(intent)
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build());
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    break;
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                case RestrictionEntry.TYPE_NULL:
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                default:
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (!actions.isEmpty()) {
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mCurrentDialogFragment = new DialogFragment.Builder()
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .title(entry.getTitle())
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .description(entry.getDescription())
2023150b12e5df05eec2c3ebb85360661f1d034c188Andrew Wilson                        .iconResourceId(RestrictedProfileDialogFragment.getIconResource())
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .iconBackgroundColor(
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                mFragment.getActivity().getResources()
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        .getColor(R.color.icon_background))
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .actions(actions).build();
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mCurrentDialogFragment.setListener(this);
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                DialogFragment.add(mFragment.getFragmentManager(), mCurrentDialogFragment);
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (ACTION_TRUE.equals(action.getKey())) {
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            entry.setSelectedState(true);
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            saveRestrictions();
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (ACTION_FALSE.equals(action.getKey())) {
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            entry.setSelectedState(false);
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            saveRestrictions();
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (ACTION_CHOICE.equals(action.getKey())) {
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            entry.setSelectedString(getChoiceValue(action));
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            saveRestrictions();
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if (ACTION_MULTI_CHOICE.equals(action.getKey())) {
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            action.setChecked(!action.isChecked());
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (mCurrentDialogFragment != null) {
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mCurrentDialogFragment.setActions(mCurrentDialogFragment.getActions());
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
2266e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler            HashSet<String> selectedChoiceValues = new HashSet<>();
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            selectedChoiceValues.addAll(Arrays.asList(entry.getAllSelectedStrings()));
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (action.isChecked()) {
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                selectedChoiceValues.add(getChoiceValue(action));
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                selectedChoiceValues.remove(getChoiceValue(action));
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            entry.setAllSelectedStrings(
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    selectedChoiceValues.toArray(new String[selectedChoiceValues.size()]));
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            saveRestrictions();
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void onActivityResult(int requestCode, int resultCode, Intent data) {
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (resultCode == Activity.RESULT_OK) {
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayList<RestrictionEntry> list =
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    data.getParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST);
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Bundle bundle = data.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (list != null) {
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // If there's a valid result, persist it to the user manager.
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mUserManager.setApplicationRestrictions(mPackageName,
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        RestrictionUtils.restrictionsToBundle(list), mUserHandle);
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (bundle != null) {
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // If there's a valid result, persist it to the user manager.
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mUserManager.setApplicationRestrictions(mPackageName, bundle, mUserHandle);
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
253420343e45f4c3db45ef7390cb572a6388ba45c37Andrew Wilson            loadRestrictionActions();
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private RestrictionEntry findRestriction(String key) {
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (RestrictionEntry entry : mRestrictions) {
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (entry.getKey().equals(key)) {
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return entry;
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Log.wtf(TAG, "Couldn't find the restriction to set!");
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return null;
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String getChoiceValue(Action action) {
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return action.getIntent().getStringExtra(EXTRA_CHOICE_VALUE);
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Send a broadcast to the app to query its restrictions
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void requestRestrictionsForApp() {
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Bundle oldEntries = mUserManager.getApplicationRestrictions(mPackageName, mUserHandle);
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.setPackage(mPackageName);
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE, oldEntries);
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mFragment.getActivity().sendOrderedBroadcast(intent, null, mBroadcastReceiver, null,
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Activity.RESULT_OK, null, null);
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void getRestrictionActions() {
2856e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler        ArrayList<Action> actions = new ArrayList<>();
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mRestrictionsIntent != null) {
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            actions.add(new Action.Builder()
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .key(ACTION_CUSTOM_CONFIGURATION)
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .title(mFragment.getActivity().getString(
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            R.string.restricted_profile_customize_restrictions))
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .intent(mRestrictionsIntent)
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .hasNext(true)
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .build());
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mRestrictions != null) {
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (RestrictionEntry entry : mRestrictions) {
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Intent data = new Intent().putExtra(EXTRA_RESTRICTION_KEY, entry.getKey());
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                switch (entry.getType()) {
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case RestrictionEntry.TYPE_BOOLEAN:
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        actions.add(new Action.Builder()
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .key(ACTION_CHANGE_RESTRICTION)
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(entry.getTitle())
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .description(mFragment.getActivity().getString(
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        R.string.restriction_description, entry.getDescription(),
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        Boolean.toString(entry.getSelectedState())))
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .hasNext(mRestrictionsIntent == null)
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .infoOnly(mRestrictionsIntent != null)
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .intent(data)
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .multilineDescription(true)
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build());
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case RestrictionEntry.TYPE_CHOICE:
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case RestrictionEntry.TYPE_CHOICE_LEVEL:
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String value = entry.getSelectedString();
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (value == null) {
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            value = entry.getDescription();
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        actions.add(new Action.Builder()
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .key(ACTION_CHANGE_RESTRICTION)
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(entry.getTitle())
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .description(mFragment.getActivity().getString(
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        R.string.restriction_description,
32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        entry.getDescription(), findInArray(
32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                                entry.getChoiceEntries(), entry.getChoiceValues(),
32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                                value)))
32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .hasNext(mRestrictionsIntent == null)
32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .infoOnly(mRestrictionsIntent != null)
33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .intent(data)
33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .multilineDescription(true)
33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build());
33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case RestrictionEntry.TYPE_MULTI_SELECT:
33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        actions.add(new Action.Builder()
33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .key(ACTION_CHANGE_RESTRICTION)
33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(entry.getTitle())
33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .description(mFragment.getActivity().getString(
33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        R.string.restriction_description,
34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                        entry.getDescription(), TextUtils.join(
34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                                ", ", findSelectedStrings(entry.getChoiceEntries(),
34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                                        entry.getChoiceValues(),
34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                                        entry.getAllSelectedStrings()))))
34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .hasNext(mRestrictionsIntent == null)
34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .infoOnly(mRestrictionsIntent != null)
34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .intent(data)
34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .multilineDescription(true)
34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build());
34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case RestrictionEntry.TYPE_NULL:
35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    default:
35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mListener.onRestrictionActionsLoaded(mPackageName, actions);
35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String findInArray(String[] choiceEntries, String[] choiceValues,
36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String selectedString) {
36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (choiceEntries == null || choiceValues.length != choiceEntries.length) {
36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return selectedString;
36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (int i = 0; i < choiceValues.length; i++) {
36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (choiceValues[i].equals(selectedString)) {
36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return choiceEntries[i];
36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return selectedString;
37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String[] findSelectedStrings(String[] choiceEntries, String[] choiceValues,
37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String[] selectedStrings) {
37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (choiceEntries == null || choiceValues.length != choiceEntries.length) {
37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return selectedStrings;
37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String[] selectedStringsMapped = new String[selectedStrings.length];
37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (int i = 0; i < selectedStrings.length; i++) {
37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            selectedStringsMapped[i] = selectedStrings[i];
38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (int j = 0; j < choiceValues.length; j++) {
38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (choiceValues[j].equals(selectedStrings[i])) {
38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    selectedStringsMapped[i] = choiceEntries[j];
38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return selectedStringsMapped;
38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void saveRestrictions() {
39065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        getRestrictionActions();
39165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mPackageName.equals(mFragment.getActivity().getPackageName())) {
39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            RestrictionUtils.setRestrictions(mFragment.getActivity(), mRestrictions, mUserHandle);
39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Bundle bundle = RestrictionUtils.restrictionsToBundle(mRestrictions);
39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mUserManager.setApplicationRestrictions(mPackageName, bundle, mUserHandle);
39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
399