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