PermissionAppsFragment.java revision 3f07e6589d0f036df10d97f676a375b2ce04ae3b
170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk/*
270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * Copyright (C) 2015 The Android Open Source Project
370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk *
470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * you may not use this file except in compliance with the License.
670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * You may obtain a copy of the License at
770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk *
870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk *
1070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * Unless required by applicable law or agreed to in writing, software
1170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
1270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * See the License for the specific language governing permissions and
1470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk * limitations under the License.
1570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk */
160f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingpackage com.android.packageinstaller.permission.ui.television;
1770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
1870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.app.ActionBar;
1970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.app.AlertDialog;
20265d3c2a0c36251bf8a9f571d7239b6dd404d942Tamas Berghammerimport android.app.Fragment;
2170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.content.Context;
2270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.content.DialogInterface;
2370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.content.DialogInterface.OnClickListener;
2470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.content.Intent;
2570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.graphics.drawable.Drawable;
2670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.os.Bundle;
270f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.support.v14.preference.SwitchPreference;
280f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.support.v4.util.ArrayMap;
290f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.support.v7.preference.Preference;
300f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.support.v7.preference.Preference.OnPreferenceChangeListener;
310f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.support.v7.preference.Preference.OnPreferenceClickListener;
3270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.support.v7.preference.PreferenceScreen;
3370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.util.ArraySet;
340f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport android.view.Menu;
3570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.view.MenuInflater;
3670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.view.MenuItem;
3770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.view.View;
3870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.view.ViewGroup;
3970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.widget.ImageView;
4070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport android.widget.TextView;
4170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
4270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.DeviceUtils;
4370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.R;
4470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.model.AppPermissionGroup;
4570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.model.PermissionApps;
4670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.model.PermissionApps.Callback;
4770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
4870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.ui.OverlayTouchActivity;
4970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.ui.ReviewPermissionsActivity;
5070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monkimport com.android.packageinstaller.permission.utils.LocationUtils;
510f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport com.android.packageinstaller.permission.utils.SafetyNetLogger;
520f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport com.android.packageinstaller.permission.utils.Utils;
530f01c849cd6b546f216f9fac837693fc4a9c5138Doris Ling
540f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport java.util.ArrayList;
550f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingimport java.util.List;
560f01c849cd6b546f216f9fac837693fc4a9c5138Doris Ling
570f01c849cd6b546f216f9fac837693fc4a9c5138Doris Lingpublic final class PermissionAppsFragment extends PermissionsFrameFragment implements Callback,
5870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        OnPreferenceChangeListener {
5970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
6070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private static final int MENU_SHOW_SYSTEM = Menu.FIRST;
6170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 1;
6270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem";
6370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
6470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    public static PermissionAppsFragment newInstance(String permissionName) {
6570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        return setPermissionName(new PermissionAppsFragment(), permissionName);
6670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    }
6770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
6870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) {
6970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        Bundle arguments = new Bundle();
7070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName);
7170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        fragment.setArguments(arguments);
7270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        return fragment;
7370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    }
7470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
7570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private PermissionApps mPermissionApps;
7670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
7770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private PreferenceScreen mExtraScreen;
7870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
7970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private ArrayMap<String, AppPermissionGroup> mToggledGroups;
8070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private ArraySet<String> mLauncherPkgs;
8170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private boolean mHasConfirmedRevoke;
8270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
8370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private boolean mShowSystem;
8470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private MenuItem mShowSystemMenu;
8570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private MenuItem mHideSystemMenu;
8670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
8770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    private Callback mOnPermissionsLoadedListener;
8870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
8970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    @Override
9070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    public void onCreate(Bundle savedInstanceState) {
9170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        super.onCreate(savedInstanceState);
9270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        setLoading(true /* loading */, false /* animate */);
9370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        setHasOptionsMenu(true);
9470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        final ActionBar ab = getActivity().getActionBar();
9570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        if (ab != null) {
9670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk            ab.setDisplayHomeAsUpEnabled(true);
9770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        }
98f20c718f192d680bc4941e544c218c5a204c35f9Jason Monk        mLauncherPkgs = Utils.getLauncherPackages(getContext());
99f20c718f192d680bc4941e544c218c5a204c35f9Jason Monk
100f20c718f192d680bc4941e544c218c5a204c35f9Jason Monk        String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
101f20c718f192d680bc4941e544c218c5a204c35f9Jason Monk        mPermissionApps = new PermissionApps(getActivity(), groupName, this);
102f20c718f192d680bc4941e544c218c5a204c35f9Jason Monk        mPermissionApps.refresh(true);
10370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    }
10470ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
10570ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    @Override
10670ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    public void onResume() {
10770ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        super.onResume();
10870ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        mPermissionApps.refresh(true);
10970ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    }
11070ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk
11170ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    @Override
11270ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
11370ecea22076c53599932f2146bc25ddf3b49c6a6Jason Monk        mShowSystemMenu = menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE,
114                R.string.menu_show_system);
115        mHideSystemMenu = menu.add(Menu.NONE, MENU_HIDE_SYSTEM, Menu.NONE,
116                R.string.menu_hide_system);
117        updateMenu();
118    }
119
120    @Override
121    public boolean onOptionsItemSelected(MenuItem item) {
122        switch (item.getItemId()) {
123            case android.R.id.home:
124                getActivity().finish();
125                return true;
126            case MENU_SHOW_SYSTEM:
127            case MENU_HIDE_SYSTEM:
128                mShowSystem = item.getItemId() == MENU_SHOW_SYSTEM;
129                if (mPermissionApps.getApps() != null) {
130                    onPermissionsLoaded(mPermissionApps);
131                }
132                updateMenu();
133                break;
134        }
135        return super.onOptionsItemSelected(item);
136    }
137
138    private void updateMenu() {
139        mShowSystemMenu.setVisible(!mShowSystem);
140        mHideSystemMenu.setVisible(mShowSystem);
141    }
142
143    @Override
144    protected void onSetEmptyText(TextView textView) {
145        textView.setText(R.string.no_apps);
146    }
147
148    @Override
149    public void onViewCreated(View view, Bundle savedInstanceState) {
150        super.onViewCreated(view, savedInstanceState);
151        bindUi(this, mPermissionApps);
152    }
153
154    private static void bindUi(Fragment fragment, PermissionApps permissionApps) {
155        final Drawable icon = permissionApps.getIcon();
156        final CharSequence label = permissionApps.getLabel();
157        final ActionBar ab = fragment.getActivity().getActionBar();
158        if (ab != null) {
159            ab.setTitle(fragment.getString(R.string.permission_title, label));
160        }
161
162        final ViewGroup rootView = (ViewGroup) fragment.getView();
163        final ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon);
164        if (iconView != null) {
165            // Set the icon as the background instead of the image because ImageView
166            // doesn't properly scale vector drawables beyond their intrinsic size
167            iconView.setBackground(icon);
168        }
169        final TextView titleView = (TextView) rootView.findViewById(R.id.lb_title);
170        if (titleView != null) {
171            titleView.setText(label);
172        }
173        final TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb);
174        if (breadcrumbView != null) {
175            breadcrumbView.setText(R.string.app_permissions);
176        }
177    }
178
179    private void setOnPermissionsLoadedListener(Callback callback) {
180        mOnPermissionsLoadedListener = callback;
181    }
182
183    @Override
184    public void onPermissionsLoaded(PermissionApps permissionApps) {
185        Context context = getPreferenceManager().getContext();
186
187        if (context == null) {
188            return;
189        }
190
191        boolean isTelevision = DeviceUtils.isTelevision(context);
192        PreferenceScreen screen = getPreferenceScreen();
193
194        ArraySet<String> preferencesToRemove = new ArraySet<>();
195        for (int i = 0, n = screen.getPreferenceCount(); i < n; i++) {
196            preferencesToRemove.add(screen.getPreference(i).getKey());
197        }
198        if (mExtraScreen != null) {
199            for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) {
200                preferencesToRemove.add(mExtraScreen.getPreference(i).getKey());
201            }
202        }
203
204        for (PermissionApp app : permissionApps.getApps()) {
205            if (!Utils.shouldShowPermission(app)) {
206                continue;
207            }
208
209            String key = app.getKey();
210            preferencesToRemove.remove(key);
211            Preference existingPref = screen.findPreference(key);
212            if (existingPref == null && mExtraScreen != null) {
213                existingPref = mExtraScreen.findPreference(key);
214            }
215
216            boolean isSystemApp = Utils.isSystem(app, mLauncherPkgs);
217            if (isSystemApp && !isTelevision && !mShowSystem) {
218                if (existingPref != null) {
219                    screen.removePreference(existingPref);
220                }
221                continue;
222            }
223
224            if (existingPref != null) {
225                // If existing preference - only update its state.
226                if (app.isPolicyFixed()) {
227                    existingPref.setSummary(getString(
228                            R.string.permission_summary_enforced_by_policy));
229                }
230                existingPref.setPersistent(false);
231                existingPref.setEnabled(!app.isPolicyFixed());
232                if (existingPref instanceof SwitchPreference) {
233                    ((SwitchPreference) existingPref)
234                            .setChecked(app.areRuntimePermissionsGranted());
235                }
236                continue;
237            }
238
239            SwitchPreference pref = new SwitchPreference(context);
240            pref.setOnPreferenceChangeListener(this);
241            pref.setKey(app.getKey());
242            pref.setIcon(app.getIcon());
243            pref.setTitle(app.getLabel());
244            if (app.isPolicyFixed()) {
245                pref.setSummary(getString(R.string.permission_summary_enforced_by_policy));
246            }
247            pref.setPersistent(false);
248            pref.setEnabled(!app.isPolicyFixed());
249            pref.setChecked(app.areRuntimePermissionsGranted());
250
251            if (isSystemApp && isTelevision) {
252                if (mExtraScreen == null) {
253                    mExtraScreen = getPreferenceManager().createPreferenceScreen(context);
254                }
255                mExtraScreen.addPreference(pref);
256            } else {
257                screen.addPreference(pref);
258            }
259        }
260
261        if (mExtraScreen != null) {
262            preferencesToRemove.remove(KEY_SHOW_SYSTEM_PREFS);
263            Preference pref = screen.findPreference(KEY_SHOW_SYSTEM_PREFS);
264
265            if (pref == null) {
266                pref = new Preference(context);
267                pref.setKey(KEY_SHOW_SYSTEM_PREFS);
268                pref.setIcon(Utils.applyTint(context, R.drawable.ic_toc,
269                        android.R.attr.colorControlNormal));
270                pref.setTitle(R.string.preference_show_system_apps);
271                pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
272                    @Override
273                    public boolean onPreferenceClick(Preference preference) {
274                        SystemAppsFragment frag = new SystemAppsFragment();
275                        setPermissionName(frag, getArguments().getString(
276                                Intent.EXTRA_PERMISSION_NAME));
277                        frag.setTargetFragment(PermissionAppsFragment.this, 0);
278                        getFragmentManager().beginTransaction()
279                            .replace(android.R.id.content, frag)
280                            .addToBackStack("SystemApps")
281                            .commit();
282                        return true;
283                    }
284                });
285                screen.addPreference(pref);
286            }
287
288            int grantedCount = 0;
289            for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) {
290                if (((SwitchPreference) mExtraScreen.getPreference(i)).isChecked()) {
291                    grantedCount++;
292                }
293            }
294            pref.setSummary(getString(R.string.app_permissions_group_summary,
295                    grantedCount, mExtraScreen.getPreferenceCount()));
296        }
297
298        for (String key : preferencesToRemove) {
299            Preference pref = screen.findPreference(key);
300            if (pref != null) {
301                screen.removePreference(pref);
302            } else if (mExtraScreen != null) {
303                pref = mExtraScreen.findPreference(key);
304                if (pref != null) {
305                    mExtraScreen.removePreference(pref);
306                }
307            }
308        }
309
310        setLoading(false /* loading */, true /* animate */);
311
312        if (mOnPermissionsLoadedListener != null) {
313            mOnPermissionsLoadedListener.onPermissionsLoaded(permissionApps);
314        }
315    }
316
317    @Override
318    public boolean onPreferenceChange(final Preference preference, Object newValue) {
319        String pkg = preference.getKey();
320        final PermissionApp app = mPermissionApps.getApp(pkg);
321
322        if (app == null) {
323            return false;
324        }
325
326        if (LocationUtils.isLocationGroupAndProvider(mPermissionApps.getGroupName(),
327                app.getPackageName())) {
328            LocationUtils.showLocationDialog(getContext(), app.getLabel());
329            return false;
330        }
331
332        addToggledGroup(app.getPackageName(), app.getPermissionGroup());
333
334        if (app.isReviewRequired()) {
335            Intent intent = new Intent(getActivity(), ReviewPermissionsActivity.class);
336            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, app.getPackageName());
337            startActivity(intent);
338            return false;
339        }
340
341        if (newValue == Boolean.TRUE) {
342            app.grantRuntimePermissions();
343        } else {
344            final boolean grantedByDefault = app.hasGrantedByDefaultPermissions();
345            if (grantedByDefault || (!app.hasRuntimePermissions() && !mHasConfirmedRevoke)) {
346                new AlertDialog.Builder(getContext())
347                        .setMessage(grantedByDefault ? R.string.system_warning
348                                : R.string.old_sdk_deny_warning)
349                        .setNegativeButton(R.string.cancel, null)
350                        .setPositiveButton(R.string.grant_dialog_button_deny_anyway,
351                                new OnClickListener() {
352                            @Override
353                            public void onClick(DialogInterface dialog, int which) {
354                                ((SwitchPreference) preference).setChecked(false);
355                                app.revokeRuntimePermissions();
356                                if (!grantedByDefault) {
357                                    mHasConfirmedRevoke = true;
358                                }
359                            }
360                        })
361                        .show();
362                return false;
363            } else {
364                app.revokeRuntimePermissions();
365            }
366        }
367        return true;
368    }
369
370    @Override
371    public void onPause() {
372        super.onPause();
373        logToggledGroups();
374    }
375
376    private void addToggledGroup(String packageName, AppPermissionGroup group) {
377        if (mToggledGroups == null) {
378            mToggledGroups = new ArrayMap<>();
379        }
380        // Double toggle is back to initial state.
381        if (mToggledGroups.containsKey(packageName)) {
382            mToggledGroups.remove(packageName);
383        } else {
384            mToggledGroups.put(packageName, group);
385        }
386    }
387
388    private void logToggledGroups() {
389        if (mToggledGroups != null) {
390            final int groupCount = mToggledGroups.size();
391            for (int i = 0; i < groupCount; i++) {
392                String packageName = mToggledGroups.keyAt(i);
393                List<AppPermissionGroup> groups = new ArrayList<>();
394                groups.add(mToggledGroups.valueAt(i));
395                SafetyNetLogger.logPermissionsToggled(packageName, groups);
396            }
397            mToggledGroups = null;
398        }
399    }
400
401    public static class SystemAppsFragment extends PermissionsFrameFragment implements Callback {
402        PermissionAppsFragment mOuterFragment;
403
404        @Override
405        public void onCreate(Bundle savedInstanceState) {
406            mOuterFragment = (PermissionAppsFragment) getTargetFragment();
407            setLoading(true /* loading */, false /* animate */);
408            super.onCreate(savedInstanceState);
409        }
410
411        @Override
412        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
413            if (mOuterFragment.mExtraScreen != null) {
414                setPreferenceScreen();
415            } else {
416                mOuterFragment.setOnPermissionsLoadedListener(this);
417            }
418        }
419
420        @Override
421        public void onViewCreated(View view, Bundle savedInstanceState) {
422            super.onViewCreated(view, savedInstanceState);
423            String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
424            PermissionApps permissionApps = new PermissionApps(getActivity(), groupName, null);
425            bindUi(this, permissionApps);
426        }
427
428        @Override
429        public void onPermissionsLoaded(PermissionApps permissionApps) {
430            setPreferenceScreen();
431            mOuterFragment.setOnPermissionsLoadedListener(null);
432        }
433
434        private void setPreferenceScreen() {
435            setPreferenceScreen(mOuterFragment.mExtraScreen);
436            setLoading(false /* loading */, true /* animate */);
437        }
438    }
439}
440