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