1233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani/*
2233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * Copyright (C) 2013 The Android Open Source Project
3233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani *
4233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
5233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * you may not use this file except in compliance with the License.
6233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * You may obtain a copy of the License at
7233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani *
8233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
9233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani *
10233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * Unless required by applicable law or agreed to in writing, software
11233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
12233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * See the License for the specific language governing permissions and
14233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani * limitations under the License.
15233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani */
16233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
17233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasanipackage com.android.settings.users;
18233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
19cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasaniimport android.app.Activity;
20cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasaniimport android.appwidget.AppWidgetManager;
21233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.BroadcastReceiver;
22233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.Context;
23233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.Intent;
247b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasaniimport android.content.IntentFilter;
25233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.RestrictionEntry;
262b2ab5a9470ba8df0f18583abc2d12d5942f97ceFyodor Kupolovimport android.content.RestrictionsManager;
2707ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolovimport android.content.pm.ActivityInfo;
28cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasaniimport android.content.pm.ApplicationInfo;
29d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasaniimport android.content.pm.IPackageManager;
30233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.pm.PackageInfo;
31233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.pm.PackageManager;
32233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.pm.PackageManager.NameNotFoundException;
33233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.content.pm.ResolveInfo;
34a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasaniimport android.content.res.Resources;
35233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.graphics.drawable.Drawable;
36a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasaniimport android.os.AsyncTask;
37233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.os.Bundle;
38d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasaniimport android.os.RemoteException;
39cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasaniimport android.os.ServiceManager;
40233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.os.UserHandle;
41233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.os.UserManager;
42233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.ListPreference;
43233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.MultiSelectListPreference;
44233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.Preference;
45233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.Preference.OnPreferenceChangeListener;
46233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.Preference.OnPreferenceClickListener;
47233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.PreferenceGroup;
48233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.preference.SwitchPreference;
49233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.text.TextUtils;
50233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.util.Log;
51233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.view.View;
52233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.view.View.OnClickListener;
53bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolovimport android.view.ViewGroup;
54a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasaniimport android.view.inputmethod.InputMethodInfo;
55a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasaniimport android.view.inputmethod.InputMethodManager;
56233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.widget.CompoundButton;
57233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.widget.CompoundButton.OnCheckedChangeListener;
58233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport android.widget.Switch;
59233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
608a963babe2e36b7a41f77b8d2598c97658196e58Chris Wrenimport com.android.internal.logging.MetricsLogger;
61233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport com.android.settings.R;
62233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport com.android.settings.SettingsPreferenceFragment;
6345f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasaniimport com.android.settings.Utils;
64233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.ArrayList;
65233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.Collections;
66233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.Comparator;
67233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.HashMap;
68233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.HashSet;
69233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.List;
70cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasaniimport java.util.Map;
71233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.Set;
72233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasaniimport java.util.StringTokenizer;
73233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
74233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasanipublic class AppRestrictionsFragment extends SettingsPreferenceFragment implements
75233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        OnPreferenceChangeListener, OnClickListener, OnPreferenceClickListener {
76233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
77233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private static final String TAG = AppRestrictionsFragment.class.getSimpleName();
78233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
79d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    private static final boolean DEBUG = false;
80d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
81233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private static final String PKG_PREFIX = "pkg_";
82233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
830ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected PackageManager mPackageManager;
840ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected UserManager mUserManager;
857eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    protected IPackageManager mIPm;
860ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected UserHandle mUser;
877eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private PackageInfo mSysPackageInfo;
88233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
89233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private PreferenceGroup mAppList;
90233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
91233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private static final int MAX_APP_RESTRICTIONS = 100;
92233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
93233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private static final String DELIMITER = ";";
94cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani
95cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    /** Key for extra passed in from calling fragment for the userId of the user being edited */
96cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    public static final String EXTRA_USER_ID = "user_id";
97cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani
98cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    /** Key for extra passed in from calling fragment to indicate if this is a newly created user */
99cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    public static final String EXTRA_NEW_USER = "new_user";
100cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani
101233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    HashMap<String,Boolean> mSelectedPackages = new HashMap<String,Boolean>();
102233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private boolean mFirstTime = true;
103233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    private boolean mNewUser;
104cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    private boolean mAppListChanged;
1050ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected boolean mRestrictedProfile;
1060ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
1070ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    private static final int CUSTOM_REQUEST_CODE_START = 1000;
1080ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    private int mCustomRequestCode = CUSTOM_REQUEST_CODE_START;
109233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
1106e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    private HashMap<Integer, AppRestrictionsPreference> mCustomRequestMap =
1116e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            new HashMap<Integer,AppRestrictionsPreference>();
1126e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
113a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    private List<SelectableAppInfo> mVisibleApps;
114a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    private List<ApplicationInfo> mUserApps;
115ab72687b15b1fb748ac796ce9a9818351845ef24Amith Yamasani    private AsyncTask mAppLoadingTask;
116a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
1177b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani    private BroadcastReceiver mUserBackgrounding = new BroadcastReceiver() {
1187b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        @Override
1197b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        public void onReceive(Context context, Intent intent) {
1207b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            // Update the user's app selection right away without waiting for a pause
1217b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            // onPause() might come in too late, causing apps to disappear after broadcasts
1227b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            // have been scheduled during user startup.
1237b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            if (mAppListChanged) {
1247b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                if (DEBUG) Log.d(TAG, "User backgrounding, update app list");
1250ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                applyUserAppsStates();
1267b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                if (DEBUG) Log.d(TAG, "User backgrounding, done updating app list");
1277b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            }
1287b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        }
1297b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani    };
1307b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani
1317eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private BroadcastReceiver mPackageObserver = new BroadcastReceiver() {
1327eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        @Override
1337eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        public void onReceive(Context context, Intent intent) {
1347eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            onPackageChanged(intent);
1357eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
1367eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    };
1377eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
138d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    static class SelectableAppInfo {
139d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        String packageName;
140d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        CharSequence appName;
141d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        CharSequence activityName;
142d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        Drawable icon;
143d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        SelectableAppInfo masterEntry;
144d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
145d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        @Override
146d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        public String toString() {
147d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            return packageName + ": appName=" + appName + "; activityName=" + activityName
148d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    + "; icon=" + icon + "; masterEntry=" + masterEntry;
149d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        }
150d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    }
151d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
152233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    static class AppRestrictionsPreference extends SwitchPreference {
153233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        private boolean hasSettings;
154233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        private OnClickListener listener;
155233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        private ArrayList<RestrictionEntry> restrictions;
156d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        private boolean panelOpen;
157d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        private boolean immutable;
1587eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        private List<Preference> mChildren = new ArrayList<Preference>();
159233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
160233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        AppRestrictionsPreference(Context context, OnClickListener listener) {
161233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            super(context);
162233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            setLayoutResource(R.layout.preference_app_restrictions);
163233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            this.listener = listener;
164233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
165233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
166233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        private void setSettingsEnabled(boolean enable) {
167233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            hasSettings = enable;
168233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
169233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
170233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        void setRestrictions(ArrayList<RestrictionEntry> restrictions) {
171233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            this.restrictions = restrictions;
172233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
173233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
174d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        void setImmutable(boolean immutable) {
175d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            this.immutable = immutable;
176233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
177233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
178d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        boolean isImmutable() {
179d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            return immutable;
180233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
181233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
182233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        ArrayList<RestrictionEntry> getRestrictions() {
183233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            return restrictions;
184233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
185233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
1867eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        boolean isPanelOpen() {
187d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            return panelOpen;
188d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        }
189d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani
190d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        void setPanelOpen(boolean open) {
191d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            panelOpen = open;
1927eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
1937eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
1947eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        List<Preference> getChildren() {
1957eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            return mChildren;
1967eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
1977eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
198233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        @Override
199233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        protected void onBindView(View view) {
200233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            super.onBindView(view);
201233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
202233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            View appRestrictionsSettings = view.findViewById(R.id.app_restrictions_settings);
203233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            appRestrictionsSettings.setVisibility(hasSettings ? View.VISIBLE : View.GONE);
204233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            view.findViewById(R.id.settings_divider).setVisibility(
205233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    hasSettings ? View.VISIBLE : View.GONE);
206233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            appRestrictionsSettings.setOnClickListener(listener);
207233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            appRestrictionsSettings.setTag(this);
208233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
209233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            View appRestrictionsPref = view.findViewById(R.id.app_restrictions_pref);
210233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            appRestrictionsPref.setOnClickListener(listener);
211233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            appRestrictionsPref.setTag(this);
212233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
213233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            ViewGroup widget = (ViewGroup) view.findViewById(android.R.id.widget_frame);
214d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            widget.setEnabled(!isImmutable());
215233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            if (widget.getChildCount() > 0) {
2167eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                final Switch toggle = (Switch) widget.getChildAt(0);
2177eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                toggle.setEnabled(!isImmutable());
2187eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                toggle.setTag(this);
2193391321e2fb6cca4db3030b01af9a69763e7c40dAmith Yamasani                toggle.setClickable(true);
2203391321e2fb6cca4db3030b01af9a69763e7c40dAmith Yamasani                toggle.setFocusable(true);
2217eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
222233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    @Override
223233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2247eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        listener.onClick(toggle);
225233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    }
226233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                });
227233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
228233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
229233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
230233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
2310ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected void init(Bundle icicle) {
232cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        if (icicle != null) {
233cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani            mUser = new UserHandle(icicle.getInt(EXTRA_USER_ID));
234cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        } else {
235cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani            Bundle args = getArguments();
2360ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            if (args != null) {
2370ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                if (args.containsKey(EXTRA_USER_ID)) {
2380ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                    mUser = new UserHandle(args.getInt(EXTRA_USER_ID));
2390ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                }
2400ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                mNewUser = args.getBoolean(EXTRA_NEW_USER, false);
241cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani            }
242cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        }
2430ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
2440ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        if (mUser == null) {
2450ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            mUser = android.os.Process.myUserHandle();
2460ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        }
2470ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
248a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        mPackageManager = getActivity().getPackageManager();
2497eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
250233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        mUserManager = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
2510ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        mRestrictedProfile = mUserManager.getUserInfo(mUser.getIdentifier()).isRestricted();
2527eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        try {
2537eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            mSysPackageInfo = mPackageManager.getPackageInfo("android",
2547eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                PackageManager.GET_SIGNATURES);
2557eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        } catch (NameNotFoundException nnfe) {
2567eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            // ?
2577eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
2580ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        addPreferencesFromResource(R.xml.app_restrictions);
2590ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        mAppList = getAppPreferenceGroup();
2601bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani    }
2611bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani
2621bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani    @Override
2638a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    protected int getMetricsCategory() {
2648a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren        return MetricsLogger.USERS_APP_RESTRICTIONS;
2658a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    }
2668a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren
2678a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    @Override
268cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    public void onSaveInstanceState(Bundle outState) {
269cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        super.onSaveInstanceState(outState);
270cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        outState.putInt(EXTRA_USER_ID, mUser.getIdentifier());
271233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
272233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
2737eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    @Override
274233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    public void onResume() {
275233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        super.onResume();
2760ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
2777b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        getActivity().registerReceiver(mUserBackgrounding,
2787b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                new IntentFilter(Intent.ACTION_USER_BACKGROUND));
2797eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        IntentFilter packageFilter = new IntentFilter();
2807eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
2817eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2827eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        packageFilter.addDataScheme("package");
2837eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        getActivity().registerReceiver(mPackageObserver, packageFilter);
2847eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
285cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        mAppListChanged = false;
286ab72687b15b1fb748ac796ce9a9818351845ef24Amith Yamasani        if (mAppLoadingTask == null || mAppLoadingTask.getStatus() == AsyncTask.Status.FINISHED) {
287ab72687b15b1fb748ac796ce9a9818351845ef24Amith Yamasani            mAppLoadingTask = new AppLoadingTask().execute((Void[]) null);
288ab72687b15b1fb748ac796ce9a9818351845ef24Amith Yamasani        }
289233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
290233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
2917eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    @Override
292cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    public void onPause() {
293cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        super.onPause();
2947b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        mNewUser = false;
2957b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        getActivity().unregisterReceiver(mUserBackgrounding);
2967eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        getActivity().unregisterReceiver(mPackageObserver);
297cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        if (mAppListChanged) {
2989517b02d4314a181cb09b33521fc2b81754baedbAmith Yamasani            new Thread() {
2999517b02d4314a181cb09b33521fc2b81754baedbAmith Yamasani                public void run() {
3000ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                    applyUserAppsStates();
3019517b02d4314a181cb09b33521fc2b81754baedbAmith Yamasani                }
3029517b02d4314a181cb09b33521fc2b81754baedbAmith Yamasani            }.start();
303cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        }
304cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    }
305cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani
3067eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private void onPackageChanged(Intent intent) {
3077eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        String action = intent.getAction();
3087eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        String packageName = intent.getData().getSchemeSpecificPart();
3097eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        // Package added, check if the preference needs to be enabled
3107eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        AppRestrictionsPreference pref = (AppRestrictionsPreference)
3117eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                findPreference(getKeyForPackage(packageName));
3127eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        if (pref == null) return;
3137eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
3147eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        if ((Intent.ACTION_PACKAGE_ADDED.equals(action) && pref.isChecked())
3157eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                || (Intent.ACTION_PACKAGE_REMOVED.equals(action) && !pref.isChecked())) {
3167eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            pref.setEnabled(true);
3177eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
3187eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    }
3197eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
3200ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    protected PreferenceGroup getAppPreferenceGroup() {
3210ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        return getPreferenceScreen();
3220ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    }
3230ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
3240ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    private void applyUserAppsStates() {
325a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        final int userId = mUser.getIdentifier();
3260ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        if (!mUserManager.getUserInfo(userId).isRestricted() && userId != UserHandle.myUserId()) {
3270ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            Log.e(TAG, "Cannot apply application restrictions on another user!");
328a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            return;
329a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        }
330cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        for (Map.Entry<String,Boolean> entry : mSelectedPackages.entrySet()) {
331a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            String packageName = entry.getKey();
3327eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            boolean enabled = entry.getValue();
3337eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            applyUserAppState(packageName, enabled);
3347eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
3357eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    }
3367eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
3377eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private void applyUserAppState(String packageName, boolean enabled) {
3387eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        final int userId = mUser.getIdentifier();
3397eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        if (enabled) {
3407eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            // Enable selected apps
3417eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            try {
3427eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                ApplicationInfo info = mIPm.getApplicationInfo(packageName,
3437eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        PackageManager.GET_UNINSTALLED_PACKAGES, userId);
3447eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                if (info == null || info.enabled == false
3457eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
3467eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier());
3477eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    if (DEBUG) {
3487eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        Log.d(TAG, "Installing " + packageName);
349a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                    }
3507eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                }
351cc254f4da96506901268c4a0b1d3cfacb5f44948Alex Klyubin                if (info != null && (info.privateFlags&ApplicationInfo.PRIVATE_FLAG_HIDDEN) != 0
3527eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        && (info.flags&ApplicationInfo.FLAG_INSTALLED) != 0) {
3537eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    disableUiForPackage(packageName);
354fca31ca418ec9c8d09efd18d7616b816a3e9f94aAmith Yamasani                    mIPm.setApplicationHiddenSettingAsUser(packageName, false, userId);
3557eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    if (DEBUG) {
356fca31ca418ec9c8d09efd18d7616b816a3e9f94aAmith Yamasani                        Log.d(TAG, "Unhiding " + packageName);
3570ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                    }
358cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani                }
3597eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            } catch (RemoteException re) {
3607eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            }
3617eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        } else {
3627eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            // Blacklist all other apps, system or downloaded
3637eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            try {
3647eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                ApplicationInfo info = mIPm.getApplicationInfo(packageName, 0, userId);
3657eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                if (info != null) {
3667eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    if (mRestrictedProfile) {
3677eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        mIPm.deletePackageAsUser(packageName, null, mUser.getIdentifier(),
3687eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                                PackageManager.DELETE_SYSTEM_APP);
3697eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        if (DEBUG) {
3707eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                            Log.d(TAG, "Uninstalling " + packageName);
3717eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        }
3727eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    } else {
3737eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        disableUiForPackage(packageName);
374fca31ca418ec9c8d09efd18d7616b816a3e9f94aAmith Yamasani                        mIPm.setApplicationHiddenSettingAsUser(packageName, true, userId);
3757eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                        if (DEBUG) {
376fca31ca418ec9c8d09efd18d7616b816a3e9f94aAmith Yamasani                            Log.d(TAG, "Hiding " + packageName);
3777b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                        }
378a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                    }
379cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani                }
3807eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            } catch (RemoteException re) {
381cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani            }
382cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani        }
383cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani    }
384cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani
3857eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private void disableUiForPackage(String packageName) {
3867eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        AppRestrictionsPreference pref = (AppRestrictionsPreference) findPreference(
3877eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                getKeyForPackage(packageName));
3887eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        if (pref != null) {
3897eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani            pref.setEnabled(false);
3907eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        }
3917eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    }
3927eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
393a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    private boolean isSystemPackage(String packageName) {
394a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        try {
395a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
396a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            if (pi.applicationInfo == null) return false;
397a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            final int flags = pi.applicationInfo.flags;
398a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0
399a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                    || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
400a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                return true;
401a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            }
402a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        } catch (NameNotFoundException nnfe) {
403a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            // Missing package?
404a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        }
405a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        return false;
406a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    }
407a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani
408a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    /**
409a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * Find all pre-installed input methods that are marked as default
410a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * and add them to an exclusion list so that they aren't
411a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * presented to the user for toggling.
412a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * Don't add non-default ones, as they may include other stuff that we
413a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * don't need to auto-include.
414a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * @param excludePackages the set of package names to append to
415a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     */
416a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    private void addSystemImes(Set<String> excludePackages) {
417a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        final Context context = getActivity();
418a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        if (context == null) return;
419a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        InputMethodManager imm = (InputMethodManager)
420a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                context.getSystemService(Context.INPUT_METHOD_SERVICE);
421a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        List<InputMethodInfo> imis = imm.getInputMethodList();
422a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        for (InputMethodInfo imi : imis) {
423a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            try {
424a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                if (imi.isDefault(context) && isSystemPackage(imi.getPackageName())) {
425a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                    excludePackages.add(imi.getPackageName());
426a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                }
427a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            } catch (Resources.NotFoundException rnfe) {
428a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                // Not default
429a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            }
430a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        }
431a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    }
432a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani
433a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    /**
434a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * Add system apps that match an intent to the list, excluding any packages in the exclude list.
435a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * @param visibleApps list of apps to append the new list to
436a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * @param intent the intent to match
437a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     * @param excludePackages the set of package names to be excluded, since they're required
438a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani     */
439a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani    private void addSystemApps(List<SelectableAppInfo> visibleApps, Intent intent,
440a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani            Set<String> excludePackages) {
4411bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani        if (getActivity() == null) return;
442a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        final PackageManager pm = mPackageManager;
443a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        List<ResolveInfo> launchableApps = pm.queryIntentActivities(intent,
4440ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                PackageManager.GET_DISABLED_COMPONENTS | PackageManager.GET_UNINSTALLED_PACKAGES);
445cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        for (ResolveInfo app : launchableApps) {
446cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani            if (app.activityInfo != null && app.activityInfo.applicationInfo != null) {
447928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                final String packageName = app.activityInfo.packageName;
448cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                int flags = app.activityInfo.applicationInfo.flags;
449cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0
450cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                        || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
451cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                    // System app
452a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani                    // Skip excluded packages
453928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                    if (excludePackages.contains(packageName)) continue;
454928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                    int enabled = pm.getApplicationEnabledSetting(packageName);
455928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                    if (enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
456928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                            || enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
457928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                        // Check if the app is already enabled for the target user
458928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                        ApplicationInfo targetUserAppInfo = getAppInfoForUser(packageName,
459928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                                0, mUser);
460928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                        if (targetUserAppInfo == null
461928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                                || (targetUserAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
462928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                            continue;
463928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                        }
464928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                    }
465d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    SelectableAppInfo info = new SelectableAppInfo();
466d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.packageName = app.activityInfo.packageName;
467d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.appName = app.activityInfo.applicationInfo.loadLabel(pm);
468d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.icon = app.activityInfo.loadIcon(pm);
469d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.activityName = app.activityInfo.loadLabel(pm);
470d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    if (info.activityName == null) info.activityName = info.appName;
471a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani
472d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    visibleApps.add(info);
473cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                }
474cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani            }
475cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        }
476cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani    }
477cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani
478928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani    private ApplicationInfo getAppInfoForUser(String packageName, int flags, UserHandle user) {
479928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani        try {
480928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani            ApplicationInfo targetUserAppInfo = mIPm.getApplicationInfo(packageName, flags,
481928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani                    user.getIdentifier());
482928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani            return targetUserAppInfo;
483928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani        } catch (RemoteException re) {
484928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani            return null;
485928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani        }
486928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani    }
487928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani
488a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    private class AppLoadingTask extends AsyncTask<Void, Void, Void> {
489a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
490a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        @Override
491a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        protected Void doInBackground(Void... params) {
492a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            fetchAndMergeApps();
493a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            return null;
494a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        }
495a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
496a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        @Override
497a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        protected void onPostExecute(Void result) {
498a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            populateApps();
499a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        }
500a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
501a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        @Override
502a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        protected void onPreExecute() {
503a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        }
504a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    }
505a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
506a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    private void fetchAndMergeApps() {
507233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        mAppList.setOrderingAsAdded(false);
508a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        mVisibleApps = new ArrayList<SelectableAppInfo>();
509233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        final Context context = getActivity();
5101bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani        if (context == null) return;
511a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        final PackageManager pm = mPackageManager;
5127eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        final IPackageManager ipm = mIPm;
513cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani
514a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        final HashSet<String> excludePackages = new HashSet<String>();
515a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        addSystemImes(excludePackages);
516a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani
517cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        // Add launchers
518233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
519233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
520a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        addSystemApps(mVisibleApps, launcherIntent, excludePackages);
521cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani
522cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        // Add widgets
523cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        Intent widgetIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
524a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        addSystemApps(mVisibleApps, widgetIntent, excludePackages);
525cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani
5260ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        List<ApplicationInfo> installedApps = pm.getInstalledApplications(
5270ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                PackageManager.GET_UNINSTALLED_PACKAGES);
528cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        for (ApplicationInfo app : installedApps) {
5290ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            // If it's not installed, skip
5300ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
5310ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
532cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani            if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0
533cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                    && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) {
534cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani                // Downloaded app
535d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                SelectableAppInfo info = new SelectableAppInfo();
536d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                info.packageName = app.packageName;
537d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                info.appName = app.loadLabel(pm);
538d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                info.activityName = info.appName;
539d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                info.icon = app.loadIcon(pm);
540a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                mVisibleApps.add(info);
54148b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani            } else {
54248b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                try {
54348b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                    PackageInfo pi = pm.getPackageInfo(app.packageName, 0);
54448b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                    // If it's a system app that requires an account and doesn't see restricted
54548b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                    // accounts, mark for removal. It might get shown in the UI if it has an icon
54648b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                    // but will still be marked as false and immutable.
5470ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                    if (mRestrictedProfile
5480ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                            && pi.requiredAccountType != null && pi.restrictedAccountType == null) {
54948b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                        mSelectedPackages.put(app.packageName, false);
55048b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                    }
55148b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                } catch (NameNotFoundException re) {
55248b8b8fd1866f867fa995b69ee07b557c9eb766eAmith Yamasani                }
553d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            }
554d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        }
555d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
556928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani        // Get the list of apps already installed for the user
557a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        mUserApps = null;
558d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        try {
559a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            mUserApps = ipm.getInstalledApplications(
5600ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                    PackageManager.GET_UNINSTALLED_PACKAGES, mUser.getIdentifier()).getList();
561d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        } catch (RemoteException re) {
562d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        }
563d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
564a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        if (mUserApps != null) {
565a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            for (ApplicationInfo app : mUserApps) {
5660ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani                if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
5670ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
568d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0
569d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                        && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) {
570d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    // Downloaded app
571d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    SelectableAppInfo info = new SelectableAppInfo();
572d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.packageName = app.packageName;
573d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.appName = app.loadLabel(pm);
574d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.activityName = info.appName;
575d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    info.icon = app.loadIcon(pm);
576a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                    mVisibleApps.add(info);
577d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                }
578cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani            }
579cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        }
580928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani
581928191881df05c6520c1da8c208b6a7f47f52d45Amith Yamasani        // Sort the list of visible apps
582a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        Collections.sort(mVisibleApps, new AppLabelComparator());
583233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
584d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        // Remove dupes
585a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        Set<String> dedupPackageSet = new HashSet<String>();
586a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        for (int i = mVisibleApps.size() - 1; i >= 0; i--) {
587a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            SelectableAppInfo info = mVisibleApps.get(i);
588d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            if (DEBUG) Log.i(TAG, info.toString());
589a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            String both = info.packageName + "+" + info.activityName;
590a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            if (!TextUtils.isEmpty(info.packageName)
591a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                    && !TextUtils.isEmpty(info.activityName)
592a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                    && dedupPackageSet.contains(both)) {
593a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                mVisibleApps.remove(i);
594a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            } else {
595a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                dedupPackageSet.add(both);
596cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani            }
597cb7b0b77ae04a84c75611a98a583c81208575ba5Amith Yamasani        }
598d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
599d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        // Establish master/slave relationship for entries that share a package name
600d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        HashMap<String,SelectableAppInfo> packageMap = new HashMap<String,SelectableAppInfo>();
601a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        for (SelectableAppInfo info : mVisibleApps) {
602d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            if (packageMap.containsKey(info.packageName)) {
603d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                info.masterEntry = packageMap.get(info.packageName);
604d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            } else {
605d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                packageMap.put(info.packageName, info);
606d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            }
607d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        }
608a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    }
609a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani
6107eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private boolean isPlatformSigned(PackageInfo pi) {
6117eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        return (pi != null && pi.signatures != null &&
6127eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    mSysPackageInfo.signatures[0].equals(pi.signatures[0]));
6137eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    }
6147eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
6150ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    private boolean isAppEnabledForUser(PackageInfo pi) {
6160ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        if (pi == null) return false;
6170ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        final int flags = pi.applicationInfo.flags;
618cc254f4da96506901268c4a0b1d3cfacb5f44948Alex Klyubin        final int privateFlags = pi.applicationInfo.privateFlags;
619fca31ca418ec9c8d09efd18d7616b816a3e9f94aAmith Yamasani        // Return true if it is installed and not hidden
6200ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        return ((flags&ApplicationInfo.FLAG_INSTALLED) != 0
621cc254f4da96506901268c4a0b1d3cfacb5f44948Alex Klyubin                && (privateFlags&ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0);
6220ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani    }
6230ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani
624a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani    private void populateApps() {
625a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani        final Context context = getActivity();
6261bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani        if (context == null) return;
627a7a93784d1f9798d37cb618def1a558f8d626f0fAmith Yamasani        final PackageManager pm = mPackageManager;
6287eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        final IPackageManager ipm = mIPm;
62945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani        final int userId = mUser.getIdentifier();
6307eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
63145f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani        // Check if the user was removed in the meantime.
63245f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani        if (Utils.getExistingUser(mUserManager, mUser) == null) {
63345f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            return;
63445f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani        }
6351bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani        mAppList.removeAll();
636233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        Intent restrictionsIntent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
637233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(restrictionsIntent, 0);
63845f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani        for (SelectableAppInfo app : mVisibleApps) {
63945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            String packageName = app.packageName;
64045f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            if (packageName == null) continue;
64145f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            final boolean isSettingsApp = packageName.equals(context.getPackageName());
64245f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            AppRestrictionsPreference p = new AppRestrictionsPreference(context, this);
64345f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            final boolean hasSettings = resolveInfoListHasPackage(receivers, packageName);
644bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            if (isSettingsApp) {
645bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                addLocationAppRestrictionsPreference(app, p);
646b0fc28cba5fecb4cf6ed045915f65d3459208cbcFyodor Kupolov                // Settings app should be available to restricted user
647b0fc28cba5fecb4cf6ed045915f65d3459208cbcFyodor Kupolov                mSelectedPackages.put(packageName, true);
648bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                continue;
64945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            }
65045f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            PackageInfo pi = null;
65145f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            try {
65245f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                pi = ipm.getPackageInfo(packageName,
65345f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                        PackageManager.GET_UNINSTALLED_PACKAGES
65445f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                        | PackageManager.GET_SIGNATURES, userId);
65545f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            } catch (RemoteException e) {
65645f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            }
65745f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            if (pi == null) {
65845f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                continue;
65945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            }
660bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            if (mRestrictedProfile && isAppUnsupportedInRestrictedProfile(pi)) {
661bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                continue;
662bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            }
663bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setIcon(app.icon != null ? app.icon.mutate() : null);
664bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setChecked(false);
665bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setTitle(app.activityName);
666bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setKey(getKeyForPackage(packageName));
667bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setSettingsEnabled(hasSettings && app.masterEntry == null);
668bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setPersistent(false);
669bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setOnPreferenceChangeListener(this);
670bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setOnPreferenceClickListener(this);
671bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setSummary(getPackageSummary(pi, app));
67245f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            if (pi.requiredForAllUsers || isPlatformSigned(pi)) {
67345f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                p.setChecked(true);
67445f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                p.setImmutable(true);
67545f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                // If the app is required and has no restrictions, skip showing it
676bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                if (!hasSettings) continue;
67745f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                // Get and populate the defaults, since the user is not going to be
67845f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                // able to toggle this app ON (it's ON by default and immutable).
67945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                // Only do this for restricted profiles, not single-user restrictions
68045f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                // Also don't do this for slave icons
681bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                if (app.masterEntry == null) {
68245f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                    requestRestrictionsForApp(packageName, p, false);
683233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                }
68445f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            } else if (!mNewUser && isAppEnabledForUser(pi)) {
68545f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                p.setChecked(true);
68645f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            }
68745f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            if (app.masterEntry != null) {
68845f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                p.setImmutable(true);
68945f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani                p.setChecked(mSelectedPackages.get(packageName));
69045f86236e4d771f9d6c464f1e54be7fb813f4cebAmith Yamasani            }
691bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            p.setOrder(MAX_APP_RESTRICTIONS * (mAppList.getPreferenceCount() + 2));
692b0fc28cba5fecb4cf6ed045915f65d3459208cbcFyodor Kupolov            mSelectedPackages.put(packageName, p.isChecked());
693b0fc28cba5fecb4cf6ed045915f65d3459208cbcFyodor Kupolov            mAppList.addPreference(p);
694233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
695bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        mAppListChanged = true;
6967b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        // If this is the first time for a new profile, install/uninstall default apps for profile
6977b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        // to avoid taking the hit in onPause(), which can cause race conditions on user switch.
6987b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        if (mNewUser && mFirstTime) {
6997b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani            mFirstTime = false;
7000ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani            applyUserAppsStates();
7017b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        }
702233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
703233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
704bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    private String getPackageSummary(PackageInfo pi, SelectableAppInfo app) {
705bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        // Check for 3 cases:
706bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        // - Slave entry that can see primary user accounts
707bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        // - Slave entry that cannot see primary user accounts
708bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        // - Master entry that can see primary user accounts
709bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        // Otherwise no summary is returned
710bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        if (app.masterEntry != null) {
711bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            if (mRestrictedProfile && pi.restrictedAccountType != null) {
712bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                return getString(R.string.app_sees_restricted_accounts_and_controlled_by,
713bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                        app.masterEntry.activityName);
714bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            }
715bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            return getString(R.string.user_restrictions_controlled_by,
716bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                    app.masterEntry.activityName);
717bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        } else if (pi.restrictedAccountType != null) {
718bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            return getString(R.string.app_sees_restricted_accounts);
719bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        }
720bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        return null;
721bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    }
722bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov
723bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    private static boolean isAppUnsupportedInRestrictedProfile(PackageInfo pi) {
724bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        return pi.requiredAccountType != null && pi.restrictedAccountType == null;
725bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    }
726bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov
727bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    private void addLocationAppRestrictionsPreference(SelectableAppInfo app,
728bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov            AppRestrictionsPreference p) {
729bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        String packageName = app.packageName;
730bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setIcon(R.drawable.ic_settings_location);
731bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setKey(getKeyForPackage(packageName));
732bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        ArrayList<RestrictionEntry> restrictions = RestrictionUtils.getRestrictions(
733bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                getActivity(), mUser);
734bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        RestrictionEntry locationRestriction = restrictions.get(0);
735bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setTitle(locationRestriction.getTitle());
736bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setRestrictions(restrictions);
737bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setSummary(locationRestriction.getDescription());
738bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setChecked(locationRestriction.getSelectedState());
739bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setPersistent(false);
740bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setOnPreferenceClickListener(this);
741bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        p.setOrder(MAX_APP_RESTRICTIONS);
742bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov        mAppList.addPreference(p);
743bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov    }
744bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov
7457eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    private String getKeyForPackage(String packageName) {
7467eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani        return PKG_PREFIX + packageName;
7477eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani    }
7487eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani
749d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    private class AppLabelComparator implements Comparator<SelectableAppInfo> {
750233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
751233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        @Override
752d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        public int compare(SelectableAppInfo lhs, SelectableAppInfo rhs) {
753d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            String lhsLabel = lhs.activityName.toString();
754d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            String rhsLabel = rhs.activityName.toString();
755d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            return lhsLabel.toLowerCase().compareTo(rhsLabel.toLowerCase());
756233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
757233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
758233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
759d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    private boolean resolveInfoListHasPackage(List<ResolveInfo> receivers, String packageName) {
760233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        for (ResolveInfo info : receivers) {
761233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            if (info.activityInfo.packageName.equals(packageName)) {
762233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                return true;
763233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
764233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
765233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        return false;
766233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
767233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
768d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    private void updateAllEntries(String prefKey, boolean checked) {
769d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        for (int i = 0; i < mAppList.getPreferenceCount(); i++) {
770d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            Preference pref = mAppList.getPreference(i);
771d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            if (pref instanceof AppRestrictionsPreference) {
772d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                if (prefKey.equals(pref.getKey())) {
773d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                    ((AppRestrictionsPreference) pref).setChecked(checked);
774d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                }
775d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            }
776d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani        }
777d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani    }
778d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani
779233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    @Override
780233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    public void onClick(View v) {
7810ca80fe4cdbfa2a9298ab332770eef9890798c60Amith Yamasani        if (v.getTag() instanceof AppRestrictionsPreference) {
782233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            AppRestrictionsPreference pref = (AppRestrictionsPreference) v.getTag();
783233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            if (v.getId() == R.id.app_restrictions_settings) {
784d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                onAppSettingsIconClicked(pref);
785d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            } else if (!pref.isImmutable()) {
786233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                pref.setChecked(!pref.isChecked());
7877b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                final String packageName = pref.getKey().substring(PKG_PREFIX.length());
788bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                // Settings/Location is handled as a top-level entry
789bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                if (packageName.equals(getActivity().getPackageName())) {
790bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                    pref.restrictions.get(0).setSelectedState(pref.isChecked());
791bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                    RestrictionUtils.setRestrictions(getActivity(), pref.restrictions, mUser);
792bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                    return;
793bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                }
7947b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                mSelectedPackages.put(packageName, pref.isChecked());
7957b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                if (pref.isChecked() && pref.hasSettings
7967b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                        && pref.restrictions == null) {
7977b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                    // The restrictions have not been initialized, get and save them
798d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                    requestRestrictionsForApp(packageName, pref, false);
7997b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                }
800cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani                mAppListChanged = true;
8017eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                // If it's not a restricted profile, apply the changes immediately
8027eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                if (!mRestrictedProfile) {
8037eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    applyUserAppState(packageName, pref.isChecked());
8047eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                }
805d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani                updateAllEntries(pref.getKey(), pref.isChecked());
806233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
807233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
808233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
809233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
810233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    @Override
811233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    public boolean onPreferenceChange(Preference preference, Object newValue) {
812233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        String key = preference.getKey();
813233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        if (key != null && key.contains(DELIMITER)) {
814233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            StringTokenizer st = new StringTokenizer(key, DELIMITER);
815233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            final String packageName = st.nextToken();
816233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            final String restrictionKey = st.nextToken();
817233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            AppRestrictionsPreference appPref = (AppRestrictionsPreference)
818233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    mAppList.findPreference(PKG_PREFIX+packageName);
819233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            ArrayList<RestrictionEntry> restrictions = appPref.getRestrictions();
820233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            if (restrictions != null) {
821233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                for (RestrictionEntry entry : restrictions) {
8226e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                    if (entry.getKey().equals(restrictionKey)) {
8236e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                        switch (entry.getType()) {
824233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        case RestrictionEntry.TYPE_BOOLEAN:
8256e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                            entry.setSelectedState((Boolean) newValue);
826233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            break;
827233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        case RestrictionEntry.TYPE_CHOICE:
828233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        case RestrictionEntry.TYPE_CHOICE_LEVEL:
829233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            ListPreference listPref = (ListPreference) preference;
8306e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                            entry.setSelectedString((String) newValue);
8316e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                            String readable = findInArray(entry.getChoiceEntries(),
8326e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                                    entry.getChoiceValues(), (String) newValue);
8336e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                            listPref.setSummary(readable);
834233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            break;
835233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        case RestrictionEntry.TYPE_MULTI_SELECT:
836233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            Set<String> set = (Set<String>) newValue;
837233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            String [] selectedValues = new String[set.size()];
838233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            set.toArray(selectedValues);
8396e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                            entry.setAllSelectedStrings(selectedValues);
840233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            break;
841233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        default:
842233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                            continue;
843233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        }
844bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                        mUserManager.setApplicationRestrictions(packageName,
8452b2ab5a9470ba8df0f18583abc2d12d5942f97ceFyodor Kupolov                                RestrictionsManager.convertRestrictionsToBundle(restrictions),
846bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                                mUser);
847233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                        break;
848233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                    }
849233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                }
850233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
851233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
852233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        return true;
853233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
854233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
855d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani    private void removeRestrictionsForApp(AppRestrictionsPreference preference) {
856d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        for (Preference p : preference.mChildren) {
857d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            mAppList.removePreference(p);
858d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        }
859d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        preference.mChildren.clear();
860d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani    }
861d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani
862d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani    private void onAppSettingsIconClicked(AppRestrictionsPreference preference) {
863233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        if (preference.getKey().startsWith(PKG_PREFIX)) {
864d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            if (preference.isPanelOpen()) {
865d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                removeRestrictionsForApp(preference);
866233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            } else {
867233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani                String packageName = preference.getKey().substring(PKG_PREFIX.length());
868bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                requestRestrictionsForApp(packageName, preference, true /*invoke if custom*/);
869233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
870d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            preference.setPanelOpen(!preference.isPanelOpen());
871233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
872233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
873233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
874d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani    /**
875d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     * Send a broadcast to the app to query its restrictions
876d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     * @param packageName package name of the app with restrictions
877d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     * @param preference the preference item for the app toggle
878d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     * @param invokeIfCustom whether to directly launch any custom activity that is returned
879d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     *        for the app.
880d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani     */
8817b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani    private void requestRestrictionsForApp(String packageName,
882d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            AppRestrictionsPreference preference, boolean invokeIfCustom) {
8837b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        Bundle oldEntries =
8847b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                mUserManager.getApplicationRestrictions(packageName, mUser);
8857b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        Intent intent = new Intent(Intent.ACTION_GET_RESTRICTION_ENTRIES);
8867b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        intent.setPackage(packageName);
8877b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        intent.putExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE, oldEntries);
8887b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
8897b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani        getActivity().sendOrderedBroadcast(intent, null,
890d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                new RestrictionsResultReceiver(packageName, preference, invokeIfCustom),
8917b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani                null, Activity.RESULT_OK, null, null);
8927b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani    }
8937b56d115ba895916fb8f93ad5f4247bede3fefc7Amith Yamasani
894233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    class RestrictionsResultReceiver extends BroadcastReceiver {
895233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
8966e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        private static final String CUSTOM_RESTRICTIONS_INTENT = Intent.EXTRA_RESTRICTIONS_INTENT;
897233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        String packageName;
898233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        AppRestrictionsPreference preference;
899d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        boolean invokeIfCustom;
900233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
901d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        RestrictionsResultReceiver(String packageName, AppRestrictionsPreference preference,
902d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                boolean invokeIfCustom) {
903233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            super();
904233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            this.packageName = packageName;
905233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            this.preference = preference;
906d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani            this.invokeIfCustom = invokeIfCustom;
907233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
908233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
909233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        @Override
910233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        public void onReceive(Context context, Intent intent) {
9116e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            Bundle results = getResultExtras(true);
9126e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            final ArrayList<RestrictionEntry> restrictions = results.getParcelableArrayList(
9135ee175051951d3a0bc1533aece69af520c295d37Amith Yamasani                    Intent.EXTRA_RESTRICTIONS_LIST);
9146e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            Intent restrictionsIntent = (Intent) results.getParcelable(CUSTOM_RESTRICTIONS_INTENT);
9156e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            if (restrictions != null && restrictionsIntent == null) {
9162601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                onRestrictionsReceived(preference, packageName, restrictions);
9177eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                if (mRestrictedProfile) {
9187eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                    mUserManager.setApplicationRestrictions(packageName,
9192b2ab5a9470ba8df0f18583abc2d12d5942f97ceFyodor Kupolov                            RestrictionsManager.convertRestrictionsToBundle(restrictions), mUser);
9207eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                }
9216e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            } else if (restrictionsIntent != null) {
9226e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                preference.setRestrictions(restrictions);
923d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                if (invokeIfCustom && AppRestrictionsFragment.this.isResumed()) {
92407ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                    assertSafeToStartCustomActivity(restrictionsIntent);
925d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                    int requestCode = generateCustomActivityRequestCode(
926d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                            RestrictionsResultReceiver.this.preference);
927d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                    AppRestrictionsFragment.this.startActivityForResult(
928d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                            restrictionsIntent, requestCode);
929d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani                }
9306e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            }
9316e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        }
93207ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov
93307ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov        private void assertSafeToStartCustomActivity(Intent intent) {
93407ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            // Activity can be started if it belongs to the same app
93507ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            if (intent.getPackage() != null && intent.getPackage().equals(packageName)) {
93607ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                return;
93707ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            }
93807ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            // Activity can be started if intent resolves to multiple activities
93907ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            List<ResolveInfo> resolveInfos = AppRestrictionsFragment.this.mPackageManager
94007ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                    .queryIntentActivities(intent, 0 /* no flags */);
94107ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            if (resolveInfos.size() != 1) {
94207ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                return;
94307ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            }
94407ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            // Prevent potential privilege escalation
94507ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
94607ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            if (!packageName.equals(activityInfo.packageName)) {
94707ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                throw new SecurityException("Application " + packageName
94807ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov                        + " is not allowed to start activity " + intent);
94907ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov            };
95007ab95c43e49facb0fc4dd11d68645b4fe8d4c88Fyodor Kupolov        }
9516e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    }
9526e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
9532601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani    private void onRestrictionsReceived(AppRestrictionsPreference preference, String packageName,
9542601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            ArrayList<RestrictionEntry> restrictions) {
955d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        // Remove any earlier restrictions
956d760a619369ec5ed50cce2f10e6eecf63ab84b46Amith Yamasani        removeRestrictionsForApp(preference);
9572601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        // Non-custom-activity case - expand the restrictions in-place
9582601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        final Context context = preference.getContext();
9592601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        int count = 1;
9602601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        for (RestrictionEntry entry : restrictions) {
9612601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            Preference p = null;
9622601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            switch (entry.getType()) {
9632601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            case RestrictionEntry.TYPE_BOOLEAN:
964daef2e2b066a0bf204b9a63b7cae13e3d5441f4eFabrice Di Meglio                p = new SwitchPreference(context);
9652601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setTitle(entry.getTitle());
9662601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setSummary(entry.getDescription());
967daef2e2b066a0bf204b9a63b7cae13e3d5441f4eFabrice Di Meglio                ((SwitchPreference)p).setChecked(entry.getSelectedState());
9682601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                break;
9692601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            case RestrictionEntry.TYPE_CHOICE:
9702601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            case RestrictionEntry.TYPE_CHOICE_LEVEL:
9712601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p = new ListPreference(context);
9722601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setTitle(entry.getTitle());
9732601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                String value = entry.getSelectedString();
9742601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                if (value == null) {
9752601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                    value = entry.getDescription();
9762601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                }
9772601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setSummary(findInArray(entry.getChoiceEntries(), entry.getChoiceValues(),
9782601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                        value));
9792601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((ListPreference)p).setEntryValues(entry.getChoiceValues());
9802601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((ListPreference)p).setEntries(entry.getChoiceEntries());
9812601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((ListPreference)p).setValue(value);
982e11a346f1fe6adeb183e7dfb622ac6ab40016794Amith Yamasani                ((ListPreference)p).setDialogTitle(entry.getTitle());
9832601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                break;
9842601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            case RestrictionEntry.TYPE_MULTI_SELECT:
9852601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p = new MultiSelectListPreference(context);
9862601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setTitle(entry.getTitle());
9872601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((MultiSelectListPreference)p).setEntryValues(entry.getChoiceValues());
9882601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((MultiSelectListPreference)p).setEntries(entry.getChoiceEntries());
9892601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                HashSet<String> set = new HashSet<String>();
990bc02b84cb5e6405b3052c2e2cc6636bed1d2468bFyodor Kupolov                Collections.addAll(set, entry.getAllSelectedStrings());
9912601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                ((MultiSelectListPreference)p).setValues(set);
992e11a346f1fe6adeb183e7dfb622ac6ab40016794Amith Yamasani                ((MultiSelectListPreference)p).setDialogTitle(entry.getTitle());
9932601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                break;
9942601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            case RestrictionEntry.TYPE_NULL:
9952601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            default:
9962601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            }
9972601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            if (p != null) {
9982601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setPersistent(false);
9992601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setOrder(preference.getOrder() + count);
10002601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                // Store the restrictions key string as a key for the preference
10012601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setKey(preference.getKey().substring(PKG_PREFIX.length()) + DELIMITER
10022601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                        + entry.getKey());
10032601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                mAppList.addPreference(p);
10042601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                p.setOnPreferenceChangeListener(AppRestrictionsFragment.this);
1005247520c369370885a1c085e53ee679dce0fd55ceAmith Yamasani                p.setIcon(R.drawable.empty_icon);
10067eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                preference.mChildren.add(p);
10072601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani                count++;
10082601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani            }
10092601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        }
10102601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani        preference.setRestrictions(restrictions);
10110b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani        if (count == 1 // No visible restrictions
10120b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani                && preference.isImmutable()
10130b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani                && preference.isChecked()) {
10140b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani            // Special case of required app with no visible restrictions. Remove it
10150b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani            mAppList.removePreference(preference);
10160b2781ae537e6d3d27863080eea0a0a5fa6c83b8Amith Yamasani        }
10172601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani    }
10182601cd9142bda1953c1e7b0302f7e0d0f02b0c1bAmith Yamasani
10196e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    /**
10206e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani     * Generates a request code that is stored in a map to retrieve the associated
10216e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani     * AppRestrictionsPreference.
10226e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani     * @param preference
10236e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani     * @return
10246e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani     */
10256e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    private int generateCustomActivityRequestCode(AppRestrictionsPreference preference) {
10266e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        mCustomRequestCode++;
10276e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        mCustomRequestMap.put(mCustomRequestCode, preference);
10286e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        return mCustomRequestCode;
10296e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    }
10306e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
10316e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    @Override
10326e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    public void onActivityResult(int requestCode, int resultCode, Intent data) {
10336e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        super.onActivityResult(requestCode, resultCode, data);
10346e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
10356e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        AppRestrictionsPreference pref = mCustomRequestMap.get(requestCode);
10366e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        if (pref == null) {
10376e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            Log.w(TAG, "Unknown requestCode " + requestCode);
10386e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            return;
10396e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        }
10406e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
10416e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        if (resultCode == Activity.RESULT_OK) {
1042a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            String packageName = pref.getKey().substring(PKG_PREFIX.length());
10436e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            ArrayList<RestrictionEntry> list =
10445ee175051951d3a0bc1533aece69af520c295d37Amith Yamasani                    data.getParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST);
1045a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            Bundle bundle = data.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
10466e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            if (list != null) {
10476e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                // If there's a valid result, persist it to the user manager.
10486e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                pref.setRestrictions(list);
10495ee175051951d3a0bc1533aece69af520c295d37Amith Yamasani                mUserManager.setApplicationRestrictions(packageName,
10502b2ab5a9470ba8df0f18583abc2d12d5942f97ceFyodor Kupolov                        RestrictionsManager.convertRestrictionsToBundle(list), mUser);
1051a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani            } else if (bundle != null) {
1052a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                // If there's a valid result, persist it to the user manager.
1053a98c402e44e1bd74926c55db031d2be0ce7ce7beAmith Yamasani                mUserManager.setApplicationRestrictions(packageName, bundle, mUser);
10546e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            }
10556e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        }
10566e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        // Remove request from the map
10576e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        mCustomRequestMap.remove(requestCode);
10586e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    }
10596e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani
10606e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani    private String findInArray(String[] choiceEntries, String[] choiceValues,
10616e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            String selectedString) {
10626e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        for (int i = 0; i < choiceValues.length; i++) {
10636e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani            if (choiceValues[i].equals(selectedString)) {
10646e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani                return choiceEntries[i];
1065233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
1066233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
10676e4757f0a66bae09149d83102b88a74d824d267dAmith Yamasani        return selectedString;
1068233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
1069233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani
1070233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    @Override
1071233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    public boolean onPreferenceClick(Preference preference) {
1072233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        if (preference.getKey().startsWith(PKG_PREFIX)) {
1073233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            AppRestrictionsPreference arp = (AppRestrictionsPreference) preference;
1074d81a3f73680372ba93a2a26a445d148220c1a521Amith Yamasani            if (!arp.isImmutable()) {
10757eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                final String packageName = arp.getKey().substring(PKG_PREFIX.length());
10767eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                final boolean newEnabledState = !arp.isChecked();
10777eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                arp.setChecked(newEnabledState);
10787eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                mSelectedPackages.put(packageName, newEnabledState);
10797eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                updateAllEntries(arp.getKey(), newEnabledState);
1080cc395695fc869dc8ef8e3c74622f71ef8a421d44Amith Yamasani                mAppListChanged = true;
10817eedcf4a5012fabff69bab08a8efc9146e7607dcAmith Yamasani                applyUserAppState(packageName, newEnabledState);
1082233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            }
1083233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani            return true;
1084233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        }
1085233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani        return false;
1086233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani    }
1087bf3391f19b6f1733825de07d9c602545f8818c64Svetoslav
1088233592bb43c02e88d39d990fadc59fd330a4d3ddAmith Yamasani}
1089