Home | History | Annotate | Download | only in applications
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy 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,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.applications;
     18 
     19 import static android.net.NetworkPolicyManager.POLICY_NONE;
     20 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
     21 
     22 import android.app.Activity;
     23 import android.app.ActivityManager;
     24 import android.app.AlertDialog;
     25 import android.app.AppOpsManager;
     26 import android.app.Fragment;
     27 import android.app.INotificationManager;
     28 import android.content.ComponentName;
     29 import android.content.Context;
     30 import android.content.DialogInterface;
     31 import android.content.Intent;
     32 import android.content.IntentFilter;
     33 import android.content.ServiceConnection;
     34 import android.content.pm.ApplicationInfo;
     35 import android.content.pm.IPackageManager;
     36 import android.content.pm.PackageInfo;
     37 import android.content.pm.PackageManager;
     38 import android.net.NetworkPolicyManager;
     39 import android.os.AsyncTask;
     40 import android.os.Bundle;
     41 import android.os.Environment;
     42 import android.os.Handler;
     43 import android.os.IBinder;
     44 import android.os.RemoteException;
     45 import android.os.ServiceManager;
     46 import android.os.UserHandle;
     47 import android.preference.PreferenceActivity;
     48 import android.preference.PreferenceFrameLayout;
     49 import android.provider.Settings;
     50 import android.support.v4.view.PagerAdapter;
     51 import android.support.v4.view.PagerTabStrip;
     52 import android.support.v4.view.ViewPager;
     53 import android.text.BidiFormatter;
     54 import android.text.format.Formatter;
     55 import android.util.Log;
     56 import android.view.LayoutInflater;
     57 import android.view.Menu;
     58 import android.view.MenuInflater;
     59 import android.view.MenuItem;
     60 import android.view.View;
     61 import android.view.ViewGroup;
     62 import android.view.animation.AnimationUtils;
     63 import android.widget.AbsListView;
     64 import android.widget.AdapterView;
     65 import android.widget.AdapterView.OnItemClickListener;
     66 import android.widget.BaseAdapter;
     67 import android.widget.Filter;
     68 import android.widget.Filterable;
     69 import android.widget.ListView;
     70 import android.widget.TextView;
     71 
     72 import com.android.internal.app.IMediaContainerService;
     73 import com.android.internal.content.PackageHelper;
     74 import com.android.settings.R;
     75 import com.android.settings.Settings.RunningServicesActivity;
     76 import com.android.settings.Settings.StorageUseActivity;
     77 import com.android.settings.applications.ApplicationsState.AppEntry;
     78 import com.android.settings.deviceinfo.StorageMeasurement;
     79 import com.android.settings.Utils;
     80 
     81 import java.util.ArrayList;
     82 import java.util.Comparator;
     83 import java.util.List;
     84 
     85 final class CanBeOnSdCardChecker {
     86     final IPackageManager mPm;
     87     int mInstallLocation;
     88 
     89     CanBeOnSdCardChecker() {
     90         mPm = IPackageManager.Stub.asInterface(
     91                 ServiceManager.getService("package"));
     92     }
     93 
     94     void init() {
     95         try {
     96             mInstallLocation = mPm.getInstallLocation();
     97         } catch (RemoteException e) {
     98             Log.e("CanBeOnSdCardChecker", "Is Package Manager running?");
     99             return;
    100         }
    101     }
    102 
    103     boolean check(ApplicationInfo info) {
    104         boolean canBe = false;
    105         if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
    106             canBe = true;
    107         } else {
    108             if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
    109                 if (info.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
    110                         info.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
    111                     canBe = true;
    112                 } else if (info.installLocation
    113                         == PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
    114                     if (mInstallLocation == PackageHelper.APP_INSTALL_EXTERNAL) {
    115                         // For apps with no preference and the default value set
    116                         // to install on sdcard.
    117                         canBe = true;
    118                     }
    119                 }
    120             }
    121         }
    122         return canBe;
    123     }
    124 }
    125 
    126 interface AppClickListener {
    127     void onItemClick(ManageApplications.TabInfo tab, AdapterView<?> parent,
    128             View view, int position, long id);
    129 }
    130 
    131 /**
    132  * Activity to pick an application that will be used to display installation information and
    133  * options to uninstall/delete user data for system applications. This activity
    134  * can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
    135  * intent.
    136  */
    137 public class ManageApplications extends Fragment implements
    138         AppClickListener, DialogInterface.OnClickListener,
    139         DialogInterface.OnDismissListener {
    140 
    141     static final String TAG = "ManageApplications";
    142     static final boolean DEBUG = false;
    143 
    144     private static final String EXTRA_SORT_ORDER = "sortOrder";
    145     private static final String EXTRA_SHOW_BACKGROUND = "showBackground";
    146     private static final String EXTRA_DEFAULT_LIST_TYPE = "defaultListType";
    147     private static final String EXTRA_RESET_DIALOG = "resetDialog";
    148 
    149     // attributes used as keys when passing values to InstalledAppDetails activity
    150     public static final String APP_CHG = "chg";
    151 
    152     // constant value that can be used to check return code from sub activity.
    153     private static final int INSTALLED_APP_DETAILS = 1;
    154 
    155     public static final int SIZE_TOTAL = 0;
    156     public static final int SIZE_INTERNAL = 1;
    157     public static final int SIZE_EXTERNAL = 2;
    158 
    159     // sort order that can be changed through the menu can be sorted alphabetically
    160     // or size(descending)
    161     private static final int MENU_OPTIONS_BASE = 0;
    162     // Filter options used for displayed list of applications
    163     public static final int FILTER_APPS_ALL = MENU_OPTIONS_BASE + 0;
    164     public static final int FILTER_APPS_THIRD_PARTY = MENU_OPTIONS_BASE + 1;
    165     public static final int FILTER_APPS_SDCARD = MENU_OPTIONS_BASE + 2;
    166     public static final int FILTER_APPS_DISABLED = MENU_OPTIONS_BASE + 3;
    167 
    168     public static final int SORT_ORDER_ALPHA = MENU_OPTIONS_BASE + 4;
    169     public static final int SORT_ORDER_SIZE = MENU_OPTIONS_BASE + 5;
    170     public static final int SHOW_RUNNING_SERVICES = MENU_OPTIONS_BASE + 6;
    171     public static final int SHOW_BACKGROUND_PROCESSES = MENU_OPTIONS_BASE + 7;
    172     public static final int RESET_APP_PREFERENCES = MENU_OPTIONS_BASE + 8;
    173     // sort order
    174     private int mSortOrder = SORT_ORDER_ALPHA;
    175 
    176     private ApplicationsState mApplicationsState;
    177 
    178     public static class TabInfo implements OnItemClickListener {
    179         public final ManageApplications mOwner;
    180         public final ApplicationsState mApplicationsState;
    181         public final CharSequence mLabel;
    182         public final int mListType;
    183         public final int mFilter;
    184         public final AppClickListener mClickListener;
    185         public final CharSequence mInvalidSizeStr;
    186         public final CharSequence mComputingSizeStr;
    187         private final Bundle mSavedInstanceState;
    188 
    189         public ApplicationsAdapter mApplications;
    190         public LayoutInflater mInflater;
    191         public View mRootView;
    192 
    193         private IMediaContainerService mContainerService;
    194 
    195         private View mLoadingContainer;
    196 
    197         private View mListContainer;
    198 
    199         // ListView used to display list
    200         private ListView mListView;
    201         // Custom view used to display running processes
    202         private RunningProcessesView mRunningProcessesView;
    203 
    204         private LinearColorBar mColorBar;
    205         private TextView mStorageChartLabel;
    206         private TextView mUsedStorageText;
    207         private TextView mFreeStorageText;
    208         private long mFreeStorage = 0, mAppStorage = 0, mTotalStorage = 0;
    209         private long mLastUsedStorage, mLastAppStorage, mLastFreeStorage;
    210 
    211         final Runnable mRunningProcessesAvail = new Runnable() {
    212             public void run() {
    213                 handleRunningProcessesAvail();
    214             }
    215         };
    216 
    217         public TabInfo(ManageApplications owner, ApplicationsState apps,
    218                 CharSequence label, int listType, AppClickListener clickListener,
    219                 Bundle savedInstanceState) {
    220             mOwner = owner;
    221             mApplicationsState = apps;
    222             mLabel = label;
    223             mListType = listType;
    224             switch (listType) {
    225                 case LIST_TYPE_DOWNLOADED: mFilter = FILTER_APPS_THIRD_PARTY; break;
    226                 case LIST_TYPE_SDCARD: mFilter = FILTER_APPS_SDCARD; break;
    227                 case LIST_TYPE_DISABLED: mFilter = FILTER_APPS_DISABLED; break;
    228                 default: mFilter = FILTER_APPS_ALL; break;
    229             }
    230             mClickListener = clickListener;
    231             mInvalidSizeStr = owner.getActivity().getText(R.string.invalid_size_value);
    232             mComputingSizeStr = owner.getActivity().getText(R.string.computing_size);
    233             mSavedInstanceState = savedInstanceState;
    234         }
    235 
    236         public void setContainerService(IMediaContainerService containerService) {
    237             mContainerService = containerService;
    238             updateStorageUsage();
    239         }
    240 
    241         public View build(LayoutInflater inflater, ViewGroup contentParent, View contentChild) {
    242             if (mRootView != null) {
    243                 return mRootView;
    244             }
    245 
    246             mInflater = inflater;
    247             mRootView = inflater.inflate(mListType == LIST_TYPE_RUNNING
    248                     ? R.layout.manage_applications_running
    249                     : R.layout.manage_applications_apps, null);
    250             mLoadingContainer = mRootView.findViewById(R.id.loading_container);
    251             mLoadingContainer.setVisibility(View.VISIBLE);
    252             mListContainer = mRootView.findViewById(R.id.list_container);
    253             if (mListContainer != null) {
    254                 // Create adapter and list view here
    255                 View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty);
    256                 ListView lv = (ListView) mListContainer.findViewById(android.R.id.list);
    257                 if (emptyView != null) {
    258                     lv.setEmptyView(emptyView);
    259                 }
    260                 lv.setOnItemClickListener(this);
    261                 lv.setSaveEnabled(true);
    262                 lv.setItemsCanFocus(true);
    263                 lv.setTextFilterEnabled(true);
    264                 mListView = lv;
    265                 mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter);
    266                 mListView.setAdapter(mApplications);
    267                 mListView.setRecyclerListener(mApplications);
    268                 mColorBar = (LinearColorBar)mListContainer.findViewById(R.id.storage_color_bar);
    269                 mStorageChartLabel = (TextView)mListContainer.findViewById(R.id.storageChartLabel);
    270                 mUsedStorageText = (TextView)mListContainer.findViewById(R.id.usedStorageText);
    271                 mFreeStorageText = (TextView)mListContainer.findViewById(R.id.freeStorageText);
    272                 Utils.prepareCustomPreferencesList(contentParent, contentChild, mListView, false);
    273                 if (mFilter == FILTER_APPS_SDCARD) {
    274                     mStorageChartLabel.setText(mOwner.getActivity().getText(
    275                             R.string.sd_card_storage));
    276                 } else {
    277                     mStorageChartLabel.setText(mOwner.getActivity().getText(
    278                             R.string.internal_storage));
    279                 }
    280                 applyCurrentStorage();
    281             }
    282             mRunningProcessesView = (RunningProcessesView)mRootView.findViewById(
    283                     R.id.running_processes);
    284             if (mRunningProcessesView != null) {
    285                 mRunningProcessesView.doCreate(mSavedInstanceState);
    286             }
    287 
    288             return mRootView;
    289         }
    290 
    291         public void detachView() {
    292             if (mRootView != null) {
    293                 ViewGroup group = (ViewGroup)mRootView.getParent();
    294                 if (group != null) {
    295                     group.removeView(mRootView);
    296                 }
    297             }
    298         }
    299 
    300         public void resume(int sortOrder) {
    301             if (mApplications != null) {
    302                 mApplications.resume(sortOrder);
    303             }
    304             if (mRunningProcessesView != null) {
    305                 boolean haveData = mRunningProcessesView.doResume(mOwner, mRunningProcessesAvail);
    306                 if (haveData) {
    307                     mRunningProcessesView.setVisibility(View.VISIBLE);
    308                     mLoadingContainer.setVisibility(View.INVISIBLE);
    309                 } else {
    310                     mLoadingContainer.setVisibility(View.VISIBLE);
    311                 }
    312             }
    313         }
    314 
    315         public void pause() {
    316             if (mApplications != null) {
    317                 mApplications.pause();
    318             }
    319             if (mRunningProcessesView != null) {
    320                 mRunningProcessesView.doPause();
    321             }
    322         }
    323 
    324         void updateStorageUsage() {
    325             // Make sure a callback didn't come at an inopportune time.
    326             if (mOwner.getActivity() == null) return;
    327             // Doesn't make sense for stuff that is not an app list.
    328             if (mApplications == null) return;
    329 
    330             mFreeStorage = 0;
    331             mAppStorage = 0;
    332             mTotalStorage = 0;
    333 
    334             if (mFilter == FILTER_APPS_SDCARD) {
    335                 if (mContainerService != null) {
    336                     try {
    337                         final long[] stats = mContainerService.getFileSystemStats(
    338                                 Environment.getExternalStorageDirectory().getPath());
    339                         mTotalStorage = stats[0];
    340                         mFreeStorage = stats[1];
    341                     } catch (RemoteException e) {
    342                         Log.w(TAG, "Problem in container service", e);
    343                     }
    344                 }
    345 
    346                 if (mApplications != null) {
    347                     final int N = mApplications.getCount();
    348                     for (int i=0; i<N; i++) {
    349                         ApplicationsState.AppEntry ae = mApplications.getAppEntry(i);
    350                         mAppStorage += ae.externalCodeSize + ae.externalDataSize
    351                                 + ae.externalCacheSize;
    352                     }
    353                 }
    354             } else {
    355                 if (mContainerService != null) {
    356                     try {
    357                         final long[] stats = mContainerService.getFileSystemStats(
    358                                 Environment.getDataDirectory().getPath());
    359                         mTotalStorage = stats[0];
    360                         mFreeStorage = stats[1];
    361                     } catch (RemoteException e) {
    362                         Log.w(TAG, "Problem in container service", e);
    363                     }
    364                 }
    365 
    366                 final boolean emulatedStorage = Environment.isExternalStorageEmulated();
    367                 if (mApplications != null) {
    368                     final int N = mApplications.getCount();
    369                     for (int i=0; i<N; i++) {
    370                         ApplicationsState.AppEntry ae = mApplications.getAppEntry(i);
    371                         mAppStorage += ae.codeSize + ae.dataSize;
    372                         if (emulatedStorage) {
    373                             mAppStorage += ae.externalCodeSize + ae.externalDataSize;
    374                         }
    375                     }
    376                 }
    377                 mFreeStorage += mApplicationsState.sumCacheSizes();
    378             }
    379 
    380             applyCurrentStorage();
    381         }
    382 
    383         void applyCurrentStorage() {
    384             // If view hierarchy is not yet created, no views to update.
    385             if (mRootView == null) {
    386                 return;
    387             }
    388             if (mTotalStorage > 0) {
    389                 BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    390                 mColorBar.setRatios((mTotalStorage-mFreeStorage-mAppStorage)/(float)mTotalStorage,
    391                         mAppStorage/(float)mTotalStorage, mFreeStorage/(float)mTotalStorage);
    392                 long usedStorage = mTotalStorage - mFreeStorage;
    393                 if (mLastUsedStorage != usedStorage) {
    394                     mLastUsedStorage = usedStorage;
    395                     String sizeStr = bidiFormatter.unicodeWrap(
    396                             Formatter.formatShortFileSize(mOwner.getActivity(), usedStorage));
    397                     mUsedStorageText.setText(mOwner.getActivity().getResources().getString(
    398                             R.string.service_foreground_processes, sizeStr));
    399                 }
    400                 if (mLastFreeStorage != mFreeStorage) {
    401                     mLastFreeStorage = mFreeStorage;
    402                     String sizeStr = bidiFormatter.unicodeWrap(
    403                             Formatter.formatShortFileSize(mOwner.getActivity(), mFreeStorage));
    404                     mFreeStorageText.setText(mOwner.getActivity().getResources().getString(
    405                             R.string.service_background_processes, sizeStr));
    406                 }
    407             } else {
    408                 mColorBar.setRatios(0, 0, 0);
    409                 if (mLastUsedStorage != -1) {
    410                     mLastUsedStorage = -1;
    411                     mUsedStorageText.setText("");
    412                 }
    413                 if (mLastFreeStorage != -1) {
    414                     mLastFreeStorage = -1;
    415                     mFreeStorageText.setText("");
    416                 }
    417             }
    418         }
    419 
    420         @Override
    421         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    422             mClickListener.onItemClick(this, parent, view, position, id);
    423         }
    424 
    425         void handleRunningProcessesAvail() {
    426             mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(
    427                     mOwner.getActivity(), android.R.anim.fade_out));
    428             mRunningProcessesView.startAnimation(AnimationUtils.loadAnimation(
    429                     mOwner.getActivity(), android.R.anim.fade_in));
    430             mRunningProcessesView.setVisibility(View.VISIBLE);
    431             mLoadingContainer.setVisibility(View.GONE);
    432         }
    433     }
    434     private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    435     private int mNumTabs;
    436     TabInfo mCurTab = null;
    437 
    438     // Size resource used for packages whose size computation failed for some reason
    439     CharSequence mInvalidSizeStr;
    440     private CharSequence mComputingSizeStr;
    441 
    442     // layout inflater object used to inflate views
    443     private LayoutInflater mInflater;
    444 
    445     private String mCurrentPkgName;
    446 
    447     private Menu mOptionsMenu;
    448 
    449     // These are for keeping track of activity and spinner switch state.
    450     private boolean mActivityResumed;
    451 
    452     static final int LIST_TYPE_DOWNLOADED = 0;
    453     static final int LIST_TYPE_RUNNING = 1;
    454     static final int LIST_TYPE_SDCARD = 2;
    455     static final int LIST_TYPE_ALL = 3;
    456     static final int LIST_TYPE_DISABLED = 4;
    457 
    458     private boolean mShowBackground = false;
    459 
    460     private int mDefaultListType = -1;
    461 
    462     private ViewGroup mContentContainer;
    463     private View mRootView;
    464     private ViewPager mViewPager;
    465 
    466     AlertDialog mResetDialog;
    467 
    468     class MyPagerAdapter extends PagerAdapter
    469             implements ViewPager.OnPageChangeListener {
    470         int mCurPos = 0;
    471 
    472         @Override
    473         public int getCount() {
    474             return mNumTabs;
    475         }
    476 
    477         @Override
    478         public Object instantiateItem(ViewGroup container, int position) {
    479             TabInfo tab = mTabs.get(position);
    480             View root = tab.build(mInflater, mContentContainer, mRootView);
    481             container.addView(root);
    482             root.setTag(R.id.name, tab);
    483             return root;
    484         }
    485 
    486         @Override
    487         public void destroyItem(ViewGroup container, int position, Object object) {
    488             container.removeView((View)object);
    489         }
    490 
    491         @Override
    492         public boolean isViewFromObject(View view, Object object) {
    493             return view == object;
    494         }
    495 
    496         @Override
    497         public int getItemPosition(Object object) {
    498             return super.getItemPosition(object);
    499             //return ((TabInfo)((View)object).getTag(R.id.name)).mListType;
    500         }
    501 
    502         @Override
    503         public CharSequence getPageTitle(int position) {
    504             return mTabs.get(position).mLabel;
    505         }
    506 
    507         @Override
    508         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    509         }
    510 
    511         @Override
    512         public void onPageSelected(int position) {
    513             mCurPos = position;
    514         }
    515 
    516         @Override
    517         public void onPageScrollStateChanged(int state) {
    518             if (state == ViewPager.SCROLL_STATE_IDLE) {
    519                 updateCurrentTab(mCurPos);
    520             }
    521         }
    522     }
    523 
    524     /*
    525      * Custom adapter implementation for the ListView
    526      * This adapter maintains a map for each displayed application and its properties
    527      * An index value on each AppInfo object indicates the correct position or index
    528      * in the list. If the list gets updated dynamically when the user is viewing the list of
    529      * applications, we need to return the correct index of position. This is done by mapping
    530      * the getId methods via the package name into the internal maps and indices.
    531      * The order of applications in the list is mirrored in mAppLocalList
    532      */
    533     static class ApplicationsAdapter extends BaseAdapter implements Filterable,
    534             ApplicationsState.Callbacks, AbsListView.RecyclerListener {
    535         private final ApplicationsState mState;
    536         private final ApplicationsState.Session mSession;
    537         private final TabInfo mTab;
    538         private final Context mContext;
    539         private final ArrayList<View> mActive = new ArrayList<View>();
    540         private final int mFilterMode;
    541         private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
    542         private ArrayList<ApplicationsState.AppEntry> mEntries;
    543         private boolean mResumed;
    544         private int mLastSortMode=-1;
    545         private boolean mWaitingForData;
    546         private int mWhichSize = SIZE_TOTAL;
    547         CharSequence mCurFilterPrefix;
    548 
    549         private Filter mFilter = new Filter() {
    550             @Override
    551             protected FilterResults performFiltering(CharSequence constraint) {
    552                 ArrayList<ApplicationsState.AppEntry> entries
    553                         = applyPrefixFilter(constraint, mBaseEntries);
    554                 FilterResults fr = new FilterResults();
    555                 fr.values = entries;
    556                 fr.count = entries.size();
    557                 return fr;
    558             }
    559 
    560             @Override
    561             protected void publishResults(CharSequence constraint, FilterResults results) {
    562                 mCurFilterPrefix = constraint;
    563                 mEntries = (ArrayList<ApplicationsState.AppEntry>)results.values;
    564                 notifyDataSetChanged();
    565                 mTab.updateStorageUsage();
    566             }
    567         };
    568 
    569         public ApplicationsAdapter(ApplicationsState state, TabInfo tab, int filterMode) {
    570             mState = state;
    571             mSession = state.newSession(this);
    572             mTab = tab;
    573             mContext = tab.mOwner.getActivity();
    574             mFilterMode = filterMode;
    575         }
    576 
    577         public void resume(int sort) {
    578             if (DEBUG) Log.i(TAG, "Resume!  mResumed=" + mResumed);
    579             if (!mResumed) {
    580                 mResumed = true;
    581                 mSession.resume();
    582                 mLastSortMode = sort;
    583                 rebuild(true);
    584             } else {
    585                 rebuild(sort);
    586             }
    587         }
    588 
    589         public void pause() {
    590             if (mResumed) {
    591                 mResumed = false;
    592                 mSession.pause();
    593             }
    594         }
    595 
    596         public void rebuild(int sort) {
    597             if (sort == mLastSortMode) {
    598                 return;
    599             }
    600             mLastSortMode = sort;
    601             rebuild(true);
    602         }
    603 
    604         public void rebuild(boolean eraseold) {
    605             if (DEBUG) Log.i(TAG, "Rebuilding app list...");
    606             ApplicationsState.AppFilter filterObj;
    607             Comparator<AppEntry> comparatorObj;
    608             boolean emulated = Environment.isExternalStorageEmulated();
    609             if (emulated) {
    610                 mWhichSize = SIZE_TOTAL;
    611             } else {
    612                 mWhichSize = SIZE_INTERNAL;
    613             }
    614             switch (mFilterMode) {
    615                 case FILTER_APPS_THIRD_PARTY:
    616                     filterObj = ApplicationsState.THIRD_PARTY_FILTER;
    617                     break;
    618                 case FILTER_APPS_SDCARD:
    619                     filterObj = ApplicationsState.ON_SD_CARD_FILTER;
    620                     if (!emulated) {
    621                         mWhichSize = SIZE_EXTERNAL;
    622                     }
    623                     break;
    624                 case FILTER_APPS_DISABLED:
    625                     filterObj = ApplicationsState.DISABLED_FILTER;
    626                     break;
    627                 default:
    628                     filterObj = ApplicationsState.ALL_ENABLED_FILTER;
    629                     break;
    630             }
    631             switch (mLastSortMode) {
    632                 case SORT_ORDER_SIZE:
    633                     switch (mWhichSize) {
    634                         case SIZE_INTERNAL:
    635                             comparatorObj = ApplicationsState.INTERNAL_SIZE_COMPARATOR;
    636                             break;
    637                         case SIZE_EXTERNAL:
    638                             comparatorObj = ApplicationsState.EXTERNAL_SIZE_COMPARATOR;
    639                             break;
    640                         default:
    641                             comparatorObj = ApplicationsState.SIZE_COMPARATOR;
    642                             break;
    643                     }
    644                     break;
    645                 default:
    646                     comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
    647                     break;
    648             }
    649             ArrayList<ApplicationsState.AppEntry> entries
    650                     = mSession.rebuild(filterObj, comparatorObj);
    651             if (entries == null && !eraseold) {
    652                 // Don't have new list yet, but can continue using the old one.
    653                 return;
    654             }
    655             mBaseEntries = entries;
    656             if (mBaseEntries != null) {
    657                 mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
    658             } else {
    659                 mEntries = null;
    660             }
    661             notifyDataSetChanged();
    662             mTab.updateStorageUsage();
    663 
    664             if (entries == null) {
    665                 mWaitingForData = true;
    666                 mTab.mListContainer.setVisibility(View.INVISIBLE);
    667                 mTab.mLoadingContainer.setVisibility(View.VISIBLE);
    668             } else {
    669                 mTab.mListContainer.setVisibility(View.VISIBLE);
    670                 mTab.mLoadingContainer.setVisibility(View.GONE);
    671             }
    672         }
    673 
    674         ArrayList<ApplicationsState.AppEntry> applyPrefixFilter(CharSequence prefix,
    675                 ArrayList<ApplicationsState.AppEntry> origEntries) {
    676             if (prefix == null || prefix.length() == 0) {
    677                 return origEntries;
    678             } else {
    679                 String prefixStr = ApplicationsState.normalize(prefix.toString());
    680                 final String spacePrefixStr = " " + prefixStr;
    681                 ArrayList<ApplicationsState.AppEntry> newEntries
    682                         = new ArrayList<ApplicationsState.AppEntry>();
    683                 for (int i=0; i<origEntries.size(); i++) {
    684                     ApplicationsState.AppEntry entry = origEntries.get(i);
    685                     String nlabel = entry.getNormalizedLabel();
    686                     if (nlabel.startsWith(prefixStr) || nlabel.indexOf(spacePrefixStr) != -1) {
    687                         newEntries.add(entry);
    688                     }
    689                 }
    690                 return newEntries;
    691             }
    692         }
    693 
    694         @Override
    695         public void onRunningStateChanged(boolean running) {
    696             mTab.mOwner.getActivity().setProgressBarIndeterminateVisibility(running);
    697         }
    698 
    699         @Override
    700         public void onRebuildComplete(ArrayList<AppEntry> apps) {
    701             if (mTab.mLoadingContainer.getVisibility() == View.VISIBLE) {
    702                 mTab.mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(
    703                         mContext, android.R.anim.fade_out));
    704                 mTab.mListContainer.startAnimation(AnimationUtils.loadAnimation(
    705                         mContext, android.R.anim.fade_in));
    706             }
    707             mTab.mListContainer.setVisibility(View.VISIBLE);
    708             mTab.mLoadingContainer.setVisibility(View.GONE);
    709             mWaitingForData = false;
    710             mBaseEntries = apps;
    711             mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
    712             notifyDataSetChanged();
    713             mTab.updateStorageUsage();
    714         }
    715 
    716         @Override
    717         public void onPackageListChanged() {
    718             rebuild(false);
    719         }
    720 
    721         @Override
    722         public void onPackageIconChanged() {
    723             // We ensure icons are loaded when their item is displayed, so
    724             // don't care about icons loaded in the background.
    725         }
    726 
    727         @Override
    728         public void onPackageSizeChanged(String packageName) {
    729             for (int i=0; i<mActive.size(); i++) {
    730                 AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag();
    731                 if (holder.entry.info.packageName.equals(packageName)) {
    732                     synchronized (holder.entry) {
    733                         holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize);
    734                     }
    735                     if (holder.entry.info.packageName.equals(mTab.mOwner.mCurrentPkgName)
    736                             && mLastSortMode == SORT_ORDER_SIZE) {
    737                         // We got the size information for the last app the
    738                         // user viewed, and are sorting by size...  they may
    739                         // have cleared data, so we immediately want to resort
    740                         // the list with the new size to reflect it to the user.
    741                         rebuild(false);
    742                     }
    743                     mTab.updateStorageUsage();
    744                     return;
    745                 }
    746             }
    747         }
    748 
    749         @Override
    750         public void onAllSizesComputed() {
    751             if (mLastSortMode == SORT_ORDER_SIZE) {
    752                 rebuild(false);
    753             }
    754             mTab.updateStorageUsage();
    755         }
    756 
    757         public int getCount() {
    758             return mEntries != null ? mEntries.size() : 0;
    759         }
    760 
    761         public Object getItem(int position) {
    762             return mEntries.get(position);
    763         }
    764 
    765         public ApplicationsState.AppEntry getAppEntry(int position) {
    766             return mEntries.get(position);
    767         }
    768 
    769         public long getItemId(int position) {
    770             return mEntries.get(position).id;
    771         }
    772 
    773         public View getView(int position, View convertView, ViewGroup parent) {
    774             // A ViewHolder keeps references to children views to avoid unnecessary calls
    775             // to findViewById() on each row.
    776             AppViewHolder holder = AppViewHolder.createOrRecycle(mTab.mInflater, convertView);
    777             convertView = holder.rootView;
    778 
    779             // Bind the data efficiently with the holder
    780             ApplicationsState.AppEntry entry = mEntries.get(position);
    781             synchronized (entry) {
    782                 holder.entry = entry;
    783                 if (entry.label != null) {
    784                     holder.appName.setText(entry.label);
    785                 }
    786                 mState.ensureIcon(entry);
    787                 if (entry.icon != null) {
    788                     holder.appIcon.setImageDrawable(entry.icon);
    789                 }
    790                 holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize);
    791                 if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
    792                     holder.disabled.setVisibility(View.VISIBLE);
    793                     holder.disabled.setText(R.string.not_installed);
    794                 } else if (!entry.info.enabled) {
    795                     holder.disabled.setVisibility(View.VISIBLE);
    796                     holder.disabled.setText(R.string.disabled);
    797                 } else {
    798                     holder.disabled.setVisibility(View.GONE);
    799                 }
    800                 if (mFilterMode == FILTER_APPS_SDCARD) {
    801                     holder.checkBox.setVisibility(View.VISIBLE);
    802                     holder.checkBox.setChecked((entry.info.flags
    803                             & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
    804                 } else {
    805                     holder.checkBox.setVisibility(View.GONE);
    806                 }
    807             }
    808             mActive.remove(convertView);
    809             mActive.add(convertView);
    810             return convertView;
    811         }
    812 
    813         @Override
    814         public Filter getFilter() {
    815             return mFilter;
    816         }
    817 
    818         @Override
    819         public void onMovedToScrapHeap(View view) {
    820             mActive.remove(view);
    821         }
    822     }
    823 
    824     @Override
    825     public void onCreate(Bundle savedInstanceState) {
    826         super.onCreate(savedInstanceState);
    827 
    828         setHasOptionsMenu(true);
    829 
    830         mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication());
    831         Intent intent = getActivity().getIntent();
    832         String action = intent.getAction();
    833         int defaultListType = LIST_TYPE_DOWNLOADED;
    834         String className = getArguments() != null
    835                 ? getArguments().getString("classname") : null;
    836         if (className == null) {
    837             className = intent.getComponent().getClassName();
    838         }
    839         if (className.equals(RunningServicesActivity.class.getName())
    840                 || className.endsWith(".RunningServices")) {
    841             defaultListType = LIST_TYPE_RUNNING;
    842         } else if (className.equals(StorageUseActivity.class.getName())
    843                 || Intent.ACTION_MANAGE_PACKAGE_STORAGE.equals(action)
    844                 || className.endsWith(".StorageUse")) {
    845             mSortOrder = SORT_ORDER_SIZE;
    846             defaultListType = LIST_TYPE_ALL;
    847         } else if (Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS.equals(action)) {
    848             // Select the all-apps list, with the default sorting
    849             defaultListType = LIST_TYPE_ALL;
    850         }
    851 
    852         if (savedInstanceState != null) {
    853             mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
    854             int tmp = savedInstanceState.getInt(EXTRA_DEFAULT_LIST_TYPE, -1);
    855             if (tmp != -1) defaultListType = tmp;
    856             mShowBackground = savedInstanceState.getBoolean(EXTRA_SHOW_BACKGROUND, false);
    857         }
    858 
    859         mDefaultListType = defaultListType;
    860 
    861         final Intent containerIntent = new Intent().setComponent(
    862                 StorageMeasurement.DEFAULT_CONTAINER_COMPONENT);
    863         getActivity().bindService(containerIntent, mContainerConnection, Context.BIND_AUTO_CREATE);
    864 
    865         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
    866         mComputingSizeStr = getActivity().getText(R.string.computing_size);
    867 
    868         TabInfo tab = new TabInfo(this, mApplicationsState,
    869                 getActivity().getString(R.string.filter_apps_third_party),
    870                 LIST_TYPE_DOWNLOADED, this, savedInstanceState);
    871         mTabs.add(tab);
    872 
    873         if (!Environment.isExternalStorageEmulated()) {
    874             tab = new TabInfo(this, mApplicationsState,
    875                     getActivity().getString(R.string.filter_apps_onsdcard),
    876                     LIST_TYPE_SDCARD, this, savedInstanceState);
    877             mTabs.add(tab);
    878         }
    879 
    880         tab = new TabInfo(this, mApplicationsState,
    881                 getActivity().getString(R.string.filter_apps_running),
    882                 LIST_TYPE_RUNNING, this, savedInstanceState);
    883         mTabs.add(tab);
    884 
    885         tab = new TabInfo(this, mApplicationsState,
    886                 getActivity().getString(R.string.filter_apps_all),
    887                 LIST_TYPE_ALL, this, savedInstanceState);
    888         mTabs.add(tab);
    889 
    890         tab = new TabInfo(this, mApplicationsState,
    891                 getActivity().getString(R.string.filter_apps_disabled),
    892                 LIST_TYPE_DISABLED, this, savedInstanceState);
    893         mTabs.add(tab);
    894 
    895         mNumTabs = mTabs.size();
    896     }
    897 
    898 
    899     @Override
    900     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    901         // initialize the inflater
    902         mInflater = inflater;
    903 
    904         View rootView = mInflater.inflate(R.layout.manage_applications_content,
    905                 container, false);
    906         mContentContainer = container;
    907         mRootView = rootView;
    908 
    909         mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
    910         MyPagerAdapter adapter = new MyPagerAdapter();
    911         mViewPager.setAdapter(adapter);
    912         mViewPager.setOnPageChangeListener(adapter);
    913         PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs);
    914         tabs.setTabIndicatorColorResource(android.R.color.holo_blue_light);
    915 
    916         // We have to do this now because PreferenceFrameLayout looks at it
    917         // only when the view is added.
    918         if (container instanceof PreferenceFrameLayout) {
    919             ((PreferenceFrameLayout.LayoutParams) rootView.getLayoutParams()).removeBorders = true;
    920         }
    921 
    922         if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) {
    923             buildResetDialog();
    924         }
    925 
    926         if (savedInstanceState == null) {
    927             // First time init: make sure view pager is showing the correct tab.
    928             for (int i = 0; i < mTabs.size(); i++) {
    929                 TabInfo tab = mTabs.get(i);
    930                 if (tab.mListType == mDefaultListType) {
    931                     mViewPager.setCurrentItem(i);
    932                     break;
    933                 }
    934             }
    935         }
    936 
    937         return rootView;
    938     }
    939 
    940     @Override
    941     public void onStart() {
    942         super.onStart();
    943     }
    944 
    945     @Override
    946     public void onResume() {
    947         super.onResume();
    948         mActivityResumed = true;
    949         updateCurrentTab(mViewPager.getCurrentItem());
    950         updateNumTabs();
    951         updateOptionsMenu();
    952     }
    953 
    954     @Override
    955     public void onSaveInstanceState(Bundle outState) {
    956         super.onSaveInstanceState(outState);
    957         outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
    958         if (mDefaultListType != -1) {
    959             outState.putInt(EXTRA_DEFAULT_LIST_TYPE, mDefaultListType);
    960         }
    961         outState.putBoolean(EXTRA_SHOW_BACKGROUND, mShowBackground);
    962         if (mResetDialog != null) {
    963             outState.putBoolean(EXTRA_RESET_DIALOG, true);
    964         }
    965     }
    966 
    967     @Override
    968     public void onPause() {
    969         super.onPause();
    970         mActivityResumed = false;
    971         for (int i=0; i<mTabs.size(); i++) {
    972             mTabs.get(i).pause();
    973         }
    974     }
    975 
    976     @Override
    977     public void onStop() {
    978         super.onStop();
    979         if (mResetDialog != null) {
    980             mResetDialog.dismiss();
    981             mResetDialog = null;
    982         }
    983     }
    984 
    985     @Override
    986     public void onDestroyView() {
    987         super.onDestroyView();
    988 
    989         // We are going to keep the tab data structures around, but they
    990         // are no longer attached to their view hierarchy.
    991         for (int i=0; i<mTabs.size(); i++) {
    992             mTabs.get(i).detachView();
    993         }
    994     }
    995 
    996     @Override
    997     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    998         if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
    999             mApplicationsState.requestSize(mCurrentPkgName);
   1000         }
   1001     }
   1002 
   1003     private void updateNumTabs() {
   1004         int newNum = mApplicationsState.haveDisabledApps() ? mTabs.size() : (mTabs.size()-1);
   1005         if (newNum != mNumTabs) {
   1006             mNumTabs = newNum;
   1007             if (mViewPager != null) {
   1008                 mViewPager.getAdapter().notifyDataSetChanged();
   1009             }
   1010         }
   1011     }
   1012 
   1013     TabInfo tabForType(int type) {
   1014         for (int i = 0; i < mTabs.size(); i++) {
   1015             TabInfo tab = mTabs.get(i);
   1016             if (tab.mListType == type) {
   1017                 return tab;
   1018             }
   1019         }
   1020         return null;
   1021     }
   1022 
   1023     // utility method used to start sub activity
   1024     private void startApplicationDetailsActivity() {
   1025         // start new fragment to display extended information
   1026         Bundle args = new Bundle();
   1027         args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);
   1028 
   1029         PreferenceActivity pa = (PreferenceActivity)getActivity();
   1030         pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
   1031                 R.string.application_info_label, null, this, INSTALLED_APP_DETAILS);
   1032     }
   1033 
   1034     @Override
   1035     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
   1036         mOptionsMenu = menu;
   1037         // note: icons removed for now because the cause the new action
   1038         // bar UI to be very confusing.
   1039         menu.add(0, SORT_ORDER_ALPHA, 1, R.string.sort_order_alpha)
   1040                 //.setIcon(android.R.drawable.ic_menu_sort_alphabetically)
   1041                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
   1042         menu.add(0, SORT_ORDER_SIZE, 2, R.string.sort_order_size)
   1043                 //.setIcon(android.R.drawable.ic_menu_sort_by_size)
   1044                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
   1045         menu.add(0, SHOW_RUNNING_SERVICES, 3, R.string.show_running_services)
   1046                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
   1047         menu.add(0, SHOW_BACKGROUND_PROCESSES, 3, R.string.show_background_processes)
   1048                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
   1049         menu.add(0, RESET_APP_PREFERENCES, 4, R.string.reset_app_preferences)
   1050                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
   1051         updateOptionsMenu();
   1052     }
   1053 
   1054     @Override
   1055     public void onPrepareOptionsMenu(Menu menu) {
   1056         updateOptionsMenu();
   1057     }
   1058 
   1059     @Override
   1060     public void onDestroyOptionsMenu() {
   1061         mOptionsMenu = null;
   1062     }
   1063 
   1064     @Override
   1065     public void onDestroy() {
   1066         getActivity().unbindService(mContainerConnection);
   1067         super.onDestroy();
   1068     }
   1069 
   1070     void updateOptionsMenu() {
   1071         if (mOptionsMenu == null) {
   1072             return;
   1073         }
   1074 
   1075         /*
   1076          * The running processes screen doesn't use the mApplicationsAdapter
   1077          * so bringing up this menu in that case doesn't make any sense.
   1078          */
   1079         if (mCurTab != null && mCurTab.mListType == LIST_TYPE_RUNNING) {
   1080             TabInfo tab = tabForType(LIST_TYPE_RUNNING);
   1081             boolean showingBackground = tab != null && tab.mRunningProcessesView != null
   1082                     ? tab.mRunningProcessesView.mAdapter.getShowBackground() : false;
   1083             mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(false);
   1084             mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(false);
   1085             mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(showingBackground);
   1086             mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(!showingBackground);
   1087             mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(false);
   1088         } else {
   1089             mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
   1090             mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder != SORT_ORDER_SIZE);
   1091             mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(false);
   1092             mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(false);
   1093             mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(true);
   1094         }
   1095     }
   1096 
   1097     void buildResetDialog() {
   1098         if (mResetDialog == null) {
   1099             AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
   1100             builder.setTitle(R.string.reset_app_preferences_title);
   1101             builder.setMessage(R.string.reset_app_preferences_desc);
   1102             builder.setPositiveButton(R.string.reset_app_preferences_button, this);
   1103             builder.setNegativeButton(R.string.cancel, null);
   1104             mResetDialog = builder.show();
   1105             mResetDialog.setOnDismissListener(this);
   1106         }
   1107     }
   1108 
   1109     @Override
   1110     public void onDismiss(DialogInterface dialog) {
   1111         if (mResetDialog == dialog) {
   1112             mResetDialog = null;
   1113         }
   1114     }
   1115 
   1116 
   1117     @Override
   1118     public void onClick(DialogInterface dialog, int which) {
   1119         if (mResetDialog == dialog) {
   1120             final PackageManager pm = getActivity().getPackageManager();
   1121             final IPackageManager mIPm = IPackageManager.Stub.asInterface(
   1122                     ServiceManager.getService("package"));
   1123             final INotificationManager nm = INotificationManager.Stub.asInterface(
   1124                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
   1125             final NetworkPolicyManager npm = NetworkPolicyManager.from(getActivity());
   1126             final AppOpsManager aom = (AppOpsManager)getActivity().getSystemService(
   1127                     Context.APP_OPS_SERVICE);
   1128             final Handler handler = new Handler(getActivity().getMainLooper());
   1129             (new AsyncTask<Void, Void, Void>() {
   1130                 @Override protected Void doInBackground(Void... params) {
   1131                     List<ApplicationInfo> apps = pm.getInstalledApplications(
   1132                             PackageManager.GET_DISABLED_COMPONENTS);
   1133                     for (int i=0; i<apps.size(); i++) {
   1134                         ApplicationInfo app = apps.get(i);
   1135                         try {
   1136                             if (DEBUG) Log.v(TAG, "Enabling notifications: " + app.packageName);
   1137                             nm.setNotificationsEnabledForPackage(app.packageName, app.uid, true);
   1138                         } catch (android.os.RemoteException ex) {
   1139                         }
   1140                         if (!app.enabled) {
   1141                             if (DEBUG) Log.v(TAG, "Enabling app: " + app.packageName);
   1142                             if (pm.getApplicationEnabledSetting(app.packageName)
   1143                                     == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
   1144                                 pm.setApplicationEnabledSetting(app.packageName,
   1145                                         PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
   1146                                         PackageManager.DONT_KILL_APP);
   1147                             }
   1148                         }
   1149                     }
   1150                     try {
   1151                         mIPm.resetPreferredActivities(UserHandle.myUserId());
   1152                     } catch (RemoteException e) {
   1153                     }
   1154                     aom.resetAllModes();
   1155                     final int[] restrictedUids = npm.getUidsWithPolicy(
   1156                             POLICY_REJECT_METERED_BACKGROUND);
   1157                     final int currentUserId = ActivityManager.getCurrentUser();
   1158                     for (int uid : restrictedUids) {
   1159                         // Only reset for current user
   1160                         if (UserHandle.getUserId(uid) == currentUserId) {
   1161                             if (DEBUG) Log.v(TAG, "Clearing data policy: " + uid);
   1162                             npm.setUidPolicy(uid, POLICY_NONE);
   1163                         }
   1164                     }
   1165                     handler.post(new Runnable() {
   1166                         @Override public void run() {
   1167                             if (DEBUG) Log.v(TAG, "Done clearing");
   1168                             if (getActivity() != null && mActivityResumed) {
   1169                                 if (DEBUG) Log.v(TAG, "Updating UI!");
   1170                                 for (int i=0; i<mTabs.size(); i++) {
   1171                                     TabInfo tab = mTabs.get(i);
   1172                                     if (tab.mApplications != null) {
   1173                                         tab.mApplications.pause();
   1174                                     }
   1175                                 }
   1176                                 if (mCurTab != null) {
   1177                                     mCurTab.resume(mSortOrder);
   1178                                 }
   1179                             }
   1180                         }
   1181                     });
   1182                     return null;
   1183                 }
   1184             }).execute();
   1185         }
   1186     }
   1187 
   1188     @Override
   1189     public boolean onOptionsItemSelected(MenuItem item) {
   1190         int menuId = item.getItemId();
   1191         if ((menuId == SORT_ORDER_ALPHA) || (menuId == SORT_ORDER_SIZE)) {
   1192             mSortOrder = menuId;
   1193             if (mCurTab != null && mCurTab.mApplications != null) {
   1194                 mCurTab.mApplications.rebuild(mSortOrder);
   1195             }
   1196         } else if (menuId == SHOW_RUNNING_SERVICES) {
   1197             mShowBackground = false;
   1198             if (mCurTab != null && mCurTab.mRunningProcessesView != null) {
   1199                 mCurTab.mRunningProcessesView.mAdapter.setShowBackground(false);
   1200             }
   1201         } else if (menuId == SHOW_BACKGROUND_PROCESSES) {
   1202             mShowBackground = true;
   1203             if (mCurTab != null && mCurTab.mRunningProcessesView != null) {
   1204                 mCurTab.mRunningProcessesView.mAdapter.setShowBackground(true);
   1205             }
   1206         } else if (menuId == RESET_APP_PREFERENCES) {
   1207             buildResetDialog();
   1208         } else {
   1209             // Handle the home button
   1210             return false;
   1211         }
   1212         updateOptionsMenu();
   1213         return true;
   1214     }
   1215 
   1216     public void onItemClick(TabInfo tab, AdapterView<?> parent, View view, int position,
   1217             long id) {
   1218         if (tab.mApplications != null && tab.mApplications.getCount() > position) {
   1219             ApplicationsState.AppEntry entry = tab.mApplications.getAppEntry(position);
   1220             mCurrentPkgName = entry.info.packageName;
   1221             startApplicationDetailsActivity();
   1222         }
   1223     }
   1224 
   1225     public void updateCurrentTab(int position) {
   1226         TabInfo tab = mTabs.get(position);
   1227         mCurTab = tab;
   1228 
   1229         // Put things in the correct paused/resumed state.
   1230         if (mActivityResumed) {
   1231             mCurTab.build(mInflater, mContentContainer, mRootView);
   1232             mCurTab.resume(mSortOrder);
   1233         } else {
   1234             mCurTab.pause();
   1235         }
   1236         for (int i=0; i<mTabs.size(); i++) {
   1237             TabInfo t = mTabs.get(i);
   1238             if (t != mCurTab) {
   1239                 t.pause();
   1240             }
   1241         }
   1242 
   1243         mCurTab.updateStorageUsage();
   1244         updateOptionsMenu();
   1245         final Activity host = getActivity();
   1246         if (host != null) {
   1247             host.invalidateOptionsMenu();
   1248         }
   1249     }
   1250 
   1251     private volatile IMediaContainerService mContainerService;
   1252 
   1253     private final ServiceConnection mContainerConnection = new ServiceConnection() {
   1254         @Override
   1255         public void onServiceConnected(ComponentName name, IBinder service) {
   1256             mContainerService = IMediaContainerService.Stub.asInterface(service);
   1257             for (int i=0; i<mTabs.size(); i++) {
   1258                 mTabs.get(i).setContainerService(mContainerService);
   1259             }
   1260         }
   1261 
   1262         @Override
   1263         public void onServiceDisconnected(ComponentName name) {
   1264             mContainerService = null;
   1265         }
   1266     };
   1267 }
   1268