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