OSDN Git Service

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