blob: 20cf2f9a6777af9fdede4907ccf6766f178a6d75 [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import com.android.internal.content.PackageHelper;
import com.android.settings.R;
import com.android.settings.applications.ApplicationsState.AppEntry;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import java.util.ArrayList;
import java.util.Comparator;
final class CanBeOnSdCardChecker {
final IPackageManager mPm;
int mInstallLocation;
CanBeOnSdCardChecker() {
mPm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
}
void init() {
try {
mInstallLocation = mPm.getInstallLocation();
} catch (RemoteException e) {
Log.e("CanBeOnSdCardChecker", "Is Package Manager running?");
return;
}
}
boolean check(ApplicationInfo info) {
boolean canBe = false;
if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
canBe = true;
} else {
if ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0 &&
(info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (info.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
info.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
canBe = true;
} else if (info.installLocation
== PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
if (mInstallLocation == PackageHelper.APP_INSTALL_EXTERNAL) {
// For apps with no preference and the default value set
// to install on sdcard.
canBe = true;
}
}
}
}
return canBe;
}
}
/**
* Activity to pick an application that will be used to display installation information and
* options to uninstall/delete user data for system applications. This activity
* can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
* intent.
*/
public class ManageApplications extends Fragment implements
OnItemClickListener,
TabHost.TabContentFactory, TabHost.OnTabChangeListener {
static final String TAG = "ManageApplications";
static final boolean DEBUG = false;
// attributes used as keys when passing values to InstalledAppDetails activity
public static final String APP_CHG = "chg";
// constant value that can be used to check return code from sub activity.
private static final int INSTALLED_APP_DETAILS = 1;
// sort order that can be changed through the menu can be sorted alphabetically
// or size(descending)
private static final int MENU_OPTIONS_BASE = 0;
// Filter options used for displayed list of applications
public static final int FILTER_APPS_ALL = MENU_OPTIONS_BASE + 0;
public static final int FILTER_APPS_THIRD_PARTY = MENU_OPTIONS_BASE + 1;
public static final int FILTER_APPS_SDCARD = MENU_OPTIONS_BASE + 2;
public static final int SORT_ORDER_ALPHA = MENU_OPTIONS_BASE + 4;
public static final int SORT_ORDER_SIZE = MENU_OPTIONS_BASE + 5;
public static final int SHOW_RUNNING_SERVICES = MENU_OPTIONS_BASE + 6;
public static final int SHOW_BACKGROUND_PROCESSES = MENU_OPTIONS_BASE + 7;
// sort order
private int mSortOrder = SORT_ORDER_ALPHA;
// Filter value
private int mFilterApps = FILTER_APPS_THIRD_PARTY;
private ApplicationsState mApplicationsState;
private ApplicationsAdapter mApplicationsAdapter;
// Size resource used for packages whose size computation failed for some reason
private CharSequence mInvalidSizeStr;
private CharSequence mComputingSizeStr;
// layout inflater object used to inflate views
private LayoutInflater mInflater;
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 tab switch state.
private int mCurView;
private boolean mCreatedRunning;
private boolean mResumedRunning;
private boolean mActivityResumed;
private StatFs mDataFileStats;
private StatFs mSDCardFileStats;
private boolean mLastShowedInternalStorage = true;
private long mLastUsedStorage, mLastAppStorage, mLastFreeStorage;
static final String TAB_DOWNLOADED = "Downloaded";
static final String TAB_RUNNING = "Running";
static final String TAB_ALL = "All";
static final String TAB_SDCARD = "OnSdCard";
private View mRootView;
// -------------- Copied from TabActivity --------------
private TabHost mTabHost;
private String mDefaultTab = null;
// -------------- Copied from TabActivity --------------
final Runnable mRunningProcessesAvail = new Runnable() {
public void run() {
handleRunningProcessesAvail();
}
};
// View Holder used when displaying views
static class AppViewHolder {
ApplicationsState.AppEntry entry;
TextView appName;
ImageView appIcon;
TextView appSize;
TextView disabled;
CheckBox checkBox;
void updateSizeText(ManageApplications ma) {
if (DEBUG) Log.i(TAG, "updateSizeText of " + entry.label + " " + entry
+ ": " + entry.sizeStr);
if (entry.sizeStr != null) {
appSize.setText(entry.sizeStr);
} else if (entry.size == ApplicationsState.SIZE_INVALID) {
appSize.setText(ma.mInvalidSizeStr);
}
}
}
/*
* Custom adapter implementation for the ListView
* This adapter maintains a map for each displayed application and its properties
* An index value on each AppInfo object indicates the correct position or index
* in the list. If the list gets updated dynamically when the user is viewing the list of
* applications, we need to return the correct index of position. This is done by mapping
* 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,
ApplicationsState.Callbacks, AbsListView.RecyclerListener {
private final ApplicationsState mState;
private final ArrayList<View> mActive = new ArrayList<View>();
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
private ArrayList<ApplicationsState.AppEntry> mEntries;
private boolean mResumed;
private int mLastFilterMode=-1, mLastSortMode=-1;
private boolean mWaitingForData;
CharSequence mCurFilterPrefix;
private Filter mFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<ApplicationsState.AppEntry> entries
= applyPrefixFilter(constraint, mBaseEntries);
FilterResults fr = new FilterResults();
fr.values = entries;
fr.count = entries.size();
return fr;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mCurFilterPrefix = constraint;
mEntries = (ArrayList<ApplicationsState.AppEntry>)results.values;
notifyDataSetChanged();
updateStorageUsage();
}
};
public ApplicationsAdapter(ApplicationsState state) {
mState = state;
}
public void resume(int filter, int sort) {
if (DEBUG) Log.i(TAG, "Resume! mResumed=" + mResumed);
if (!mResumed) {
mResumed = true;
mState.resume(this);
mLastFilterMode = filter;
mLastSortMode = sort;
rebuild(true);
} else {
rebuild(filter, sort);
}
}
public void pause() {
if (mResumed) {
mResumed = false;
mState.pause();
}
}
public void rebuild(int filter, int sort) {
if (filter == mLastFilterMode && sort == mLastSortMode) {
return;
}
mLastFilterMode = filter;
mLastSortMode = sort;
rebuild(true);
}
public void rebuild(boolean eraseold) {
if (DEBUG) Log.i(TAG, "Rebuilding app list...");
ApplicationsState.AppFilter filterObj;
Comparator<AppEntry> comparatorObj;
switch (mLastFilterMode) {
case FILTER_APPS_THIRD_PARTY:
filterObj = ApplicationsState.THIRD_PARTY_FILTER;
break;
case FILTER_APPS_SDCARD:
filterObj = ApplicationsState.ON_SD_CARD_FILTER;
break;
default:
filterObj = null;
break;
}
switch (mLastSortMode) {
case SORT_ORDER_SIZE:
comparatorObj = ApplicationsState.SIZE_COMPARATOR;
break;
default:
comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
break;
}
ArrayList<ApplicationsState.AppEntry> entries
= mState.rebuild(filterObj, comparatorObj);
if (entries == null && !eraseold) {
// Don't have new list yet, but can continue using the old one.
return;
}
mBaseEntries = entries;
if (mBaseEntries != null) {
mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
} else {
mEntries = null;
}
notifyDataSetChanged();
updateStorageUsage();
if (entries == null) {
mWaitingForData = true;
mListContainer.setVisibility(View.INVISIBLE);
mLoadingContainer.setVisibility(View.VISIBLE);
} else {
mListContainer.setVisibility(View.VISIBLE);
mLoadingContainer.setVisibility(View.GONE);
}
}
ArrayList<ApplicationsState.AppEntry> applyPrefixFilter(CharSequence prefix,
ArrayList<ApplicationsState.AppEntry> origEntries) {
if (prefix == null || prefix.length() == 0) {
return origEntries;
} else {
String prefixStr = ApplicationsState.normalize(prefix.toString());
final String spacePrefixStr = " " + prefixStr;
ArrayList<ApplicationsState.AppEntry> newEntries
= new ArrayList<ApplicationsState.AppEntry>();
for (int i=0; i<origEntries.size(); i++) {
ApplicationsState.AppEntry entry = origEntries.get(i);
String nlabel = entry.getNormalizedLabel();
if (nlabel.startsWith(prefixStr) || nlabel.indexOf(spacePrefixStr) != -1) {
newEntries.add(entry);
}
}
return newEntries;
}
}
@Override
public void onRunningStateChanged(boolean running) {
getActivity().setProgressBarIndeterminateVisibility(running);
}
@Override
public void onRebuildComplete(ArrayList<AppEntry> 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));
}
mListContainer.setVisibility(View.VISIBLE);
mLoadingContainer.setVisibility(View.GONE);
mWaitingForData = false;
mBaseEntries = apps;
mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
notifyDataSetChanged();
updateStorageUsage();
}
@Override
public void onPackageListChanged() {
rebuild(false);
}
@Override
public void onPackageIconChanged() {
// We ensure icons are loaded when their item is displayed, so
// don't care about icons loaded in the background.
}
@Override
public void onPackageSizeChanged(String packageName) {
for (int i=0; i<mActive.size(); i++) {
AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag();
if (holder.entry.info.packageName.equals(packageName)) {
synchronized (holder.entry) {
holder.updateSizeText(ManageApplications.this);
}
if (holder.entry.info.packageName.equals(mCurrentPkgName)
&& mLastSortMode == SORT_ORDER_SIZE) {
// We got the size information for the last app the
// user viewed, and are sorting by size... they may
// have cleared data, so we immediately want to resort
// the list with the new size to reflect it to the user.
rebuild(false);
}
updateStorageUsage();
return;
}
}
}
@Override
public void onAllSizesComputed() {
if (mLastSortMode == SORT_ORDER_SIZE) {
rebuild(false);
}
}
public int getCount() {
return mEntries != null ? mEntries.size() : 0;
}
public Object getItem(int position) {
return mEntries.get(position);
}
public ApplicationsState.AppEntry getAppEntry(int position) {
return mEntries.get(position);
}
public long getItemId(int position) {
return mEntries.get(position).id;
}
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;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.manage_applications_item, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new AppViewHolder();
holder.appName = (TextView) convertView.findViewById(R.id.app_name);
holder.appIcon = (ImageView) convertView.findViewById(R.id.app_icon);
holder.appSize = (TextView) convertView.findViewById(R.id.app_size);
holder.disabled = (TextView) convertView.findViewById(R.id.app_disabled);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.app_on_sdcard);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (AppViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder
ApplicationsState.AppEntry entry = mEntries.get(position);
synchronized (entry) {
holder.entry = entry;
if (entry.label != null) {
holder.appName.setText(entry.label);
holder.appName.setTextColor(getActivity().getResources().getColorStateList(
entry.info.enabled ? android.R.color.primary_text_dark
: android.R.color.secondary_text_dark));
}
mState.ensureIcon(entry);
if (entry.icon != null) {
holder.appIcon.setImageDrawable(entry.icon);
}
holder.updateSizeText(ManageApplications.this);
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) {
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setChecked((entry.info.flags
& ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
} else {
holder.checkBox.setVisibility(View.GONE);
}
}
mActive.remove(convertView);
mActive.add(convertView);
return convertView;
}
@Override
public Filter getFilter() {
return mFilter;
}
@Override
public void onMovedToScrapHeap(View view) {
mActive.remove(view);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication());
mApplicationsAdapter = new ApplicationsAdapter(mApplicationsState);
Intent intent = getActivity().getIntent();
String action = intent.getAction();
String defaultTabTag = TAB_DOWNLOADED;
String className = getArguments() != null
? getArguments().getString("classname") : null;
if (className == null) {
className = intent.getComponent().getClassName();
}
if (className.equals("com.android.settings.RunningServices")) {
defaultTabTag = TAB_RUNNING;
} else if (className.equals("com.android.settings.applications.StorageUse")
|| action.equals(Intent.ACTION_MANAGE_PACKAGE_STORAGE)) {
mSortOrder = SORT_ORDER_SIZE;
mFilterApps = FILTER_APPS_ALL;
defaultTabTag = TAB_ALL;
} else if (action.equals(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS)) {
// Select the all-apps tab, with the default sorting
defaultTabTag = TAB_ALL;
}
if (savedInstanceState != null) {
mSortOrder = savedInstanceState.getInt("sortOrder", mSortOrder);
mFilterApps = savedInstanceState.getInt("filterApps", mFilterApps);
String tmp = savedInstanceState.getString("defaultTabTag");
if (tmp != null) defaultTabTag = tmp;
}
mDefaultTab = defaultTabTag;
mDataFileStats = new StatFs("/data");
mSDCardFileStats = new StatFs(Environment.getExternalStorageDirectory().toString());
mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
mComputingSizeStr = getActivity().getText(R.string.computing_size);
}
@Override
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;
View tabRoot = mInflater.inflate(com.android.internal.R.layout.tab_content, null);
mTabHost = (TabHost)tabRoot.findViewById(com.android.internal.R.id.tabhost);
mTabHost.setup();
final TabHost tabHost = mTabHost;
tabHost.addTab(tabHost.newTabSpec(TAB_DOWNLOADED)
.setIndicator(getActivity().getString(R.string.filter_apps_third_party),
getActivity().getResources().getDrawable(R.drawable.ic_tab_download))
.setContent(this));
tabHost.addTab(tabHost.newTabSpec(TAB_ALL)
.setIndicator(getActivity().getString(R.string.filter_apps_all),
getActivity().getResources().getDrawable(R.drawable.ic_tab_all))
.setContent(this));
if (!Environment.isExternalStorageEmulated()) {
tabHost.addTab(tabHost.newTabSpec(TAB_SDCARD)
.setIndicator(getActivity().getString(R.string.filter_apps_onsdcard),
getActivity().getResources().getDrawable(R.drawable.ic_tab_sdcard))
.setContent(this));
}
tabHost.addTab(tabHost.newTabSpec(TAB_RUNNING)
.setIndicator(getActivity().getString(R.string.filter_apps_running),
getActivity().getResources().getDrawable(R.drawable.ic_tab_running))
.setContent(this));
tabHost.setCurrentTabByTag(mDefaultTab);
tabHost.setOnTabChangedListener(this);
return tabRoot;
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onResume() {
super.onResume();
mActivityResumed = true;
showCurrentTab();
updateOptionsMenu();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("sortOrder", mSortOrder);
outState.putInt("filterApps", mFilterApps);
if (mDefaultTab != null) {
outState.putString("defautTabTag", mDefaultTab);
}
}
@Override
public void onPause() {
super.onPause();
mActivityResumed = false;
mApplicationsAdapter.pause();
if (mResumedRunning) {
mRunningProcessesView.doPause();
mResumedRunning = false;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
mApplicationsState.requestSize(mCurrentPkgName);
}
}
// utility method used to start sub activity
private void startApplicationDetailsActivity() {
// start new fragment to display extended information
Bundle args = new Bundle();
args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);
PreferenceActivity pa = (PreferenceActivity)getActivity();
pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
R.string.application_info_label, null, this, INSTALLED_APP_DETAILS);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.i(TAG, "onCreateOptionsMenu in " + this + ": " + menu);
mOptionsMenu = menu;
menu.add(0, SORT_ORDER_ALPHA, 1, R.string.sort_order_alpha)
.setIcon(android.R.drawable.ic_menu_sort_alphabetically)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, SORT_ORDER_SIZE, 2, R.string.sort_order_size)
.setIcon(android.R.drawable.ic_menu_sort_by_size)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, SHOW_RUNNING_SERVICES, 3, R.string.show_running_services)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, SHOW_BACKGROUND_PROCESSES, 3, R.string.show_background_processes)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
updateOptionsMenu();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
updateOptionsMenu();
}
@Override
public void onDestroyOptionsMenu() {
mOptionsMenu = null;
}
void updateOptionsMenu() {
if (mOptionsMenu == null) {
return;
}
/*
* The running processes screen doesn't use the mApplicationsAdapter
* so bringing up this menu in that case doesn't make any sense.
*/
if (mCurView == VIEW_RUNNING) {
boolean showingBackground = mRunningProcessesView != null
? mRunningProcessesView.mAdapter.getShowBackground() : false;
mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(false);
mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(false);
mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(showingBackground);
mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(!showingBackground);
} else {
mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder != SORT_ORDER_SIZE);
mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(false);
mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(false);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int menuId = item.getItemId();
if ((menuId == SORT_ORDER_ALPHA) || (menuId == SORT_ORDER_SIZE)) {
mSortOrder = menuId;
if (mCurView != VIEW_RUNNING) {
mApplicationsAdapter.rebuild(mFilterApps, mSortOrder);
}
} else if (menuId == SHOW_RUNNING_SERVICES) {
mRunningProcessesView.mAdapter.setShowBackground(false);
} else if (menuId == SHOW_BACKGROUND_PROCESSES) {
mRunningProcessesView.mAdapter.setShowBackground(true);
}
updateOptionsMenu();
return true;
}
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
ApplicationsState.AppEntry entry = mApplicationsAdapter.getAppEntry(position);
mCurrentPkgName = entry.info.packageName;
startApplicationDetailsActivity();
}
public View createTabContent(String tag) {
return mRootView;
}
static final int VIEW_NOTHING = 0;
static final int VIEW_LIST = 1;
static final int VIEW_RUNNING = 2;
void updateStorageUsage() {
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);
mSDCardFileStats.restat(Environment.getExternalStorageDirectory().toString());
try {
totalStorage = (long)mSDCardFileStats.getBlockCount() *
mSDCardFileStats.getBlockSize();
freeStorage = (long) mSDCardFileStats.getAvailableBlocks() *
mSDCardFileStats.getBlockSize();
} catch (IllegalArgumentException e) {
// use the old value of mFreeMem
}
} else {
if (!mLastShowedInternalStorage) {
mLastShowedInternalStorage = true;
}
newLabel = getActivity().getText(R.string.internal_storage);
mDataFileStats.restat("/data");
try {
totalStorage = (long)mDataFileStats.getBlockCount() *
mDataFileStats.getBlockSize();
freeStorage = (long) mDataFileStats.getAvailableBlocks() *
mDataFileStats.getBlockSize();
} catch (IllegalArgumentException e) {
}
final int N = mApplicationsAdapter.getCount();
for (int i=0; i<N; i++) {
ApplicationsState.AppEntry ae = mApplicationsAdapter.getAppEntry(i);
appStorage += ae.codeSize + ae.dataSize;
}
freeStorage += mApplicationsState.sumCacheSizes();
}
if (newLabel != null) {
mStorageChartLabel.setText(newLabel);
}
if (totalStorage > 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("");
}
}
}
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);
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);
}
}
mCurView = which;
}
void handleRunningProcessesAvail() {
if (mCurView == VIEW_RUNNING) {
mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(
getActivity(), android.R.anim.fade_out));
mRunningProcessesView.startAnimation(AnimationUtils.loadAnimation(
getActivity(), android.R.anim.fade_in));
mRunningProcessesView.setVisibility(View.VISIBLE);
mLoadingContainer.setVisibility(View.GONE);
}
}
public void showCurrentTab() {
String tabId = mDefaultTab = mTabHost.getCurrentTabTag();
int newOption;
if (TAB_DOWNLOADED.equalsIgnoreCase(tabId)) {
newOption = FILTER_APPS_THIRD_PARTY;
} else if (TAB_ALL.equalsIgnoreCase(tabId)) {
newOption = FILTER_APPS_ALL;
} else if (TAB_SDCARD.equalsIgnoreCase(tabId)) {
newOption = FILTER_APPS_SDCARD;
} else if (TAB_RUNNING.equalsIgnoreCase(tabId)) {
((InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(
getActivity().getWindow().getDecorView().getWindowToken(), 0);
selectView(VIEW_RUNNING);
return;
} else {
// Invalid option. Do nothing
return;
}
mFilterApps = newOption;
selectView(VIEW_LIST);
updateStorageUsage();
updateOptionsMenu();
}
public void onTabChanged(String tabId) {
showCurrentTab();
}
}