InstalledAppDetails.java revision 584b2b2bc17a4ccf42952b188722de1091c101be
1/** 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 17package com.android.settings.applications; 18 19import android.app.Activity; 20import android.app.ActivityManager; 21import android.app.AlertDialog; 22import android.app.LoaderManager.LoaderCallbacks; 23import android.content.BroadcastReceiver; 24import android.content.ComponentName; 25import android.content.Context; 26import android.content.DialogInterface; 27import android.content.Intent; 28import android.content.Loader; 29import android.content.pm.ApplicationInfo; 30import android.content.pm.PackageInfo; 31import android.content.pm.PackageManager; 32import android.content.pm.PackageManager.NameNotFoundException; 33import android.content.pm.ResolveInfo; 34import android.net.INetworkStatsService; 35import android.net.INetworkStatsSession; 36import android.net.NetworkTemplate; 37import android.net.TrafficStats; 38import android.net.Uri; 39import android.os.AsyncTask; 40import android.os.Bundle; 41import android.os.RemoteException; 42import android.os.ServiceManager; 43import android.os.UserHandle; 44import android.preference.Preference; 45import android.preference.Preference.OnPreferenceClickListener; 46import android.provider.Settings; 47import android.text.format.DateUtils; 48import android.text.format.Formatter; 49import android.view.Menu; 50import android.view.MenuInflater; 51import android.view.MenuItem; 52import android.view.View; 53import android.widget.Button; 54import android.widget.ImageView; 55import android.widget.TextView; 56 57import com.android.settings.DataUsageSummary; 58import com.android.settings.DataUsageSummary.AppItem; 59import com.android.settings.R; 60import com.android.settings.SettingsActivity; 61import com.android.settings.Utils; 62import com.android.settings.applications.ApplicationsState.AppEntry; 63import com.android.settings.net.ChartData; 64import com.android.settings.net.ChartDataLoader; 65import com.android.settings.notification.NotificationBackend; 66import com.android.settings.notification.NotificationBackend.AppRow; 67 68import java.lang.ref.WeakReference; 69import java.util.ArrayList; 70import java.util.HashSet; 71import java.util.List; 72 73/** 74 * Activity to display application information from Settings. This activity presents 75 * extended information associated with a package like code, data, total size, permissions 76 * used by the application and also the set of default launchable activities. 77 * For system applications, an option to clear user data is displayed only if data size is > 0. 78 * System applications that do not want clear user data do not have this option. 79 * For non-system applications, there is no option to clear data. Instead there is an option to 80 * uninstall the application. 81 */ 82public class InstalledAppDetails extends AppInfoBase 83 implements View.OnClickListener, OnPreferenceClickListener { 84 85 // Menu identifiers 86 public static final int UNINSTALL_ALL_USERS_MENU = 1; 87 public static final int UNINSTALL_UPDATES = 2; 88 89 // Result code identifiers 90 public static final int REQUEST_UNINSTALL = 0; 91 private static final int SUB_INFO_FRAGMENT = 1; 92 93 private static final int LOADER_CHART_DATA = 2; 94 95 private static final int DLG_FORCE_STOP = DLG_BASE + 1; 96 private static final int DLG_DISABLE = DLG_BASE + 2; 97 private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3; 98 private static final int DLG_FACTORY_RESET = DLG_BASE + 4; 99 100 private static final String KEY_HEADER = "header_view"; 101 private static final String KEY_NOTIFICATION = "notification_settings"; 102 private static final String KEY_STORAGE = "storage_settings"; 103 private static final String KEY_PERMISSION = "permission_settings"; 104 private static final String KEY_DATA = "data_settings"; 105 private static final String KEY_LAUNCH = "preferred_settings"; 106 107 private final HashSet<String> mHomePackages = new HashSet<String>(); 108 109 private boolean mInitialized; 110 private boolean mShowUninstalled; 111 private LayoutPreference mHeader; 112 private Button mUninstallButton; 113 private boolean mUpdatedSysApp = false; 114 private TextView mAppVersion; 115 private Button mForceStopButton; 116 private Preference mNotificationPreference; 117 private Preference mStoragePreference; 118 private Preference mPermissionsPreference; 119 private Preference mLaunchPreference; 120 private Preference mDataPreference; 121 122 private boolean mDisableAfterUninstall; 123 // Used for updating notification preference. 124 private final NotificationBackend mBackend = new NotificationBackend(); 125 126 private ChartData mChartData; 127 private INetworkStatsSession mStatsSession; 128 129 private boolean handleDisableable(Button button) { 130 boolean disableable = false; 131 // Try to prevent the user from bricking their phone 132 // by not allowing disabling of apps signed with the 133 // system cert and any launcher app in the system. 134 if (mHomePackages.contains(mAppEntry.info.packageName) 135 || Utils.isSystemPackage(mPm, mPackageInfo)) { 136 // Disable button for core system applications. 137 button.setText(R.string.disable_text); 138 } else if (mAppEntry.info.enabled) { 139 button.setText(R.string.disable_text); 140 disableable = true; 141 } else { 142 button.setText(R.string.enable_text); 143 disableable = true; 144 } 145 146 return disableable; 147 } 148 149 private void initUninstallButtons() { 150 final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 151 boolean enabled = true; 152 if (isBundled) { 153 enabled = handleDisableable(mUninstallButton); 154 } else { 155 if ((mPackageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0 156 && mUserManager.getUsers().size() >= 2) { 157 // When we have multiple users, there is a separate menu 158 // to uninstall for all users. 159 enabled = false; 160 } 161 mUninstallButton.setText(R.string.uninstall_text); 162 } 163 // If this is a device admin, it can't be uninstalled or disabled. 164 // We do this here so the text of the button is still set correctly. 165 if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { 166 enabled = false; 167 } 168 169 // Home apps need special handling. Bundled ones we don't risk downgrading 170 // because that can interfere with home-key resolution. Furthermore, we 171 // can't allow uninstallation of the only home app, and we don't want to 172 // allow uninstallation of an explicitly preferred one -- the user can go 173 // to Home settings and pick a different one, after which we'll permit 174 // uninstallation of the now-not-default one. 175 if (enabled && mHomePackages.contains(mPackageInfo.packageName)) { 176 if (isBundled) { 177 enabled = false; 178 } else { 179 ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>(); 180 ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities); 181 if (currentDefaultHome == null) { 182 // No preferred default, so permit uninstall only when 183 // there is more than one candidate 184 enabled = (mHomePackages.size() > 1); 185 } else { 186 // There is an explicit default home app -- forbid uninstall of 187 // that one, but permit it for installed-but-inactive ones. 188 enabled = !mPackageInfo.packageName.equals(currentDefaultHome.getPackageName()); 189 } 190 } 191 } 192 193 if (mAppControlRestricted) { 194 enabled = false; 195 } 196 197 mUninstallButton.setEnabled(enabled); 198 if (enabled) { 199 // Register listener 200 mUninstallButton.setOnClickListener(this); 201 } 202 } 203 204 /** Called when the activity is first created. */ 205 @Override 206 public void onCreate(Bundle icicle) { 207 super.onCreate(icicle); 208 209 setHasOptionsMenu(true); 210 addPreferencesFromResource(R.xml.installed_app_details); 211 212 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( 213 ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); 214 try { 215 mStatsSession = statsService.openSession(); 216 } catch (RemoteException e) { 217 throw new RuntimeException(e); 218 } 219 } 220 221 @Override 222 public void onResume() { 223 super.onResume(); 224 AppItem app = new AppItem(mAppEntry.info.uid); 225 app.addUid(mAppEntry.info.uid); 226 getLoaderManager().restartLoader(LOADER_CHART_DATA, 227 ChartDataLoader.buildArgs(NetworkTemplate.buildTemplateMobileWildcard(), app), 228 mDataCallbacks); 229 } 230 231 @Override 232 public void onPause() { 233 getLoaderManager().destroyLoader(LOADER_CHART_DATA); 234 super.onPause(); 235 } 236 237 @Override 238 public void onDestroy() { 239 TrafficStats.closeQuietly(mStatsSession); 240 241 super.onDestroy(); 242 } 243 244 public void onActivityCreated(Bundle savedInstanceState) { 245 super.onActivityCreated(savedInstanceState); 246 handleHeader(); 247 248 mNotificationPreference = findPreference(KEY_NOTIFICATION); 249 mNotificationPreference.setOnPreferenceClickListener(this); 250 mStoragePreference = findPreference(KEY_STORAGE); 251 mStoragePreference.setOnPreferenceClickListener(this); 252 mPermissionsPreference = findPreference(KEY_PERMISSION); 253 mPermissionsPreference.setOnPreferenceClickListener(this); 254 mLaunchPreference = findPreference(KEY_LAUNCH); 255 mLaunchPreference.setOnPreferenceClickListener(this); 256 mDataPreference = findPreference(KEY_DATA); 257 mDataPreference.setOnPreferenceClickListener(this); 258 } 259 260 private void handleHeader() { 261 mHeader = (LayoutPreference) findPreference(KEY_HEADER); 262 263 // Get Control button panel 264 View btnPanel = mHeader.findViewById(R.id.control_buttons_panel); 265 mForceStopButton = (Button) btnPanel.findViewById(R.id.right_button); 266 mForceStopButton.setText(R.string.force_stop); 267 mUninstallButton = (Button) btnPanel.findViewById(R.id.left_button); 268 mForceStopButton.setEnabled(false); 269 } 270 271 @Override 272 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 273 menu.add(0, UNINSTALL_UPDATES, 0, R.string.app_factory_reset) 274 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 275 menu.add(0, UNINSTALL_ALL_USERS_MENU, 1, R.string.uninstall_all_users_text) 276 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 277 } 278 279 @Override 280 public void onPrepareOptionsMenu(Menu menu) { 281 boolean showIt = true; 282 if (mUpdatedSysApp) { 283 showIt = false; 284 } else if (mAppEntry == null) { 285 showIt = false; 286 } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 287 showIt = false; 288 } else if (mPackageInfo == null || mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { 289 showIt = false; 290 } else if (UserHandle.myUserId() != 0) { 291 showIt = false; 292 } else if (mUserManager.getUsers().size() < 2) { 293 showIt = false; 294 } 295 menu.findItem(UNINSTALL_ALL_USERS_MENU).setVisible(showIt); 296 mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; 297 menu.findItem(UNINSTALL_UPDATES).setVisible(mUpdatedSysApp && !mAppControlRestricted); 298 } 299 300 @Override 301 public boolean onOptionsItemSelected(MenuItem item) { 302 switch (item.getItemId()) { 303 case UNINSTALL_ALL_USERS_MENU: 304 uninstallPkg(mAppEntry.info.packageName, true, false); 305 return true; 306 case UNINSTALL_UPDATES: 307 showDialogInner(DLG_FACTORY_RESET, 0); 308 return true; 309 } 310 return false; 311 } 312 313 @Override 314 public void onActivityResult(int requestCode, int resultCode, Intent data) { 315 super.onActivityResult(requestCode, resultCode, data); 316 if (requestCode == REQUEST_UNINSTALL) { 317 if (mDisableAfterUninstall) { 318 mDisableAfterUninstall = false; 319 try { 320 ApplicationInfo ainfo = getActivity().getPackageManager().getApplicationInfo( 321 mAppEntry.info.packageName, PackageManager.GET_UNINSTALLED_PACKAGES 322 | PackageManager.GET_DISABLED_COMPONENTS); 323 if ((ainfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) { 324 new DisableChanger(this, mAppEntry.info, 325 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) 326 .execute((Object)null); 327 } 328 } catch (NameNotFoundException e) { 329 } 330 } 331 if (!refreshUi()) { 332 setIntentAndFinish(true, true); 333 } 334 } 335 } 336 337 // Utility method to set application label and icon. 338 private void setAppLabelAndIcon(PackageInfo pkgInfo) { 339 final View appSnippet = mHeader.findViewById(R.id.app_snippet); 340 appSnippet.setPaddingRelative(0, appSnippet.getPaddingTop(), 0, 341 appSnippet.getPaddingBottom()); 342 343 ImageView icon = (ImageView) appSnippet.findViewById(R.id.app_icon); 344 mState.ensureIcon(mAppEntry); 345 icon.setImageDrawable(mAppEntry.icon); 346 // Set application name. 347 TextView label = (TextView) appSnippet.findViewById(R.id.app_name); 348 label.setText(mAppEntry.label); 349 // Version number of application 350 mAppVersion = (TextView) appSnippet.findViewById(R.id.app_size); 351 352 if (pkgInfo != null && pkgInfo.versionName != null) { 353 mAppVersion.setVisibility(View.VISIBLE); 354 mAppVersion.setText(getActivity().getString(R.string.version_text, 355 String.valueOf(pkgInfo.versionName))); 356 } else { 357 mAppVersion.setVisibility(View.INVISIBLE); 358 } 359 } 360 361 private boolean signaturesMatch(String pkg1, String pkg2) { 362 if (pkg1 != null && pkg2 != null) { 363 try { 364 final int match = mPm.checkSignatures(pkg1, pkg2); 365 if (match >= PackageManager.SIGNATURE_MATCH) { 366 return true; 367 } 368 } catch (Exception e) { 369 // e.g. named alternate package not found during lookup; 370 // this is an expected case sometimes 371 } 372 } 373 return false; 374 } 375 376 @Override 377 protected boolean refreshUi() { 378 retrieveAppEntry(); 379 if (mAppEntry == null) { 380 return false; // onCreate must have failed, make sure to exit 381 } 382 383 if (mPackageInfo == null) { 384 return false; // onCreate must have failed, make sure to exit 385 } 386 387 // Get list of "home" apps and trace through any meta-data references 388 List<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>(); 389 mPm.getHomeActivities(homeActivities); 390 mHomePackages.clear(); 391 for (int i = 0; i< homeActivities.size(); i++) { 392 ResolveInfo ri = homeActivities.get(i); 393 final String activityPkg = ri.activityInfo.packageName; 394 mHomePackages.add(activityPkg); 395 396 // Also make sure to include anything proxying for the home app 397 final Bundle metadata = ri.activityInfo.metaData; 398 if (metadata != null) { 399 final String metaPkg = metadata.getString(ActivityManager.META_HOME_ALTERNATE); 400 if (signaturesMatch(metaPkg, activityPkg)) { 401 mHomePackages.add(metaPkg); 402 } 403 } 404 } 405 406 checkForceStop(); 407 setAppLabelAndIcon(mPackageInfo); 408 initUninstallButtons(); 409 410 // Update the preference summaries. 411 Activity context = getActivity(); 412 mStoragePreference.setSummary(AppStorageSettings.getSummary(mAppEntry, context)); 413 mPermissionsPreference.setSummary(AppPermissionSettings.getSummary(mAppEntry, context)); 414 mLaunchPreference.setSummary(AppLaunchSettings.getSummary(mAppEntry, mUsbManager, 415 mPm, context)); 416 mNotificationPreference.setSummary(getNotificationSummary(mAppEntry, context, 417 mBackend)); 418 mDataPreference.setSummary(getDataSummary()); 419 420 if (!mInitialized) { 421 // First time init: are we displaying an uninstalled app? 422 mInitialized = true; 423 mShowUninstalled = (mAppEntry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0; 424 } else { 425 // All other times: if the app no longer exists then we want 426 // to go away. 427 try { 428 ApplicationInfo ainfo = context.getPackageManager().getApplicationInfo( 429 mAppEntry.info.packageName, PackageManager.GET_UNINSTALLED_PACKAGES 430 | PackageManager.GET_DISABLED_COMPONENTS); 431 if (!mShowUninstalled) { 432 // If we did not start out with the app uninstalled, then 433 // it transitioning to the uninstalled state for the current 434 // user means we should go away as well. 435 return (ainfo.flags&ApplicationInfo.FLAG_INSTALLED) != 0; 436 } 437 } catch (NameNotFoundException e) { 438 return false; 439 } 440 } 441 442 return true; 443 } 444 445 private CharSequence getDataSummary() { 446 if (mChartData != null) { 447 long totalBytes = mChartData.detail.getTotalBytes(); 448 Context context = getActivity(); 449 return getString(R.string.data_summary_format, 450 Formatter.formatFileSize(context, totalBytes), 451 DateUtils.formatDateTime(context, mChartData.detail.getStart(), 452 DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH)); 453 } 454 return getString(R.string.computing_size); 455 } 456 457 @Override 458 protected AlertDialog createDialog(int id, int errorCode) { 459 switch (id) { 460 case DLG_DISABLE: 461 return new AlertDialog.Builder(getActivity()) 462 .setTitle(getActivity().getText(R.string.app_disable_dlg_title)) 463 .setMessage(getActivity().getText(R.string.app_disable_dlg_text)) 464 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 465 public void onClick(DialogInterface dialog, int which) { 466 // Disable the app 467 new DisableChanger(InstalledAppDetails.this, mAppEntry.info, 468 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) 469 .execute((Object)null); 470 } 471 }) 472 .setNegativeButton(R.string.dlg_cancel, null) 473 .create(); 474 case DLG_SPECIAL_DISABLE: 475 return new AlertDialog.Builder(getActivity()) 476 .setTitle(getActivity().getText(R.string.app_special_disable_dlg_title)) 477 .setMessage(getActivity().getText(R.string.app_special_disable_dlg_text)) 478 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 479 public void onClick(DialogInterface dialog, int which) { 480 // Clear user data here 481 uninstallPkg(mAppEntry.info.packageName, 482 false, true); 483 } 484 }) 485 .setNegativeButton(R.string.dlg_cancel, null) 486 .create(); 487 case DLG_FORCE_STOP: 488 return new AlertDialog.Builder(getActivity()) 489 .setTitle(getActivity().getText(R.string.force_stop_dlg_title)) 490 .setMessage(getActivity().getText(R.string.force_stop_dlg_text)) 491 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 492 public void onClick(DialogInterface dialog, int which) { 493 // Force stop 494 forceStopPackage(mAppEntry.info.packageName); 495 } 496 }) 497 .setNegativeButton(R.string.dlg_cancel, null) 498 .create(); 499 case DLG_FACTORY_RESET: 500 return new AlertDialog.Builder(getActivity()) 501 .setTitle(getActivity().getText(R.string.app_factory_reset_dlg_title)) 502 .setMessage(getActivity().getText(R.string.app_factory_reset_dlg_text)) 503 .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 504 public void onClick(DialogInterface dialog, int which) { 505 // Clear user data here 506 uninstallPkg(mAppEntry.info.packageName, 507 false, false); 508 } 509 }) 510 .setNegativeButton(R.string.dlg_cancel, null) 511 .create(); 512 } 513 return null; 514 } 515 516 private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) { 517 // Create new intent to launch Uninstaller activity 518 Uri packageURI = Uri.parse("package:"+packageName); 519 Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI); 520 uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers); 521 startActivityForResult(uninstallIntent, REQUEST_UNINSTALL); 522 mDisableAfterUninstall = andDisable; 523 } 524 525 private void forceStopPackage(String pkgName) { 526 ActivityManager am = (ActivityManager)getActivity().getSystemService( 527 Context.ACTIVITY_SERVICE); 528 am.forceStopPackage(pkgName); 529 int userId = UserHandle.getUserId(mAppEntry.info.uid); 530 mState.invalidatePackage(pkgName, userId); 531 ApplicationsState.AppEntry newEnt = mState.getEntry(pkgName, userId); 532 if (newEnt != null) { 533 mAppEntry = newEnt; 534 } 535 checkForceStop(); 536 } 537 538 private void updateForceStopButton(boolean enabled) { 539 if (mAppControlRestricted) { 540 mForceStopButton.setEnabled(false); 541 } else { 542 mForceStopButton.setEnabled(enabled); 543 mForceStopButton.setOnClickListener(InstalledAppDetails.this); 544 } 545 } 546 547 private void checkForceStop() { 548 if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { 549 // User can't force stop device admin. 550 updateForceStopButton(false); 551 } else if ((mAppEntry.info.flags&ApplicationInfo.FLAG_STOPPED) == 0) { 552 // If the app isn't explicitly stopped, then always show the 553 // force stop button. 554 updateForceStopButton(true); 555 } else { 556 Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART, 557 Uri.fromParts("package", mAppEntry.info.packageName, null)); 558 intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mAppEntry.info.packageName }); 559 intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid); 560 intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid)); 561 getActivity().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, 562 mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null); 563 } 564 } 565 566 private void startAppInfoFragment(Class<? extends AppInfoBase> fragment, CharSequence title) { 567 // start new fragment to display extended information 568 Bundle args = new Bundle(); 569 args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mAppEntry.info.packageName); 570 571 SettingsActivity sa = (SettingsActivity) getActivity(); 572 sa.startPreferencePanel(fragment.getName(), args, -1, title, this, SUB_INFO_FRAGMENT); 573 } 574 575 private void startNotifications() { 576 // start new fragment to display extended information 577 getActivity().startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) 578 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 579 .putExtra(Settings.EXTRA_APP_PACKAGE, mAppEntry.info.packageName) 580 .putExtra(Settings.EXTRA_APP_UID, mAppEntry.info.uid)); 581 } 582 583 /* 584 * Method implementing functionality of buttons clicked 585 * @see android.view.View.OnClickListener#onClick(android.view.View) 586 */ 587 public void onClick(View v) { 588 String packageName = mAppEntry.info.packageName; 589 if(v == mUninstallButton) { 590 if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 591 if (mAppEntry.info.enabled) { 592 if (mUpdatedSysApp) { 593 showDialogInner(DLG_SPECIAL_DISABLE, 0); 594 } else { 595 showDialogInner(DLG_DISABLE, 0); 596 } 597 } else { 598 new DisableChanger(this, mAppEntry.info, 599 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) 600 .execute((Object) null); 601 } 602 } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { 603 uninstallPkg(packageName, true, false); 604 } else { 605 uninstallPkg(packageName, false, false); 606 } 607 } else if (v == mForceStopButton) { 608 showDialogInner(DLG_FORCE_STOP, 0); 609 //forceStopPackage(mAppInfo.packageName); 610 } 611 } 612 613 @Override 614 public boolean onPreferenceClick(Preference preference) { 615 if (preference == mStoragePreference) { 616 startAppInfoFragment(AppStorageSettings.class, mStoragePreference.getTitle()); 617 } else if (preference == mNotificationPreference) { 618 startNotifications(); 619 } else if (preference == mPermissionsPreference) { 620 startAppInfoFragment(AppPermissionSettings.class, mPermissionsPreference.getTitle()); 621 } else if (preference == mLaunchPreference) { 622 startAppInfoFragment(AppLaunchSettings.class, mLaunchPreference.getTitle()); 623 } else if (preference == mDataPreference) { 624 Bundle args = new Bundle(); 625 args.putString(DataUsageSummary.EXTRA_SHOW_APP_IMMEDIATE_PKG, 626 mAppEntry.info.packageName); 627 628 SettingsActivity sa = (SettingsActivity) getActivity(); 629 sa.startPreferencePanel(DataUsageSummary.class.getName(), args, -1, 630 getString(R.string.app_data_usage), this, SUB_INFO_FRAGMENT); 631 } else { 632 return false; 633 } 634 return true; 635 } 636 637 public static CharSequence getNotificationSummary(AppEntry appEntry, Context context) { 638 return getNotificationSummary(appEntry, context, new NotificationBackend()); 639 } 640 641 public static CharSequence getNotificationSummary(AppEntry appEntry, Context context, 642 NotificationBackend backend) { 643 AppRow appRow = backend.loadAppRow(context.getPackageManager(), appEntry.info); 644 return getNotificationSummary(appRow, context); 645 } 646 647 public static CharSequence getNotificationSummary(AppRow appRow, Context context) { 648 if (appRow.banned) { 649 return context.getString(R.string.notifications_disabled); 650 } else if (appRow.priority) { 651 if (appRow.sensitive) { 652 return context.getString(R.string.notifications_priority_sensitive); 653 } 654 return context.getString(R.string.notifications_priority); 655 } else if (appRow.sensitive) { 656 return context.getString(R.string.notifications_sensitive); 657 } 658 return context.getString(R.string.notifications_enabled); 659 } 660 661 static class DisableChanger extends AsyncTask<Object, Object, Object> { 662 final PackageManager mPm; 663 final WeakReference<InstalledAppDetails> mActivity; 664 final ApplicationInfo mInfo; 665 final int mState; 666 667 DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) { 668 mPm = activity.mPm; 669 mActivity = new WeakReference<InstalledAppDetails>(activity); 670 mInfo = info; 671 mState = state; 672 } 673 674 @Override 675 protected Object doInBackground(Object... params) { 676 mPm.setApplicationEnabledSetting(mInfo.packageName, mState, 0); 677 return null; 678 } 679 } 680 681 private final LoaderCallbacks<ChartData> mDataCallbacks = new LoaderCallbacks<ChartData>() { 682 683 @Override 684 public Loader<ChartData> onCreateLoader(int id, Bundle args) { 685 return new ChartDataLoader(getActivity(), mStatsSession, args); 686 } 687 688 @Override 689 public void onLoadFinished(Loader<ChartData> loader, ChartData data) { 690 mChartData = data; 691 mDataPreference.setSummary(getDataSummary()); 692 } 693 694 @Override 695 public void onLoaderReset(Loader<ChartData> loader) { 696 mChartData = null; 697 mDataPreference.setSummary(getDataSummary()); 698 } 699 }; 700 701 private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() { 702 @Override 703 public void onReceive(Context context, Intent intent) { 704 updateForceStopButton(getResultCode() != Activity.RESULT_CANCELED); 705 } 706 }; 707} 708 709 710