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