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