Home | History | Annotate | Download | only in applications
      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 
     17 package com.android.settings.applications;
     18 
     19 import com.android.settings.R;
     20 import com.android.settings.Utils;
     21 import com.android.settings.applications.ApplicationsState.AppEntry;
     22 
     23 import android.app.Activity;
     24 import android.app.ActivityManager;
     25 import android.app.AlertDialog;
     26 import android.app.Dialog;
     27 import android.app.DialogFragment;
     28 import android.app.Fragment;
     29 import android.app.INotificationManager;
     30 import android.app.admin.DevicePolicyManager;
     31 import android.appwidget.AppWidgetManager;
     32 import android.content.BroadcastReceiver;
     33 import android.content.ComponentName;
     34 import android.content.Context;
     35 import android.content.DialogInterface;
     36 import android.content.Intent;
     37 import android.content.IntentFilter;
     38 import android.content.pm.ApplicationInfo;
     39 import android.content.pm.IPackageDataObserver;
     40 import android.content.pm.IPackageMoveObserver;
     41 import android.content.pm.PackageInfo;
     42 import android.content.pm.PackageManager;
     43 import android.content.pm.ResolveInfo;
     44 import android.content.pm.PackageManager.NameNotFoundException;
     45 import android.content.res.Resources;
     46 import android.hardware.usb.IUsbManager;
     47 import android.net.Uri;
     48 import android.os.AsyncTask;
     49 import android.os.Bundle;
     50 import android.os.Environment;
     51 import android.os.Handler;
     52 import android.os.IBinder;
     53 import android.os.Message;
     54 import android.os.RemoteException;
     55 import android.os.ServiceManager;
     56 import android.preference.PreferenceActivity;
     57 import android.text.SpannableString;
     58 import android.text.TextUtils;
     59 import android.text.format.Formatter;
     60 import android.text.style.BulletSpan;
     61 import android.util.Log;
     62 
     63 import java.lang.ref.WeakReference;
     64 import java.util.ArrayList;
     65 import java.util.List;
     66 import android.view.LayoutInflater;
     67 import android.view.View;
     68 import android.view.ViewGroup;
     69 import android.widget.AppSecurityPermissions;
     70 import android.widget.Button;
     71 import android.widget.CheckBox;
     72 import android.widget.CompoundButton;
     73 import android.widget.ImageView;
     74 import android.widget.LinearLayout;
     75 import android.widget.TextView;
     76 
     77 /**
     78  * Activity to display application information from Settings. This activity presents
     79  * extended information associated with a package like code, data, total size, permissions
     80  * used by the application and also the set of default launchable activities.
     81  * For system applications, an option to clear user data is displayed only if data size is > 0.
     82  * System applications that do not want clear user data do not have this option.
     83  * For non-system applications, there is no option to clear data. Instead there is an option to
     84  * uninstall the application.
     85  */
     86 public class InstalledAppDetails extends Fragment
     87         implements View.OnClickListener, CompoundButton.OnCheckedChangeListener,
     88         ApplicationsState.Callbacks {
     89     private static final String TAG="InstalledAppDetails";
     90     static final boolean SUPPORT_DISABLE_APPS = true;
     91     private static final boolean localLOGV = false;
     92 
     93     public static final String ARG_PACKAGE_NAME = "package";
     94 
     95     private PackageManager mPm;
     96     private IUsbManager mUsbManager;
     97     private AppWidgetManager mAppWidgetManager;
     98     private DevicePolicyManager mDpm;
     99     private ApplicationsState mState;
    100     private ApplicationsState.Session mSession;
    101     private ApplicationsState.AppEntry mAppEntry;
    102     private PackageInfo mPackageInfo;
    103     private CanBeOnSdCardChecker mCanBeOnSdCardChecker;
    104     private View mRootView;
    105     private Button mUninstallButton;
    106     private boolean mMoveInProgress = false;
    107     private boolean mUpdatedSysApp = false;
    108     private Button mActivitiesButton;
    109     private View mScreenCompatSection;
    110     private CheckBox mAskCompatibilityCB;
    111     private CheckBox mEnableCompatibilityCB;
    112     private boolean mCanClearData = true;
    113     private TextView mAppVersion;
    114     private TextView mTotalSize;
    115     private TextView mAppSize;
    116     private TextView mDataSize;
    117     private TextView mExternalCodeSize;
    118     private TextView mExternalDataSize;
    119     private ClearUserDataObserver mClearDataObserver;
    120     // Views related to cache info
    121     private TextView mCacheSize;
    122     private Button mClearCacheButton;
    123     private ClearCacheObserver mClearCacheObserver;
    124     private Button mForceStopButton;
    125     private Button mClearDataButton;
    126     private Button mMoveAppButton;
    127     private CompoundButton mNotificationSwitch;
    128 
    129     private PackageMoveObserver mPackageMoveObserver;
    130 
    131     private boolean mHaveSizes = false;
    132     private long mLastCodeSize = -1;
    133     private long mLastDataSize = -1;
    134     private long mLastExternalCodeSize = -1;
    135     private long mLastExternalDataSize = -1;
    136     private long mLastCacheSize = -1;
    137     private long mLastTotalSize = -1;
    138 
    139     //internal constants used in Handler
    140     private static final int OP_SUCCESSFUL = 1;
    141     private static final int OP_FAILED = 2;
    142     private static final int CLEAR_USER_DATA = 1;
    143     private static final int CLEAR_CACHE = 3;
    144     private static final int PACKAGE_MOVE = 4;
    145 
    146     // invalid size value used initially and also when size retrieval through PackageManager
    147     // fails for whatever reason
    148     private static final int SIZE_INVALID = -1;
    149 
    150     // Resource strings
    151     private CharSequence mInvalidSizeStr;
    152     private CharSequence mComputingStr;
    153 
    154     // Dialog identifiers used in showDialog
    155     private static final int DLG_BASE = 0;
    156     private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
    157     private static final int DLG_FACTORY_RESET = DLG_BASE + 2;
    158     private static final int DLG_APP_NOT_FOUND = DLG_BASE + 3;
    159     private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 4;
    160     private static final int DLG_FORCE_STOP = DLG_BASE + 5;
    161     private static final int DLG_MOVE_FAILED = DLG_BASE + 6;
    162     private static final int DLG_DISABLE = DLG_BASE + 7;
    163     private static final int DLG_DISABLE_NOTIFICATIONS = DLG_BASE + 8;
    164 
    165     private Handler mHandler = new Handler() {
    166         public void handleMessage(Message msg) {
    167             // If the fragment is gone, don't process any more messages.
    168             if (getView() == null) {
    169                 return;
    170             }
    171             switch (msg.what) {
    172                 case CLEAR_USER_DATA:
    173                     processClearMsg(msg);
    174                     break;
    175                 case CLEAR_CACHE:
    176                     // Refresh size info
    177                     mState.requestSize(mAppEntry.info.packageName);
    178                     break;
    179                 case PACKAGE_MOVE:
    180                     processMoveMsg(msg);
    181                     break;
    182                 default:
    183                     break;
    184             }
    185         }
    186     };
    187 
    188     class ClearUserDataObserver extends IPackageDataObserver.Stub {
    189        public void onRemoveCompleted(final String packageName, final boolean succeeded) {
    190            final Message msg = mHandler.obtainMessage(CLEAR_USER_DATA);
    191            msg.arg1 = succeeded?OP_SUCCESSFUL:OP_FAILED;
    192            mHandler.sendMessage(msg);
    193         }
    194     }
    195 
    196     class ClearCacheObserver extends IPackageDataObserver.Stub {
    197         public void onRemoveCompleted(final String packageName, final boolean succeeded) {
    198             final Message msg = mHandler.obtainMessage(CLEAR_CACHE);
    199             msg.arg1 = succeeded ? OP_SUCCESSFUL:OP_FAILED;
    200             mHandler.sendMessage(msg);
    201          }
    202      }
    203 
    204     class PackageMoveObserver extends IPackageMoveObserver.Stub {
    205         public void packageMoved(String packageName, int returnCode) throws RemoteException {
    206             final Message msg = mHandler.obtainMessage(PACKAGE_MOVE);
    207             msg.arg1 = returnCode;
    208             mHandler.sendMessage(msg);
    209         }
    210     }
    211 
    212     private String getSizeStr(long size) {
    213         if (size == SIZE_INVALID) {
    214             return mInvalidSizeStr.toString();
    215         }
    216         return Formatter.formatFileSize(getActivity(), size);
    217     }
    218 
    219     private void initDataButtons() {
    220         if ((mAppEntry.info.flags&(ApplicationInfo.FLAG_SYSTEM
    221                 | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA))
    222                 == ApplicationInfo.FLAG_SYSTEM
    223                 || mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
    224             mClearDataButton.setText(R.string.clear_user_data_text);
    225             mClearDataButton.setEnabled(false);
    226             mCanClearData = false;
    227         } else {
    228             if (mAppEntry.info.manageSpaceActivityName != null) {
    229                 mClearDataButton.setText(R.string.manage_space_text);
    230             } else {
    231                 mClearDataButton.setText(R.string.clear_user_data_text);
    232             }
    233             mClearDataButton.setOnClickListener(this);
    234         }
    235     }
    236 
    237     private CharSequence getMoveErrMsg(int errCode) {
    238         switch (errCode) {
    239             case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
    240                 return getActivity().getString(R.string.insufficient_storage);
    241             case PackageManager.MOVE_FAILED_DOESNT_EXIST:
    242                 return getActivity().getString(R.string.does_not_exist);
    243             case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
    244                 return getActivity().getString(R.string.app_forward_locked);
    245             case PackageManager.MOVE_FAILED_INVALID_LOCATION:
    246                 return getActivity().getString(R.string.invalid_location);
    247             case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
    248                 return getActivity().getString(R.string.system_package);
    249             case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
    250                 return "";
    251         }
    252         return "";
    253     }
    254 
    255     private void initMoveButton() {
    256         if (Environment.isExternalStorageEmulated()) {
    257             mMoveAppButton.setVisibility(View.INVISIBLE);
    258             return;
    259         }
    260         boolean dataOnly = false;
    261         dataOnly = (mPackageInfo == null) && (mAppEntry != null);
    262         boolean moveDisable = true;
    263         if (dataOnly) {
    264             mMoveAppButton.setText(R.string.move_app);
    265         } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
    266             mMoveAppButton.setText(R.string.move_app_to_internal);
    267             // Always let apps move to internal storage from sdcard.
    268             moveDisable = false;
    269         } else {
    270             mMoveAppButton.setText(R.string.move_app_to_sdcard);
    271             mCanBeOnSdCardChecker.init();
    272             moveDisable = !mCanBeOnSdCardChecker.check(mAppEntry.info);
    273         }
    274         if (moveDisable) {
    275             mMoveAppButton.setEnabled(false);
    276         } else {
    277             mMoveAppButton.setOnClickListener(this);
    278             mMoveAppButton.setEnabled(true);
    279         }
    280     }
    281 
    282     private boolean isThisASystemPackage() {
    283         try {
    284             PackageInfo sys = mPm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
    285             return (mPackageInfo != null && mPackageInfo.signatures != null &&
    286                     sys.signatures[0].equals(mPackageInfo.signatures[0]));
    287         } catch (PackageManager.NameNotFoundException e) {
    288             return false;
    289         }
    290     }
    291 
    292     private void initUninstallButtons() {
    293         mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
    294         boolean enabled = true;
    295         if (mUpdatedSysApp) {
    296             mUninstallButton.setText(R.string.app_factory_reset);
    297         } else {
    298             if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
    299                 enabled = false;
    300                 if (SUPPORT_DISABLE_APPS) {
    301                     try {
    302                         // Try to prevent the user from bricking their phone
    303                         // by not allowing disabling of apps signed with the
    304                         // system cert and any launcher app in the system.
    305                         PackageInfo sys = mPm.getPackageInfo("android",
    306                                 PackageManager.GET_SIGNATURES);
    307                         Intent intent = new Intent(Intent.ACTION_MAIN);
    308                         intent.addCategory(Intent.CATEGORY_HOME);
    309                         intent.setPackage(mAppEntry.info.packageName);
    310                         List<ResolveInfo> homes = mPm.queryIntentActivities(intent, 0);
    311                         if ((homes != null && homes.size() > 0) || isThisASystemPackage()) {
    312                             // Disable button for core system applications.
    313                             mUninstallButton.setText(R.string.disable_text);
    314                         } else if (mAppEntry.info.enabled) {
    315                             mUninstallButton.setText(R.string.disable_text);
    316                             enabled = true;
    317                         } else {
    318                             mUninstallButton.setText(R.string.enable_text);
    319                             enabled = true;
    320                         }
    321                     } catch (PackageManager.NameNotFoundException e) {
    322                         Log.w(TAG, "Unable to get package info", e);
    323                     }
    324                 }
    325             } else {
    326                 mUninstallButton.setText(R.string.uninstall_text);
    327             }
    328         }
    329         // If this is a device admin, it can't be uninstall or disabled.
    330         // We do this here so the text of the button is still set correctly.
    331         if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
    332             enabled = false;
    333         }
    334         mUninstallButton.setEnabled(enabled);
    335         if (enabled) {
    336             // Register listener
    337             mUninstallButton.setOnClickListener(this);
    338         }
    339     }
    340 
    341     private void initNotificationButton() {
    342         INotificationManager nm = INotificationManager.Stub.asInterface(
    343                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
    344         boolean enabled = true; // default on
    345         try {
    346             enabled = nm.areNotificationsEnabledForPackage(mAppEntry.info.packageName);
    347         } catch (android.os.RemoteException ex) {
    348             // this does not bode well
    349         }
    350         mNotificationSwitch.setChecked(enabled);
    351         if (isThisASystemPackage()) {
    352             mNotificationSwitch.setEnabled(false);
    353         } else {
    354             mNotificationSwitch.setEnabled(true);
    355             mNotificationSwitch.setOnCheckedChangeListener(this);
    356         }
    357     }
    358 
    359     /** Called when the activity is first created. */
    360     @Override
    361     public void onCreate(Bundle icicle) {
    362         super.onCreate(icicle);
    363 
    364         mState = ApplicationsState.getInstance(getActivity().getApplication());
    365         mSession = mState.newSession(this);
    366         mPm = getActivity().getPackageManager();
    367         IBinder b = ServiceManager.getService(Context.USB_SERVICE);
    368         mUsbManager = IUsbManager.Stub.asInterface(b);
    369         mAppWidgetManager = AppWidgetManager.getInstance(getActivity());
    370         mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
    371 
    372         mCanBeOnSdCardChecker = new CanBeOnSdCardChecker();
    373     }
    374 
    375     @Override
    376     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    377         View view = mRootView = inflater.inflate(R.layout.installed_app_details, null);
    378 
    379         mComputingStr = getActivity().getText(R.string.computing_size);
    380 
    381         // Set default values on sizes
    382         mTotalSize = (TextView)view.findViewById(R.id.total_size_text);
    383         mAppSize = (TextView)view.findViewById(R.id.application_size_text);
    384         mDataSize = (TextView)view.findViewById(R.id.data_size_text);
    385         mExternalCodeSize = (TextView)view.findViewById(R.id.external_code_size_text);
    386         mExternalDataSize = (TextView)view.findViewById(R.id.external_data_size_text);
    387 
    388         // Get Control button panel
    389         View btnPanel = view.findViewById(R.id.control_buttons_panel);
    390         mForceStopButton = (Button) btnPanel.findViewById(R.id.left_button);
    391         mForceStopButton.setText(R.string.force_stop);
    392         mUninstallButton = (Button)btnPanel.findViewById(R.id.right_button);
    393         mForceStopButton.setEnabled(false);
    394 
    395         // Initialize clear data and move install location buttons
    396         View data_buttons_panel = view.findViewById(R.id.data_buttons_panel);
    397         mClearDataButton = (Button) data_buttons_panel.findViewById(R.id.right_button);
    398         mMoveAppButton = (Button) data_buttons_panel.findViewById(R.id.left_button);
    399 
    400         // Cache section
    401         mCacheSize = (TextView) view.findViewById(R.id.cache_size_text);
    402         mClearCacheButton = (Button) view.findViewById(R.id.clear_cache_button);
    403 
    404         mActivitiesButton = (Button)view.findViewById(R.id.clear_activities_button);
    405 
    406         // Screen compatibility control
    407         mScreenCompatSection = view.findViewById(R.id.screen_compatibility_section);
    408         mAskCompatibilityCB = (CheckBox)view.findViewById(R.id.ask_compatibility_cb);
    409         mEnableCompatibilityCB = (CheckBox)view.findViewById(R.id.enable_compatibility_cb);
    410 
    411         mNotificationSwitch = (CompoundButton) view.findViewById(R.id.notification_switch);
    412 
    413         return view;
    414     }
    415 
    416     // Utility method to set applicaiton label and icon.
    417     private void setAppLabelAndIcon(PackageInfo pkgInfo) {
    418         View appSnippet = mRootView.findViewById(R.id.app_snippet);
    419         ImageView icon = (ImageView) appSnippet.findViewById(R.id.app_icon);
    420         mState.ensureIcon(mAppEntry);
    421         icon.setImageDrawable(mAppEntry.icon);
    422         // Set application name.
    423         TextView label = (TextView) appSnippet.findViewById(R.id.app_name);
    424         label.setText(mAppEntry.label);
    425         // Version number of application
    426         mAppVersion = (TextView) appSnippet.findViewById(R.id.app_size);
    427 
    428         if (pkgInfo != null && pkgInfo.versionName != null) {
    429             mAppVersion.setVisibility(View.VISIBLE);
    430             mAppVersion.setText(getActivity().getString(R.string.version_text,
    431                     String.valueOf(pkgInfo.versionName)));
    432         } else {
    433             mAppVersion.setVisibility(View.INVISIBLE);
    434         }
    435     }
    436 
    437     @Override
    438     public void onResume() {
    439         super.onResume();
    440 
    441         mSession.resume();
    442         if (!refreshUi()) {
    443             setIntentAndFinish(true, true);
    444         }
    445     }
    446 
    447     @Override
    448     public void onPause() {
    449         super.onPause();
    450         mSession.pause();
    451     }
    452 
    453     @Override
    454     public void onAllSizesComputed() {
    455     }
    456 
    457     @Override
    458     public void onPackageIconChanged() {
    459     }
    460 
    461     @Override
    462     public void onPackageListChanged() {
    463         refreshUi();
    464     }
    465 
    466     @Override
    467     public void onRebuildComplete(ArrayList<AppEntry> apps) {
    468     }
    469 
    470     @Override
    471     public void onPackageSizeChanged(String packageName) {
    472         if (packageName.equals(mAppEntry.info.packageName)) {
    473             refreshSizeInfo();
    474         }
    475     }
    476 
    477     @Override
    478     public void onRunningStateChanged(boolean running) {
    479     }
    480 
    481     private boolean refreshUi() {
    482         if (mMoveInProgress) {
    483             return true;
    484         }
    485         final Bundle args = getArguments();
    486         String packageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
    487         if (packageName == null) {
    488             Intent intent = (args == null) ?
    489                     getActivity().getIntent() : (Intent) args.getParcelable("intent");
    490             if (intent != null) {
    491                 packageName = intent.getData().getSchemeSpecificPart();
    492             }
    493         }
    494         mAppEntry = mState.getEntry(packageName);
    495 
    496         if (mAppEntry == null) {
    497             return false; // onCreate must have failed, make sure to exit
    498         }
    499 
    500         // Get application info again to refresh changed properties of application
    501         try {
    502             mPackageInfo = mPm.getPackageInfo(mAppEntry.info.packageName,
    503                     PackageManager.GET_DISABLED_COMPONENTS |
    504                     PackageManager.GET_UNINSTALLED_PACKAGES |
    505                     PackageManager.GET_SIGNATURES);
    506         } catch (NameNotFoundException e) {
    507             Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e);
    508             return false; // onCreate must have failed, make sure to exit
    509         }
    510 
    511         // Get list of preferred activities
    512         List<ComponentName> prefActList = new ArrayList<ComponentName>();
    513 
    514         // Intent list cannot be null. so pass empty list
    515         List<IntentFilter> intentList = new ArrayList<IntentFilter>();
    516         mPm.getPreferredActivities(intentList, prefActList, packageName);
    517         if (localLOGV)
    518             Log.i(TAG, "Have " + prefActList.size() + " number of activities in preferred list");
    519         boolean hasUsbDefaults = false;
    520         try {
    521             hasUsbDefaults = mUsbManager.hasDefaults(packageName);
    522         } catch (RemoteException e) {
    523             Log.e(TAG, "mUsbManager.hasDefaults", e);
    524         }
    525         boolean hasBindAppWidgetPermission =
    526                 mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName);
    527 
    528         TextView autoLaunchTitleView = (TextView) mRootView.findViewById(R.id.auto_launch_title);
    529         TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch);
    530         boolean autoLaunchEnabled = prefActList.size() > 0 || hasUsbDefaults;
    531         if (!autoLaunchEnabled && !hasBindAppWidgetPermission) {
    532             resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView);
    533         } else {
    534             boolean useBullets = hasBindAppWidgetPermission && autoLaunchEnabled;
    535 
    536             if (hasBindAppWidgetPermission) {
    537                 autoLaunchTitleView.setText(R.string.auto_launch_label_generic);
    538             } else {
    539                 autoLaunchTitleView.setText(R.string.auto_launch_label);
    540             }
    541 
    542             CharSequence text = null;
    543             int bulletIndent = getResources()
    544                     .getDimensionPixelSize(R.dimen.installed_app_details_bullet_offset);
    545             if (autoLaunchEnabled) {
    546                 CharSequence autoLaunchEnableText = getText(R.string.auto_launch_enable_text);
    547                 SpannableString s = new SpannableString(autoLaunchEnableText);
    548                 if (useBullets) {
    549                     s.setSpan(new BulletSpan(bulletIndent), 0, autoLaunchEnableText.length(), 0);
    550                 }
    551                 text = (text == null) ?
    552                         TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n");
    553             }
    554             if (hasBindAppWidgetPermission) {
    555                 CharSequence alwaysAllowBindAppWidgetsText =
    556                         getText(R.string.always_allow_bind_appwidgets_text);
    557                 SpannableString s = new SpannableString(alwaysAllowBindAppWidgetsText);
    558                 if (useBullets) {
    559                     s.setSpan(new BulletSpan(bulletIndent),
    560                             0, alwaysAllowBindAppWidgetsText.length(), 0);
    561                 }
    562                 text = (text == null) ?
    563                         TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n");
    564             }
    565             autoLaunchView.setText(text);
    566             mActivitiesButton.setEnabled(true);
    567             mActivitiesButton.setOnClickListener(this);
    568         }
    569 
    570         // Screen compatibility section.
    571         ActivityManager am = (ActivityManager)
    572                 getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    573         int compatMode = am.getPackageScreenCompatMode(packageName);
    574         // For now these are always off; this is the old UI model which we
    575         // are no longer using.
    576         if (false && (compatMode == ActivityManager.COMPAT_MODE_DISABLED
    577                 || compatMode == ActivityManager.COMPAT_MODE_ENABLED)) {
    578             mScreenCompatSection.setVisibility(View.VISIBLE);
    579             mAskCompatibilityCB.setChecked(am.getPackageAskScreenCompat(packageName));
    580             mAskCompatibilityCB.setOnCheckedChangeListener(this);
    581             mEnableCompatibilityCB.setChecked(compatMode == ActivityManager.COMPAT_MODE_ENABLED);
    582             mEnableCompatibilityCB.setOnCheckedChangeListener(this);
    583         } else {
    584             mScreenCompatSection.setVisibility(View.GONE);
    585         }
    586 
    587         // Security permissions section
    588         LinearLayout permsView = (LinearLayout) mRootView.findViewById(R.id.permissions_section);
    589         AppSecurityPermissions asp = new AppSecurityPermissions(getActivity(), packageName);
    590         if (asp.getPermissionCount() > 0) {
    591             permsView.setVisibility(View.VISIBLE);
    592             // Make the security sections header visible
    593             LinearLayout securityList = (LinearLayout) permsView.findViewById(
    594                     R.id.security_settings_list);
    595             securityList.removeAllViews();
    596             securityList.addView(asp.getPermissionsView());
    597             // If this app is running under a shared user ID with other apps,
    598             // update the description to explain this.
    599             String[] packages = mPm.getPackagesForUid(mPackageInfo.applicationInfo.uid);
    600             if (packages != null && packages.length > 1) {
    601                 ArrayList<CharSequence> pnames = new ArrayList<CharSequence>();
    602                 for (int i=0; i<packages.length; i++) {
    603                     String pkg = packages[i];
    604                     if (mPackageInfo.packageName.equals(pkg)) {
    605                         continue;
    606                     }
    607                     try {
    608                         ApplicationInfo ainfo = mPm.getApplicationInfo(pkg, 0);
    609                         pnames.add(ainfo.loadLabel(mPm));
    610                     } catch (PackageManager.NameNotFoundException e) {
    611                     }
    612                 }
    613                 final int N = pnames.size();
    614                 if (N > 0) {
    615                     final Resources res = getActivity().getResources();
    616                     String appListStr;
    617                     if (N == 1) {
    618                         appListStr = pnames.get(0).toString();
    619                     } else if (N == 2) {
    620                         appListStr = res.getString(R.string.join_two_items, pnames.get(0),
    621                                 pnames.get(1));
    622                     } else {
    623                         appListStr = pnames.get(N-2).toString();
    624                         for (int i=N-3; i>=0; i--) {
    625                             appListStr = res.getString(i == 0 ? R.string.join_many_items_first
    626                                     : R.string.join_many_items_middle, pnames.get(i), appListStr);
    627                         }
    628                         appListStr = res.getString(R.string.join_many_items_last,
    629                                 appListStr, pnames.get(N-1));
    630                     }
    631                     TextView descr = (TextView) mRootView.findViewById(
    632                             R.id.security_settings_desc);
    633                     descr.setText(res.getString(R.string.security_settings_desc_multi,
    634                             mPackageInfo.applicationInfo.loadLabel(mPm), appListStr));
    635                 }
    636             }
    637         } else {
    638             permsView.setVisibility(View.GONE);
    639         }
    640 
    641         checkForceStop();
    642         setAppLabelAndIcon(mPackageInfo);
    643         refreshButtons();
    644         refreshSizeInfo();
    645         return true;
    646     }
    647 
    648     private void resetLaunchDefaultsUi(TextView title, TextView autoLaunchView) {
    649         title.setText(R.string.auto_launch_label);
    650         autoLaunchView.setText(R.string.auto_launch_disable_text);
    651         // Disable clear activities button
    652         mActivitiesButton.setEnabled(false);
    653     }
    654 
    655     private void setIntentAndFinish(boolean finish, boolean appChanged) {
    656         if(localLOGV) Log.i(TAG, "appChanged="+appChanged);
    657         Intent intent = new Intent();
    658         intent.putExtra(ManageApplications.APP_CHG, appChanged);
    659         PreferenceActivity pa = (PreferenceActivity)getActivity();
    660         pa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
    661     }
    662 
    663     private void refreshSizeInfo() {
    664         if (mAppEntry.size == ApplicationsState.SIZE_INVALID
    665                 || mAppEntry.size == ApplicationsState.SIZE_UNKNOWN) {
    666             mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
    667             if (!mHaveSizes) {
    668                 mAppSize.setText(mComputingStr);
    669                 mDataSize.setText(mComputingStr);
    670                 mCacheSize.setText(mComputingStr);
    671                 mTotalSize.setText(mComputingStr);
    672             }
    673             mClearDataButton.setEnabled(false);
    674             mClearCacheButton.setEnabled(false);
    675 
    676         } else {
    677             mHaveSizes = true;
    678             if (mLastCodeSize != mAppEntry.codeSize) {
    679                 mLastCodeSize = mAppEntry.codeSize;
    680                 mAppSize.setText(getSizeStr(mAppEntry.codeSize));
    681             }
    682             if (mLastDataSize != mAppEntry.dataSize) {
    683                 mLastDataSize = mAppEntry.dataSize;
    684                 mDataSize.setText(getSizeStr(mAppEntry.dataSize));
    685             }
    686             if (mLastExternalCodeSize != mAppEntry.externalCodeSize) {
    687                 mLastExternalCodeSize = mAppEntry.externalCodeSize;
    688                 mExternalCodeSize.setText(getSizeStr(mAppEntry.externalCodeSize));
    689             }
    690             long nonCacheExtDataSize = mAppEntry.externalDataSize - mAppEntry.externalCacheSize;
    691             if (mLastExternalDataSize != nonCacheExtDataSize) {
    692                 mLastExternalDataSize = nonCacheExtDataSize;
    693                 mExternalDataSize.setText(getSizeStr(nonCacheExtDataSize));
    694             }
    695             long cacheSize = mAppEntry.cacheSize + mAppEntry.externalCacheSize;
    696             if (mLastCacheSize != cacheSize) {
    697                 mLastCacheSize = cacheSize;
    698                 mCacheSize.setText(getSizeStr(cacheSize));
    699             }
    700             if (mLastTotalSize != mAppEntry.size) {
    701                 mLastTotalSize = mAppEntry.size;
    702                 mTotalSize.setText(getSizeStr(mAppEntry.size));
    703             }
    704 
    705             if ((mAppEntry.dataSize+nonCacheExtDataSize) <= 0 || !mCanClearData) {
    706                 mClearDataButton.setEnabled(false);
    707             } else {
    708                 mClearDataButton.setEnabled(true);
    709                 mClearDataButton.setOnClickListener(this);
    710             }
    711             if (cacheSize <= 0) {
    712                 mClearCacheButton.setEnabled(false);
    713             } else {
    714                 mClearCacheButton.setEnabled(true);
    715                 mClearCacheButton.setOnClickListener(this);
    716             }
    717         }
    718     }
    719 
    720     /*
    721      * Private method to handle clear message notification from observer when
    722      * the async operation from PackageManager is complete
    723      */
    724     private void processClearMsg(Message msg) {
    725         int result = msg.arg1;
    726         String packageName = mAppEntry.info.packageName;
    727         mClearDataButton.setText(R.string.clear_user_data_text);
    728         if(result == OP_SUCCESSFUL) {
    729             Log.i(TAG, "Cleared user data for package : "+packageName);
    730             mState.requestSize(mAppEntry.info.packageName);
    731         } else {
    732             mClearDataButton.setEnabled(true);
    733         }
    734         checkForceStop();
    735     }
    736 
    737     private void refreshButtons() {
    738         if (!mMoveInProgress) {
    739             initUninstallButtons();
    740             initDataButtons();
    741             initMoveButton();
    742             initNotificationButton();
    743         } else {
    744             mMoveAppButton.setText(R.string.moving);
    745             mMoveAppButton.setEnabled(false);
    746             mUninstallButton.setEnabled(false);
    747         }
    748     }
    749 
    750     private void processMoveMsg(Message msg) {
    751         int result = msg.arg1;
    752         String packageName = mAppEntry.info.packageName;
    753         // Refresh the button attributes.
    754         mMoveInProgress = false;
    755         if (result == PackageManager.MOVE_SUCCEEDED) {
    756             Log.i(TAG, "Moved resources for " + packageName);
    757             // Refresh size information again.
    758             mState.requestSize(mAppEntry.info.packageName);
    759         } else {
    760             showDialogInner(DLG_MOVE_FAILED, result);
    761         }
    762         refreshUi();
    763     }
    764 
    765     /*
    766      * Private method to initiate clearing user data when the user clicks the clear data
    767      * button for a system package
    768      */
    769     private  void initiateClearUserData() {
    770         mClearDataButton.setEnabled(false);
    771         // Invoke uninstall or clear user data based on sysPackage
    772         String packageName = mAppEntry.info.packageName;
    773         Log.i(TAG, "Clearing user data for package : " + packageName);
    774         if (mClearDataObserver == null) {
    775             mClearDataObserver = new ClearUserDataObserver();
    776         }
    777         ActivityManager am = (ActivityManager)
    778                 getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    779         boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
    780         if (!res) {
    781             // Clearing data failed for some obscure reason. Just log error for now
    782             Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
    783             showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
    784         } else {
    785             mClearDataButton.setText(R.string.recompute_size);
    786         }
    787     }
    788 
    789     private void showDialogInner(int id, int moveErrorCode) {
    790         DialogFragment newFragment = MyAlertDialogFragment.newInstance(id, moveErrorCode);
    791         newFragment.setTargetFragment(this, 0);
    792         newFragment.show(getFragmentManager(), "dialog " + id);
    793     }
    794 
    795     public static class MyAlertDialogFragment extends DialogFragment {
    796 
    797         public static MyAlertDialogFragment newInstance(int id, int moveErrorCode) {
    798             MyAlertDialogFragment frag = new MyAlertDialogFragment();
    799             Bundle args = new Bundle();
    800             args.putInt("id", id);
    801             args.putInt("moveError", moveErrorCode);
    802             frag.setArguments(args);
    803             return frag;
    804         }
    805 
    806         InstalledAppDetails getOwner() {
    807             return (InstalledAppDetails)getTargetFragment();
    808         }
    809 
    810         @Override
    811         public Dialog onCreateDialog(Bundle savedInstanceState) {
    812             int id = getArguments().getInt("id");
    813             int moveErrorCode = getArguments().getInt("moveError");
    814             switch (id) {
    815                 case DLG_CLEAR_DATA:
    816                     return new AlertDialog.Builder(getActivity())
    817                     .setTitle(getActivity().getText(R.string.clear_data_dlg_title))
    818                     .setIcon(android.R.drawable.ic_dialog_alert)
    819                     .setMessage(getActivity().getText(R.string.clear_data_dlg_text))
    820                     .setPositiveButton(R.string.dlg_ok,
    821                             new DialogInterface.OnClickListener() {
    822                         public void onClick(DialogInterface dialog, int which) {
    823                             // Clear user data here
    824                             getOwner().initiateClearUserData();
    825                         }
    826                     })
    827                     .setNegativeButton(R.string.dlg_cancel, null)
    828                     .create();
    829                 case DLG_FACTORY_RESET:
    830                     return new AlertDialog.Builder(getActivity())
    831                     .setTitle(getActivity().getText(R.string.app_factory_reset_dlg_title))
    832                     .setIcon(android.R.drawable.ic_dialog_alert)
    833                     .setMessage(getActivity().getText(R.string.app_factory_reset_dlg_text))
    834                     .setPositiveButton(R.string.dlg_ok,
    835                             new DialogInterface.OnClickListener() {
    836                         public void onClick(DialogInterface dialog, int which) {
    837                             // Clear user data here
    838                             getOwner().uninstallPkg(getOwner().mAppEntry.info.packageName);
    839                         }
    840                     })
    841                     .setNegativeButton(R.string.dlg_cancel, null)
    842                     .create();
    843                 case DLG_APP_NOT_FOUND:
    844                     return new AlertDialog.Builder(getActivity())
    845                     .setTitle(getActivity().getText(R.string.app_not_found_dlg_title))
    846                     .setIcon(android.R.drawable.ic_dialog_alert)
    847                     .setMessage(getActivity().getText(R.string.app_not_found_dlg_title))
    848                     .setNeutralButton(getActivity().getText(R.string.dlg_ok),
    849                             new DialogInterface.OnClickListener() {
    850                         public void onClick(DialogInterface dialog, int which) {
    851                             //force to recompute changed value
    852                             getOwner().setIntentAndFinish(true, true);
    853                         }
    854                     })
    855                     .create();
    856                 case DLG_CANNOT_CLEAR_DATA:
    857                     return new AlertDialog.Builder(getActivity())
    858                     .setTitle(getActivity().getText(R.string.clear_failed_dlg_title))
    859                     .setIcon(android.R.drawable.ic_dialog_alert)
    860                     .setMessage(getActivity().getText(R.string.clear_failed_dlg_text))
    861                     .setNeutralButton(R.string.dlg_ok,
    862                             new DialogInterface.OnClickListener() {
    863                         public void onClick(DialogInterface dialog, int which) {
    864                             getOwner().mClearDataButton.setEnabled(false);
    865                             //force to recompute changed value
    866                             getOwner().setIntentAndFinish(false, false);
    867                         }
    868                     })
    869                     .create();
    870                 case DLG_FORCE_STOP:
    871                     return new AlertDialog.Builder(getActivity())
    872                     .setTitle(getActivity().getText(R.string.force_stop_dlg_title))
    873                     .setIcon(android.R.drawable.ic_dialog_alert)
    874                     .setMessage(getActivity().getText(R.string.force_stop_dlg_text))
    875                     .setPositiveButton(R.string.dlg_ok,
    876                         new DialogInterface.OnClickListener() {
    877                         public void onClick(DialogInterface dialog, int which) {
    878                             // Force stop
    879                             getOwner().forceStopPackage(getOwner().mAppEntry.info.packageName);
    880                         }
    881                     })
    882                     .setNegativeButton(R.string.dlg_cancel, null)
    883                     .create();
    884                 case DLG_MOVE_FAILED:
    885                     CharSequence msg = getActivity().getString(R.string.move_app_failed_dlg_text,
    886                             getOwner().getMoveErrMsg(moveErrorCode));
    887                     return new AlertDialog.Builder(getActivity())
    888                     .setTitle(getActivity().getText(R.string.move_app_failed_dlg_title))
    889                     .setIcon(android.R.drawable.ic_dialog_alert)
    890                     .setMessage(msg)
    891                     .setNeutralButton(R.string.dlg_ok, null)
    892                     .create();
    893                 case DLG_DISABLE:
    894                     return new AlertDialog.Builder(getActivity())
    895                     .setTitle(getActivity().getText(R.string.app_disable_dlg_title))
    896                     .setIcon(android.R.drawable.ic_dialog_alert)
    897                     .setMessage(getActivity().getText(R.string.app_disable_dlg_text))
    898                     .setPositiveButton(R.string.dlg_ok,
    899                         new DialogInterface.OnClickListener() {
    900                         public void onClick(DialogInterface dialog, int which) {
    901                             // Disable the app
    902                             new DisableChanger(getOwner(), getOwner().mAppEntry.info,
    903                                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
    904                             .execute((Object)null);
    905                         }
    906                     })
    907                     .setNegativeButton(R.string.dlg_cancel, null)
    908                     .create();
    909                 case DLG_DISABLE_NOTIFICATIONS:
    910                     return new AlertDialog.Builder(getActivity())
    911                     .setTitle(getActivity().getText(R.string.app_disable_notifications_dlg_title))
    912                     .setIcon(android.R.drawable.ic_dialog_alert)
    913                     .setMessage(getActivity().getText(R.string.app_disable_notifications_dlg_text))
    914                     .setPositiveButton(R.string.dlg_ok,
    915                         new DialogInterface.OnClickListener() {
    916                         public void onClick(DialogInterface dialog, int which) {
    917                             // Disable the package's notifications
    918                             getOwner().setNotificationsEnabled(false);
    919                         }
    920                     })
    921                     .setNegativeButton(R.string.dlg_cancel,
    922                         new DialogInterface.OnClickListener() {
    923                         public void onClick(DialogInterface dialog, int which) {
    924                             // Re-enable the checkbox
    925                             getOwner().mNotificationSwitch.setChecked(true);
    926                         }
    927                     })
    928                     .create();
    929             }
    930             throw new IllegalArgumentException("unknown id " + id);
    931         }
    932     }
    933 
    934     private void uninstallPkg(String packageName) {
    935          // Create new intent to launch Uninstaller activity
    936         Uri packageURI = Uri.parse("package:"+packageName);
    937         Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
    938         startActivity(uninstallIntent);
    939         setIntentAndFinish(true, true);
    940     }
    941 
    942     private void forceStopPackage(String pkgName) {
    943         ActivityManager am = (ActivityManager)getActivity().getSystemService(
    944                 Context.ACTIVITY_SERVICE);
    945         am.forceStopPackage(pkgName);
    946         mState.invalidatePackage(pkgName);
    947         ApplicationsState.AppEntry newEnt = mState.getEntry(pkgName);
    948         if (newEnt != null) {
    949             mAppEntry = newEnt;
    950         }
    951         checkForceStop();
    952     }
    953 
    954     private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
    955         @Override
    956         public void onReceive(Context context, Intent intent) {
    957             updateForceStopButton(getResultCode() != Activity.RESULT_CANCELED);
    958         }
    959     };
    960 
    961     private void updateForceStopButton(boolean enabled) {
    962         mForceStopButton.setEnabled(enabled);
    963         mForceStopButton.setOnClickListener(InstalledAppDetails.this);
    964     }
    965 
    966     private void checkForceStop() {
    967         if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
    968             // User can't force stop device admin.
    969             updateForceStopButton(false);
    970         } else if ((mAppEntry.info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
    971             // If the app isn't explicitly stopped, then always show the
    972             // force stop button.
    973             updateForceStopButton(true);
    974         } else {
    975             Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
    976                     Uri.fromParts("package", mAppEntry.info.packageName, null));
    977             intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mAppEntry.info.packageName });
    978             intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid);
    979             getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
    980                     Activity.RESULT_CANCELED, null, null);
    981         }
    982     }
    983 
    984     static class DisableChanger extends AsyncTask<Object, Object, Object> {
    985         final PackageManager mPm;
    986         final WeakReference<InstalledAppDetails> mActivity;
    987         final ApplicationInfo mInfo;
    988         final int mState;
    989 
    990         DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) {
    991             mPm = activity.mPm;
    992             mActivity = new WeakReference<InstalledAppDetails>(activity);
    993             mInfo = info;
    994             mState = state;
    995         }
    996 
    997         @Override
    998         protected Object doInBackground(Object... params) {
    999             mPm.setApplicationEnabledSetting(mInfo.packageName, mState, 0);
   1000             return null;
   1001         }
   1002     }
   1003 
   1004     private void setNotificationsEnabled(boolean enabled) {
   1005         String packageName = mAppEntry.info.packageName;
   1006         INotificationManager nm = INotificationManager.Stub.asInterface(
   1007                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
   1008         try {
   1009             final boolean enable = mNotificationSwitch.isChecked();
   1010             nm.setNotificationsEnabledForPackage(packageName, enabled);
   1011         } catch (android.os.RemoteException ex) {
   1012             mNotificationSwitch.setChecked(!enabled); // revert
   1013         }
   1014     }
   1015 
   1016     /*
   1017      * Method implementing functionality of buttons clicked
   1018      * @see android.view.View.OnClickListener#onClick(android.view.View)
   1019      */
   1020     public void onClick(View v) {
   1021         String packageName = mAppEntry.info.packageName;
   1022         if(v == mUninstallButton) {
   1023             if (mUpdatedSysApp) {
   1024                 showDialogInner(DLG_FACTORY_RESET, 0);
   1025             } else {
   1026                 if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
   1027                     if (mAppEntry.info.enabled) {
   1028                         showDialogInner(DLG_DISABLE, 0);
   1029                     } else {
   1030                         new DisableChanger(this, mAppEntry.info,
   1031                                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
   1032                         .execute((Object)null);
   1033                     }
   1034                 } else {
   1035                     uninstallPkg(packageName);
   1036                 }
   1037             }
   1038         } else if(v == mActivitiesButton) {
   1039             mPm.clearPackagePreferredActivities(packageName);
   1040             try {
   1041                 mUsbManager.clearDefaults(packageName);
   1042             } catch (RemoteException e) {
   1043                 Log.e(TAG, "mUsbManager.clearDefaults", e);
   1044             }
   1045             mAppWidgetManager.setBindAppWidgetPermission(packageName, false);
   1046             TextView autoLaunchTitleView =
   1047                     (TextView) mRootView.findViewById(R.id.auto_launch_title);
   1048             TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch);
   1049             resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView);
   1050         } else if(v == mClearDataButton) {
   1051             if (mAppEntry.info.manageSpaceActivityName != null) {
   1052                 if (!Utils.isMonkeyRunning()) {
   1053                     Intent intent = new Intent(Intent.ACTION_DEFAULT);
   1054                     intent.setClassName(mAppEntry.info.packageName,
   1055                             mAppEntry.info.manageSpaceActivityName);
   1056                     startActivityForResult(intent, -1);
   1057                 }
   1058             } else {
   1059                 showDialogInner(DLG_CLEAR_DATA, 0);
   1060             }
   1061         } else if (v == mClearCacheButton) {
   1062             // Lazy initialization of observer
   1063             if (mClearCacheObserver == null) {
   1064                 mClearCacheObserver = new ClearCacheObserver();
   1065             }
   1066             mPm.deleteApplicationCacheFiles(packageName, mClearCacheObserver);
   1067         } else if (v == mForceStopButton) {
   1068             showDialogInner(DLG_FORCE_STOP, 0);
   1069             //forceStopPackage(mAppInfo.packageName);
   1070         } else if (v == mMoveAppButton) {
   1071             if (mPackageMoveObserver == null) {
   1072                 mPackageMoveObserver = new PackageMoveObserver();
   1073             }
   1074             int moveFlags = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
   1075                     PackageManager.MOVE_INTERNAL : PackageManager.MOVE_EXTERNAL_MEDIA;
   1076             mMoveInProgress = true;
   1077             refreshButtons();
   1078             mPm.movePackage(mAppEntry.info.packageName, mPackageMoveObserver, moveFlags);
   1079         }
   1080     }
   1081 
   1082     @Override
   1083     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   1084         String packageName = mAppEntry.info.packageName;
   1085         ActivityManager am = (ActivityManager)
   1086                 getActivity().getSystemService(Context.ACTIVITY_SERVICE);
   1087         if (buttonView == mAskCompatibilityCB) {
   1088             am.setPackageAskScreenCompat(packageName, isChecked);
   1089         } else if (buttonView == mEnableCompatibilityCB) {
   1090             am.setPackageScreenCompatMode(packageName, isChecked ?
   1091                     ActivityManager.COMPAT_MODE_ENABLED : ActivityManager.COMPAT_MODE_DISABLED);
   1092         } else if (buttonView == mNotificationSwitch) {
   1093             if (!isChecked) {
   1094                 showDialogInner(DLG_DISABLE_NOTIFICATIONS, 0);
   1095             } else {
   1096                 setNotificationsEnabled(true);
   1097             }
   1098         }
   1099     }
   1100 }
   1101 
   1102