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