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