diff --git a/Android.mk b/Android.mk index c08be7f32c7..38732bb4cea 100644 --- a/Android.mk +++ b/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_JAVA_LIBRARIES := bouncycastle -LOCAL_STATIC_JAVA_LIBRARIES := guava +LOCAL_STATIC_JAVA_LIBRARIES := guava android-support-v4 LOCAL_MODULE_TAGS := optional diff --git a/res/layout/manage_applications.xml b/res/layout/manage_applications_apps.xml old mode 100755 new mode 100644 similarity index 93% rename from res/layout/manage_applications.xml rename to res/layout/manage_applications_apps.xml index da56c99647e..51ab4127a8f --- a/res/layout/manage_applications.xml +++ b/res/layout/manage_applications_apps.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + diff --git a/res/layout/manage_applications_running.xml b/res/layout/manage_applications_running.xml new file mode 100644 index 00000000000..634de1c7b87 --- /dev/null +++ b/res/layout/manage_applications_running.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + diff --git a/res/layout/manage_apps_spinner_content.xml b/res/layout/manage_apps_spinner_content.xml deleted file mode 100644 index cbf0a407cc3..00000000000 --- a/res/layout/manage_apps_spinner_content.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/com/android/settings/applications/AppViewHolder.java b/src/com/android/settings/applications/AppViewHolder.java index 2a12f9b50a5..d23f187431e 100644 --- a/src/com/android/settings/applications/AppViewHolder.java +++ b/src/com/android/settings/applications/AppViewHolder.java @@ -42,7 +42,7 @@ public class AppViewHolder { } } - void updateSizeText(ManageApplications ma, int whichSize) { + void updateSizeText(CharSequence invalidSizeStr, int whichSize) { if (ManageApplications.DEBUG) Log.i(ManageApplications.TAG, "updateSizeText of " + entry.label + " " + entry + ": " + entry.sizeStr); if (entry.sizeStr != null) { @@ -58,7 +58,7 @@ public class AppViewHolder { break; } } else if (entry.size == ApplicationsState.SIZE_INVALID) { - appSize.setText(ma.mInvalidSizeStr); + appSize.setText(invalidSizeStr); } } } \ No newline at end of file diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java index 799b34a2170..0a5c26e0c3e 100644 --- a/src/com/android/settings/applications/ApplicationsState.java +++ b/src/com/android/settings/applications/ApplicationsState.java @@ -227,24 +227,21 @@ public class ApplicationsState { PackageIntentReceiver mPackageIntentReceiver; boolean mResumed; - Callbacks mCurCallbacks; - // Information about all applications. Synchronize on mAppEntries + // Information about all applications. Synchronize on mEntriesMap // to protect access to these. + final ArrayList mSessions = new ArrayList(); + final ArrayList mRebuildingSessions = new ArrayList(); final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges(); final HashMap mEntriesMap = new HashMap(); final ArrayList mAppEntries = new ArrayList(); List mApplications = new ArrayList(); long mCurId = 1; String mCurComputingSizePkg; + boolean mSessionsChanged; - // Rebuilding of app list. Synchronized on mRebuildSync. - final Object mRebuildSync = new Object(); - boolean mRebuildRequested; - boolean mRebuildAsync; - AppFilter mRebuildFilter; - Comparator mRebuildComparator; - ArrayList mRebuildResult; + // Temporary for dispatching session callbacks. Only touched by main thread. + final ArrayList mActiveSessions = new ArrayList(); /** * Receives notifications when applications are added/removed. @@ -262,6 +259,9 @@ public class ApplicationsState { sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mContext.registerReceiver(this, sdFilter); } + void unregisterReceiver() { + mContext.unregisterReceiver(this); + } @Override public void onReceive(Context context, Intent intent) { String actionStr = intent.getAction(); @@ -300,6 +300,21 @@ public class ApplicationsState { } } + void rebuildActiveSessions() { + synchronized (mEntriesMap) { + if (!mSessionsChanged) { + return; + } + mActiveSessions.clear(); + for (int i=0; i)msg.obj); + Session s = (Session)msg.obj; + if (mActiveSessions.contains(s)) { + s.mCallbacks.onRebuildComplete(s.mLastAppList); } } break; case MSG_PACKAGE_LIST_CHANGED: { - if (mCurCallbacks != null) { - mCurCallbacks.onPackageListChanged(); + for (int i=0; i(); - } + public class Session { + final Callbacks mCallbacks; + boolean mResumed; - if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { - // If an interesting part of the configuration has changed, we - // should completely reload the app entries. - mEntriesMap.clear(); - mAppEntries.clear(); - } else { - for (int i=0; i mRebuildComparator; + ArrayList mRebuildResult; + ArrayList mLastAppList; - for (int i=0; i rebuild(AppFilter filter, Comparator comparator) { - synchronized (mRebuildSync) { - mRebuildRequested = true; - mRebuildAsync = false; - mRebuildFilter = filter; - mRebuildComparator = comparator; - mRebuildResult = null; - if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) { - mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_REBUILD_LIST); - } - - // We will wait for .25s for the list to be built. - long waitend = SystemClock.uptimeMillis()+250; - - while (mRebuildResult == null) { - long now = SystemClock.uptimeMillis(); - if (now >= waitend) { - break; - } - try { - mRebuildSync.wait(waitend - now); - } catch (InterruptedException e) { + public void pause() { + if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock..."); + synchronized (mEntriesMap) { + if (mResumed) { + mResumed = false; + mSessionsChanged = true; + mBackgroundHandler.removeMessages(BackgroundHandler.MSG_REBUILD_LIST, this); + doPauseIfNeededLocked(); } + if (DEBUG_LOCKING) Log.v(TAG, "...pause releasing lock"); } - - mRebuildAsync = true; - - return mRebuildResult; - } - } - - void handleRebuildList() { - AppFilter filter; - Comparator comparator; - synchronized (mRebuildSync) { - if (!mRebuildRequested) { - return; - } - - filter = mRebuildFilter; - comparator = mRebuildComparator; - mRebuildRequested = false; - mRebuildFilter = null; - mRebuildComparator = null; } - Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); - - if (filter != null) { - filter.init(); - } - - List apps; - synchronized (mEntriesMap) { - apps = new ArrayList(mApplications); - } - - ArrayList filteredApps = new ArrayList(); - if (DEBUG) Log.i(TAG, "Rebuilding..."); - for (int i=0; i rebuild(AppFilter filter, Comparator comparator) { + synchronized (mRebuildSync) { synchronized (mEntriesMap) { - if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock"); - AppEntry entry = getEntryLocked(info); - entry.ensureLabel(mContext); - if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry); - filteredApps.add(entry); - if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock"); + mRebuildingSessions.add(this); + mRebuildRequested = true; + mRebuildAsync = false; + mRebuildFilter = filter; + mRebuildComparator = comparator; + mRebuildResult = null; + if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) { + Message msg = mBackgroundHandler.obtainMessage( + BackgroundHandler.MSG_REBUILD_LIST); + mBackgroundHandler.sendMessage(msg); + } } + + // We will wait for .25s for the list to be built. + long waitend = SystemClock.uptimeMillis()+250; + + while (mRebuildResult == null) { + long now = SystemClock.uptimeMillis(); + if (now >= waitend) { + break; + } + try { + mRebuildSync.wait(waitend - now); + } catch (InterruptedException e) { + } + } + + mRebuildAsync = true; + + return mRebuildResult; } } - Collections.sort(filteredApps, comparator); + void handleRebuildList() { + AppFilter filter; + Comparator comparator; + synchronized (mRebuildSync) { + if (!mRebuildRequested) { + return; + } - synchronized (mRebuildSync) { - if (!mRebuildRequested) { - if (!mRebuildAsync) { - mRebuildResult = filteredApps; - mRebuildSync.notifyAll(); - } else { - if (!mMainHandler.hasMessages(MainHandler.MSG_REBUILD_COMPLETE)) { - Message msg = mMainHandler.obtainMessage( - MainHandler.MSG_REBUILD_COMPLETE, filteredApps); - mMainHandler.sendMessage(msg); + filter = mRebuildFilter; + comparator = mRebuildComparator; + mRebuildRequested = false; + mRebuildFilter = null; + mRebuildComparator = null; + } + + Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); + + if (filter != null) { + filter.init(); + } + + List apps; + synchronized (mEntriesMap) { + apps = new ArrayList(mApplications); + } + + ArrayList filteredApps = new ArrayList(); + if (DEBUG) Log.i(TAG, "Rebuilding..."); + for (int i=0; i(); + } + + if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { + // If an interesting part of the configuration has changed, we + // should completely reload the app entries. + mEntriesMap.clear(); + mAppEntries.clear(); + } else { + for (int i=0; i rebuildingSessions = null; + synchronized (mEntriesMap) { + if (mRebuildingSessions.size() > 0) { + rebuildingSessions = new ArrayList(mRebuildingSessions); + mRebuildingSessions.clear(); + } + } + if (rebuildingSessions != null) { + for (int i=0; i 0) { + mColorBar.setRatios((totalStorage-freeStorage-appStorage)/(float)totalStorage, + appStorage/(float)totalStorage, freeStorage/(float)totalStorage); + long usedStorage = totalStorage - freeStorage; + if (mLastUsedStorage != usedStorage) { + mLastUsedStorage = usedStorage; + String sizeStr = Formatter.formatShortFileSize( + mOwner.getActivity(), usedStorage); + mUsedStorageText.setText(mOwner.getActivity().getResources().getString( + R.string.service_foreground_processes, sizeStr)); + } + if (mLastFreeStorage != freeStorage) { + mLastFreeStorage = freeStorage; + String sizeStr = Formatter.formatShortFileSize( + mOwner.getActivity(), freeStorage); + mFreeStorageText.setText(mOwner.getActivity().getResources().getString( + R.string.service_background_processes, sizeStr)); + } + } else { + mColorBar.setRatios(0, 0, 0); + if (mLastUsedStorage != -1) { + mLastUsedStorage = -1; + mUsedStorageText.setText(""); + } + if (mLastFreeStorage != -1) { + mLastFreeStorage = -1; + mFreeStorageText.setText(""); + } + } + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + mClickListener.onItemClick(parent, view, position, id); + } + + void handleRunningProcessesAvail() { + mLoadingContainer.startAnimation(AnimationUtils.loadAnimation( + mOwner.getActivity(), android.R.anim.fade_out)); + mRunningProcessesView.startAnimation(AnimationUtils.loadAnimation( + mOwner.getActivity(), android.R.anim.fade_in)); + mRunningProcessesView.setVisibility(View.VISIBLE); + mLoadingContainer.setVisibility(View.GONE); + } + } + private final ArrayList mTabs = new ArrayList(); + TabInfo mCurTab = null; + // Size resource used for packages whose size computation failed for some reason CharSequence mInvalidSizeStr; private CharSequence mComputingSizeStr; @@ -180,59 +415,72 @@ public class ManageApplications extends Fragment implements private String mCurrentPkgName; - private View mLoadingContainer; - - private View mListContainer; - - // ListView used to display list - private ListView mListView; - // Custom view used to display running processes - private RunningProcessesView mRunningProcessesView; - - LinearColorBar mColorBar; - TextView mStorageChartLabel; - TextView mUsedStorageText; - TextView mFreeStorageText; - private Menu mOptionsMenu; // These are for keeping track of activity and spinner switch state. - private int mCurView; - private boolean mCreatedRunning; - - private boolean mResumedRunning; private boolean mActivityResumed; - private boolean mLastShowedInternalStorage = true; - private long mLastUsedStorage, mLastAppStorage, mLastFreeStorage; - static final int LIST_TYPE_DOWNLOADED = 0; static final int LIST_TYPE_RUNNING = 1; static final int LIST_TYPE_SDCARD = 2; static final int LIST_TYPE_ALL = 3; - private View mRootView; private boolean mShowBackground = false; private int mDefaultListType = -1; - private SparseIntArray mIndexToType = new SparseIntArray(4); - private Spinner mSpinner; - private FrameLayout mSpinnerContent; + private ViewGroup mContentContainer; + private View mRootView; + private ViewPager mViewPager; AlertDialog mResetDialog; - final Runnable mRunningProcessesAvail = new Runnable() { - public void run() { - handleRunningProcessesAvail(); + class MyPagerAdapter extends PagerAdapter + implements ViewPager.OnPageChangeListener { + int mCurPos = 0; + + @Override + public int getCount() { + return mTabs.size(); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + TabInfo tab = mTabs.get(position); + View root = tab.build(mInflater, mContentContainer, mRootView); + container.addView(root); + return root; } - }; - static class AppFilterAdapter extends ArrayAdapter { + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View)object); + } - public AppFilterAdapter(Context context) { - super(context, R.layout.apps_spinner_item); - setDropDownViewResource(R.layout.apps_spinner_dropdown_item); + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public CharSequence getPageTitle(int position) { + return mTabs.get(position).mLabel; + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + mCurPos = position; + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == ViewPager.SCROLL_STATE_IDLE) { + updateCurrentTab(mCurPos); + } } } @@ -245,14 +493,18 @@ public class ManageApplications extends Fragment implements * the getId methods via the package name into the internal maps and indices. * The order of applications in the list is mirrored in mAppLocalList */ - class ApplicationsAdapter extends BaseAdapter implements Filterable, + static class ApplicationsAdapter extends BaseAdapter implements Filterable, ApplicationsState.Callbacks, AbsListView.RecyclerListener { private final ApplicationsState mState; + private final ApplicationsState.Session mSession; + private final TabInfo mTab; + private final Context mContext; private final ArrayList mActive = new ArrayList(); + private final int mFilterMode; private ArrayList mBaseEntries; private ArrayList mEntries; private boolean mResumed; - private int mLastFilterMode=-1, mLastSortMode=-1; + private int mLastSortMode=-1; private boolean mWaitingForData; private int mWhichSize = SIZE_TOTAL; CharSequence mCurFilterPrefix; @@ -273,39 +525,41 @@ public class ManageApplications extends Fragment implements mCurFilterPrefix = constraint; mEntries = (ArrayList)results.values; notifyDataSetChanged(); - updateStorageUsage(); + mTab.updateStorageUsage(); } }; - public ApplicationsAdapter(ApplicationsState state) { + public ApplicationsAdapter(ApplicationsState state, TabInfo tab, int filterMode) { mState = state; + mSession = state.newSession(this); + mTab = tab; + mContext = tab.mOwner.getActivity(); + mFilterMode = filterMode; } - public void resume(int filter, int sort) { + public void resume(int sort) { if (DEBUG) Log.i(TAG, "Resume! mResumed=" + mResumed); if (!mResumed) { mResumed = true; - mState.resume(this); - mLastFilterMode = filter; + mSession.resume(); mLastSortMode = sort; rebuild(true); } else { - rebuild(filter, sort); + rebuild(sort); } } public void pause() { if (mResumed) { mResumed = false; - mState.pause(); + mSession.pause(); } } - public void rebuild(int filter, int sort) { - if (filter == mLastFilterMode && sort == mLastSortMode) { + public void rebuild(int sort) { + if (sort == mLastSortMode) { return; } - mLastFilterMode = filter; mLastSortMode = sort; rebuild(true); } @@ -320,7 +574,7 @@ public class ManageApplications extends Fragment implements } else { mWhichSize = SIZE_INTERNAL; } - switch (mLastFilterMode) { + switch (mFilterMode) { case FILTER_APPS_THIRD_PARTY: filterObj = ApplicationsState.THIRD_PARTY_FILTER; break; @@ -353,7 +607,7 @@ public class ManageApplications extends Fragment implements break; } ArrayList entries - = mState.rebuild(filterObj, comparatorObj); + = mSession.rebuild(filterObj, comparatorObj); if (entries == null && !eraseold) { // Don't have new list yet, but can continue using the old one. return; @@ -365,15 +619,15 @@ public class ManageApplications extends Fragment implements mEntries = null; } notifyDataSetChanged(); - updateStorageUsage(); + mTab.updateStorageUsage(); if (entries == null) { mWaitingForData = true; - mListContainer.setVisibility(View.INVISIBLE); - mLoadingContainer.setVisibility(View.VISIBLE); + mTab.mListContainer.setVisibility(View.INVISIBLE); + mTab.mLoadingContainer.setVisibility(View.VISIBLE); } else { - mListContainer.setVisibility(View.VISIBLE); - mLoadingContainer.setVisibility(View.GONE); + mTab.mListContainer.setVisibility(View.VISIBLE); + mTab.mLoadingContainer.setVisibility(View.GONE); } } @@ -399,24 +653,24 @@ public class ManageApplications extends Fragment implements @Override public void onRunningStateChanged(boolean running) { - getActivity().setProgressBarIndeterminateVisibility(running); + mTab.mOwner.getActivity().setProgressBarIndeterminateVisibility(running); } @Override public void onRebuildComplete(ArrayList apps) { - if (mLoadingContainer.getVisibility() == View.VISIBLE) { - mLoadingContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - mListContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); + if (mTab.mLoadingContainer.getVisibility() == View.VISIBLE) { + mTab.mLoadingContainer.startAnimation(AnimationUtils.loadAnimation( + mContext, android.R.anim.fade_out)); + mTab.mListContainer.startAnimation(AnimationUtils.loadAnimation( + mContext, android.R.anim.fade_in)); } - mListContainer.setVisibility(View.VISIBLE); - mLoadingContainer.setVisibility(View.GONE); + mTab.mListContainer.setVisibility(View.VISIBLE); + mTab.mLoadingContainer.setVisibility(View.GONE); mWaitingForData = false; mBaseEntries = apps; mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries); notifyDataSetChanged(); - updateStorageUsage(); + mTab.updateStorageUsage(); } @Override @@ -436,9 +690,9 @@ public class ManageApplications extends Fragment implements AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag(); if (holder.entry.info.packageName.equals(packageName)) { synchronized (holder.entry) { - holder.updateSizeText(ManageApplications.this, mWhichSize); + holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize); } - if (holder.entry.info.packageName.equals(mCurrentPkgName) + if (holder.entry.info.packageName.equals(mTab.mOwner.mCurrentPkgName) && mLastSortMode == SORT_ORDER_SIZE) { // We got the size information for the last app the // user viewed, and are sorting by size... they may @@ -446,7 +700,7 @@ public class ManageApplications extends Fragment implements // the list with the new size to reflect it to the user. rebuild(false); } - updateStorageUsage(); + mTab.updateStorageUsage(); return; } } @@ -478,7 +732,7 @@ public class ManageApplications extends Fragment implements public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unnecessary calls // to findViewById() on each row. - AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView); + AppViewHolder holder = AppViewHolder.createOrRecycle(mTab.mInflater, convertView); convertView = holder.rootView; // Bind the data efficiently with the holder @@ -487,7 +741,7 @@ public class ManageApplications extends Fragment implements holder.entry = entry; if (entry.label != null) { holder.appName.setText(entry.label); - holder.appName.setTextColor(getActivity().getResources().getColorStateList( + holder.appName.setTextColor(mContext.getResources().getColorStateList( entry.info.enabled ? android.R.color.primary_text_dark : android.R.color.secondary_text_dark)); } @@ -495,13 +749,13 @@ public class ManageApplications extends Fragment implements if (entry.icon != null) { holder.appIcon.setImageDrawable(entry.icon); } - holder.updateSizeText(ManageApplications.this, mWhichSize); + holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize); if (InstalledAppDetails.SUPPORT_DISABLE_APPS) { holder.disabled.setVisibility(entry.info.enabled ? View.GONE : View.VISIBLE); } else { holder.disabled.setVisibility(View.GONE); } - if (mLastFilterMode == FILTER_APPS_SDCARD) { + if (mFilterMode == FILTER_APPS_SDCARD) { holder.checkBox.setVisibility(View.VISIBLE); holder.checkBox.setChecked((entry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); @@ -532,7 +786,6 @@ public class ManageApplications extends Fragment implements setHasOptionsMenu(true); mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication()); - mApplicationsAdapter = new ApplicationsAdapter(mApplicationsState); Intent intent = getActivity().getIntent(); String action = intent.getAction(); int defaultListType = LIST_TYPE_DOWNLOADED; @@ -571,6 +824,28 @@ public class ManageApplications extends Fragment implements mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value); mComputingSizeStr = getActivity().getText(R.string.computing_size); + + TabInfo tab = new TabInfo(this, mApplicationsState, mContainerService, + getActivity().getString(R.string.filter_apps_third_party), + LIST_TYPE_DOWNLOADED, this, savedInstanceState); + mTabs.add(tab); + + if (!Environment.isExternalStorageEmulated()) { + tab = new TabInfo(this, mApplicationsState, mContainerService, + getActivity().getString(R.string.filter_apps_onsdcard), + LIST_TYPE_SDCARD, this, savedInstanceState); + mTabs.add(tab); + } + + tab = new TabInfo(this, mApplicationsState, mContainerService, + getActivity().getString(R.string.filter_apps_running), + LIST_TYPE_RUNNING, this, savedInstanceState); + mTabs.add(tab); + + tab = new TabInfo(this, mApplicationsState, mContainerService, + getActivity().getString(R.string.filter_apps_all), + LIST_TYPE_ALL, this, savedInstanceState); + mTabs.add(tab); } @@ -578,75 +853,24 @@ public class ManageApplications extends Fragment implements public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // initialize the inflater mInflater = inflater; - mRootView = inflater.inflate(R.layout.manage_applications, null); - mLoadingContainer = mRootView.findViewById(R.id.loading_container); - mListContainer = mRootView.findViewById(R.id.list_container); - // Create adapter and list view here - ListView lv = (ListView) mListContainer.findViewById(android.R.id.list); - View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty); - if (emptyView != null) { - lv.setEmptyView(emptyView); - } - lv.setOnItemClickListener(this); - lv.setSaveEnabled(true); - lv.setItemsCanFocus(true); - lv.setOnItemClickListener(this); - lv.setTextFilterEnabled(true); - mListView = lv; - lv.setRecyclerListener(mApplicationsAdapter); - mListView.setAdapter(mApplicationsAdapter); - mColorBar = (LinearColorBar)mListContainer.findViewById(R.id.storage_color_bar); - mStorageChartLabel = (TextView)mListContainer.findViewById(R.id.storageChartLabel); - mUsedStorageText = (TextView)mListContainer.findViewById(R.id.usedStorageText); - mFreeStorageText = (TextView)mListContainer.findViewById(R.id.freeStorageText); - mRunningProcessesView = (RunningProcessesView)mRootView.findViewById( - R.id.running_processes); - mCreatedRunning = mResumedRunning = false; - mCurView = VIEW_NOTHING; - - View spinnerHost = mInflater.inflate(R.layout.manage_apps_spinner_content, + View rootView = mInflater.inflate(R.layout.manage_applications_content, container, false); + mContentContainer = container; + mRootView = rootView; - mSpinner = (Spinner) spinnerHost.findViewById(R.id.spinner); - mSpinnerContent = (FrameLayout) spinnerHost.findViewById(R.id.spinner_content); - mSpinnerContent.addView(mRootView); - - AppFilterAdapter sa = new AppFilterAdapter(getActivity()); - mIndexToType.append(sa.getCount(), LIST_TYPE_DOWNLOADED); - sa.add(getActivity().getString(R.string.filter_apps_third_party)); - if (!Environment.isExternalStorageEmulated()) { - mIndexToType.append(sa.getCount(), LIST_TYPE_SDCARD); - sa.add(getActivity().getString(R.string.filter_apps_onsdcard)); - } - mIndexToType.append(sa.getCount(), LIST_TYPE_RUNNING); - sa.add(getActivity().getString(R.string.filter_apps_running)); - mIndexToType.append(sa.getCount(), LIST_TYPE_ALL); - sa.add(getActivity().getString(R.string.filter_apps_all)); - - mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, - View view, int position, long id) { - showCurrentList(); - } - @Override - public void onNothingSelected(AdapterView parent) { - // Nothing - } - - }); - - mSpinner.setSelection(getIndex(mDefaultListType)); - mSpinner.setAdapter(sa); - - prepareCustomPreferencesList(container, spinnerHost, mListView, false); + mViewPager = (ViewPager) rootView.findViewById(R.id.pager); + MyPagerAdapter adapter = new MyPagerAdapter(); + mViewPager.setAdapter(adapter); + mViewPager.setOnPageChangeListener(adapter); + PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs); + tabs.setTabIndicatorColorResource(android.R.color.holo_blue_light); if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) { buildResetDialog(); } - return spinnerHost; + return rootView; } @Override @@ -658,10 +882,8 @@ public class ManageApplications extends Fragment implements public void onResume() { super.onResume(); mActivityResumed = true; - showCurrentList(); + updateCurrentTab(mViewPager.getCurrentItem()); updateOptionsMenu(); - mSpinner.setEnabled(true); - mSpinnerContent.setEnabled(true); } @Override @@ -682,13 +904,9 @@ public class ManageApplications extends Fragment implements public void onPause() { super.onPause(); mActivityResumed = false; - mApplicationsAdapter.pause(); - if (mResumedRunning) { - mRunningProcessesView.doPause(); - mResumedRunning = false; + for (int i=0; i parent, View view, int position, long id) { - ApplicationsState.AppEntry entry = mApplicationsAdapter.getAppEntry(position); - mCurrentPkgName = entry.info.packageName; - startApplicationDetailsActivity(); - } - - static final int VIEW_NOTHING = 0; - static final int VIEW_LIST = 1; - static final int VIEW_RUNNING = 2; - - void updateStorageUsage() { - // Fragment view not yet created? - if (mRootView == null) return; - // Make sure a callback didn't come at an inopportune time. - if (getActivity() == null) return; - - if (mCurView == VIEW_RUNNING) { - return; - } - - long freeStorage = 0; - long appStorage = 0; - long totalStorage = 0; - CharSequence newLabel = null; - - if (mFilterApps == FILTER_APPS_SDCARD) { - if (mLastShowedInternalStorage) { - mLastShowedInternalStorage = false; - } - newLabel = getActivity().getText(R.string.sd_card_storage); - - if (mContainerService != null) { - try { - final long[] stats = mContainerService.getFileSystemStats( - Environment.getExternalStorageDirectory().getPath()); - totalStorage = stats[0]; - freeStorage = stats[1]; - } catch (RemoteException e) { - Log.w(TAG, "Problem in container service", e); - } - } - - final int N = mApplicationsAdapter.getCount(); - for (int i=0; i 0) { - mColorBar.setRatios((totalStorage-freeStorage-appStorage)/(float)totalStorage, - appStorage/(float)totalStorage, freeStorage/(float)totalStorage); - long usedStorage = totalStorage - freeStorage; - if (mLastUsedStorage != usedStorage) { - mLastUsedStorage = usedStorage; - String sizeStr = Formatter.formatShortFileSize(getActivity(), usedStorage); - mUsedStorageText.setText(getActivity().getResources().getString( - R.string.service_foreground_processes, sizeStr)); - } - if (mLastFreeStorage != freeStorage) { - mLastFreeStorage = freeStorage; - String sizeStr = Formatter.formatShortFileSize(getActivity(), freeStorage); - mFreeStorageText.setText(getActivity().getResources().getString( - R.string.service_background_processes, sizeStr)); - } - } else { - mColorBar.setRatios(0, 0, 0); - if (mLastUsedStorage != -1) { - mLastUsedStorage = -1; - mUsedStorageText.setText(""); - } - if (mLastFreeStorage != -1) { - mLastFreeStorage = -1; - mFreeStorageText.setText(""); - } + if (mCurTab != null && mCurTab.mApplications != null) { + ApplicationsState.AppEntry entry = mCurTab.mApplications.getAppEntry(position); + mCurrentPkgName = entry.info.packageName; + startApplicationDetailsActivity(); } } - private void selectView(int which) { - if (which == VIEW_LIST) { - if (mResumedRunning) { - mRunningProcessesView.doPause(); - mResumedRunning = false; - } - if (mCurView != which) { - mRunningProcessesView.setVisibility(View.GONE); - mListContainer.setVisibility(View.VISIBLE); - mLoadingContainer.setVisibility(View.GONE); - } - if (mActivityResumed) { - mApplicationsAdapter.resume(mFilterApps, mSortOrder); - } - } else if (which == VIEW_RUNNING) { - if (!mCreatedRunning) { - mRunningProcessesView.doCreate(null); - mRunningProcessesView.mAdapter.setShowBackground(mShowBackground); - mCreatedRunning = true; - } - boolean haveData = true; - if (mActivityResumed && !mResumedRunning) { - haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail); - mResumedRunning = true; - } - mApplicationsAdapter.pause(); - if (mCurView != which) { - if (haveData) { - mRunningProcessesView.setVisibility(View.VISIBLE); - } else { - mLoadingContainer.setVisibility(View.VISIBLE); - } - mListContainer.setVisibility(View.GONE); + public void updateCurrentTab(int position) { + TabInfo tab = mTabs.get(position); + mCurTab = tab; + + // Put things in the correct paused/resumed state. + if (mActivityResumed) { + mCurTab.build(mInflater, mContentContainer, mRootView); + mCurTab.resume(mSortOrder); + } else { + mCurTab.pause(); + } + for (int i=0; i