/* * 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 static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.AppOpsManager; import android.app.Fragment; import android.app.INotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.NetworkPolicyManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.preference.PreferenceFrameLayout; import android.provider.Settings; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; 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.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.BaseAdapter; import android.widget.Filter; import android.widget.Filterable; import android.widget.ListView; import android.widget.Spinner; import com.android.internal.app.IMediaContainerService; import com.android.internal.content.PackageHelper; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.UserSpinnerAdapter; import com.android.settings.Settings.RunningServicesActivity; import com.android.settings.Settings.StorageUseActivity; import com.android.settings.UserSpinnerAdapter.UserDetails; import com.android.settings.applications.ApplicationsState.AppEntry; import com.android.settings.deviceinfo.StorageMeasurement; import com.android.settings.Utils; import java.util.ArrayList; import java.util.Comparator; import java.util.List; 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_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; } } interface AppClickListener { void onItemClick(ManageApplications.TabInfo tab, AdapterView parent, View view, int position, long id); } /** * 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 AppClickListener, DialogInterface.OnClickListener, DialogInterface.OnDismissListener, OnItemSelectedListener { static final String TAG = "ManageApplications"; static final boolean DEBUG = false; private static final String EXTRA_SORT_ORDER = "sortOrder"; private static final String EXTRA_SHOW_BACKGROUND = "showBackground"; private static final String EXTRA_DEFAULT_LIST_TYPE = "defaultListType"; private static final String EXTRA_RESET_DIALOG = "resetDialog"; // 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; public static final int SIZE_TOTAL = 0; public static final int SIZE_INTERNAL = 1; public static final int SIZE_EXTERNAL = 2; // 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 FILTER_APPS_DISABLED = MENU_OPTIONS_BASE + 3; 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; public static final int RESET_APP_PREFERENCES = MENU_OPTIONS_BASE + 8; // sort order private int mSortOrder = SORT_ORDER_ALPHA; private ApplicationsState mApplicationsState; public static class TabInfo implements OnItemClickListener { public final ManageApplications mOwner; public final ApplicationsState mApplicationsState; public final CharSequence mLabel; public final int mListType; public final int mFilter; public final AppClickListener mClickListener; public final CharSequence mInvalidSizeStr; public final CharSequence mComputingSizeStr; private final Bundle mSavedInstanceState; public ApplicationsAdapter mApplications; public LayoutInflater mInflater; public View mRootView; private IMediaContainerService mContainerService; private View mLoadingContainer; private View mListContainer; private ViewGroup mPinnedHeader; // ListView used to display list private ListView mListView; // Custom view used to display running processes private RunningProcessesView mRunningProcessesView; //private LinearColorBar mColorBar; //private TextView mStorageChartLabel; //private TextView mUsedStorageText; //private TextView mFreeStorageText; private long mFreeStorage = 0, mAppStorage = 0, mTotalStorage = 0; private long mLastUsedStorage, mLastAppStorage, mLastFreeStorage; final Runnable mRunningProcessesAvail = new Runnable() { public void run() { handleRunningProcessesAvail(); } }; public TabInfo(ManageApplications owner, ApplicationsState apps, CharSequence label, int listType, AppClickListener clickListener, Bundle savedInstanceState) { mOwner = owner; mApplicationsState = apps; mLabel = label; mListType = listType; switch (listType) { case LIST_TYPE_DOWNLOADED: mFilter = FILTER_APPS_THIRD_PARTY; break; case LIST_TYPE_SDCARD: mFilter = FILTER_APPS_SDCARD; break; case LIST_TYPE_DISABLED: mFilter = FILTER_APPS_DISABLED; break; default: mFilter = FILTER_APPS_ALL; break; } mClickListener = clickListener; mInvalidSizeStr = owner.getActivity().getText(R.string.invalid_size_value); mComputingSizeStr = owner.getActivity().getText(R.string.computing_size); mSavedInstanceState = savedInstanceState; } public void setContainerService(IMediaContainerService containerService) { mContainerService = containerService; updateStorageUsage(); } public View build(LayoutInflater inflater, ViewGroup contentParent, View contentChild) { if (mRootView != null) { return mRootView; } mInflater = inflater; mRootView = inflater.inflate(mListType == LIST_TYPE_RUNNING ? R.layout.manage_applications_running : R.layout.manage_applications_apps, null); mPinnedHeader = (ViewGroup) mRootView.findViewById(R.id.pinned_header); if (mOwner.mProfileSpinnerAdapter != null) { Spinner spinner = (Spinner) inflater.inflate(R.layout.spinner_view, null); spinner.setAdapter(mOwner.mProfileSpinnerAdapter); spinner.setOnItemSelectedListener(mOwner); mPinnedHeader.addView(spinner); mPinnedHeader.setVisibility(View.VISIBLE); } mLoadingContainer = mRootView.findViewById(R.id.loading_container); mLoadingContainer.setVisibility(View.VISIBLE); mListContainer = mRootView.findViewById(R.id.list_container); if (mListContainer != null) { // Create adapter and list view here View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty); ListView lv = (ListView) mListContainer.findViewById(android.R.id.list); if (emptyView != null) { lv.setEmptyView(emptyView); } lv.setOnItemClickListener(this); lv.setSaveEnabled(true); lv.setItemsCanFocus(true); lv.setTextFilterEnabled(true); mListView = lv; mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter); mListView.setAdapter(mApplications); mListView.setRecyclerListener(mApplications); //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); Utils.prepareCustomPreferencesList(contentParent, contentChild, mListView, false); if (mFilter == FILTER_APPS_SDCARD) { //mStorageChartLabel.setText(mOwner.getActivity().getText( // R.string.sd_card_storage)); } else { //mStorageChartLabel.setText(mOwner.getActivity().getText( // R.string.internal_storage)); } applyCurrentStorage(); } mRunningProcessesView = (RunningProcessesView)mRootView.findViewById( R.id.running_processes); if (mRunningProcessesView != null) { mRunningProcessesView.doCreate(mSavedInstanceState); } return mRootView; } public void detachView() { if (mRootView != null) { ViewGroup group = (ViewGroup)mRootView.getParent(); if (group != null) { group.removeView(mRootView); } } } public void resume(int sortOrder) { if (mApplications != null) { mApplications.resume(sortOrder); } if (mRunningProcessesView != null) { boolean haveData = mRunningProcessesView.doResume(mOwner, mRunningProcessesAvail); if (haveData) { mRunningProcessesView.setVisibility(View.VISIBLE); mLoadingContainer.setVisibility(View.INVISIBLE); } else { mLoadingContainer.setVisibility(View.VISIBLE); } } } public void pause() { if (mApplications != null) { mApplications.pause(); } if (mRunningProcessesView != null) { mRunningProcessesView.doPause(); } } public void release() { if (mApplications != null) { mApplications.release(); } } void updateStorageUsage() { // Make sure a callback didn't come at an inopportune time. if (mOwner.getActivity() == null) return; // Doesn't make sense for stuff that is not an app list. if (mApplications == null) return; mFreeStorage = 0; mAppStorage = 0; mTotalStorage = 0; if (mFilter == FILTER_APPS_SDCARD) { if (mContainerService != null) { try { final long[] stats = mContainerService.getFileSystemStats( Environment.getExternalStorageDirectory().getPath()); mTotalStorage = stats[0]; mFreeStorage = stats[1]; } catch (RemoteException e) { Log.w(TAG, "Problem in container service", e); } } if (mApplications != null) { final int N = mApplications.getCount(); for (int i=0; i 0) { BidiFormatter bidiFormatter = BidiFormatter.getInstance(); mColorBar.setRatios((mTotalStorage-mFreeStorage-mAppStorage)/(float)mTotalStorage, mAppStorage/(float)mTotalStorage, mFreeStorage/(float)mTotalStorage); long usedStorage = mTotalStorage - mFreeStorage; if (mLastUsedStorage != usedStorage) { mLastUsedStorage = usedStorage; String sizeStr = bidiFormatter.unicodeWrap( Formatter.formatShortFileSize(mOwner.getActivity(), usedStorage)); mUsedStorageText.setText(mOwner.getActivity().getResources().getString( R.string.service_foreground_processes, sizeStr)); } if (mLastFreeStorage != mFreeStorage) { mLastFreeStorage = mFreeStorage; String sizeStr = bidiFormatter.unicodeWrap( Formatter.formatShortFileSize(mOwner.getActivity(), mFreeStorage)); 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(this, 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(); private int mNumTabs; TabInfo mCurTab = null; // Size resource used for packages whose size computation failed for some reason CharSequence mInvalidSizeStr; private CharSequence mComputingSizeStr; // layout inflater object used to inflate views private LayoutInflater mInflater; private String mCurrentPkgName; private Menu mOptionsMenu; // These are for keeping track of activity and spinner switch state. private boolean mActivityResumed; 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; static final int LIST_TYPE_DISABLED = 4; private boolean mShowBackground = false; private int mDefaultListType = -1; private ViewGroup mContentContainer; private View mRootView; private ViewPager mViewPager; private UserSpinnerAdapter mProfileSpinnerAdapter; private Context mContext; AlertDialog mResetDialog; class MyPagerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener { int mCurPos = 0; @Override public int getCount() { return mNumTabs; } @Override public Object instantiateItem(ViewGroup container, int position) { TabInfo tab = mTabs.get(position); View root = tab.build(mInflater, mContentContainer, mRootView); container.addView(root); root.setTag(R.id.name, tab); return root; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); //return ((TabInfo)((View)object).getTag(R.id.name)).mListType; } @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); } } } /* * 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 */ 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 mLastSortMode=-1; private boolean mWaitingForData; private int mWhichSize = SIZE_TOTAL; CharSequence mCurFilterPrefix; private Filter mFilter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { ArrayList 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)results.values; notifyDataSetChanged(); mTab.updateStorageUsage(); } }; 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 sort) { if (DEBUG) Log.i(TAG, "Resume! mResumed=" + mResumed); if (!mResumed) { mResumed = true; mSession.resume(); mLastSortMode = sort; rebuild(true); } else { rebuild(sort); } } public void pause() { if (mResumed) { mResumed = false; mSession.pause(); } } public void release() { mSession.release(); } public void rebuild(int sort) { if (sort == mLastSortMode) { return; } mLastSortMode = sort; rebuild(true); } public void rebuild(boolean eraseold) { if (DEBUG) Log.i(TAG, "Rebuilding app list..."); ApplicationsState.AppFilter filterObj; Comparator comparatorObj; boolean emulated = Environment.isExternalStorageEmulated(); if (emulated) { mWhichSize = SIZE_TOTAL; } else { mWhichSize = SIZE_INTERNAL; } switch (mFilterMode) { case FILTER_APPS_THIRD_PARTY: filterObj = ApplicationsState.THIRD_PARTY_FILTER; break; case FILTER_APPS_SDCARD: filterObj = ApplicationsState.ON_SD_CARD_FILTER; if (!emulated) { mWhichSize = SIZE_EXTERNAL; } break; case FILTER_APPS_DISABLED: filterObj = ApplicationsState.DISABLED_FILTER; break; default: filterObj = ApplicationsState.ALL_ENABLED_FILTER; break; } switch (mLastSortMode) { case SORT_ORDER_SIZE: switch (mWhichSize) { case SIZE_INTERNAL: comparatorObj = ApplicationsState.INTERNAL_SIZE_COMPARATOR; break; case SIZE_EXTERNAL: comparatorObj = ApplicationsState.EXTERNAL_SIZE_COMPARATOR; break; default: comparatorObj = ApplicationsState.SIZE_COMPARATOR; break; } break; default: comparatorObj = ApplicationsState.ALPHA_COMPARATOR; break; } ArrayList entries = mSession.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(); mTab.updateStorageUsage(); if (entries == null) { mWaitingForData = true; mTab.mListContainer.setVisibility(View.INVISIBLE); mTab.mLoadingContainer.setVisibility(View.VISIBLE); } else { mTab.mListContainer.setVisibility(View.VISIBLE); mTab.mLoadingContainer.setVisibility(View.GONE); } } ArrayList applyPrefixFilter(CharSequence prefix, ArrayList origEntries) { if (prefix == null || prefix.length() == 0) { return origEntries; } else { String prefixStr = ApplicationsState.normalize(prefix.toString()); final String spacePrefixStr = " " + prefixStr; ArrayList newEntries = new ArrayList(); for (int i=0; i apps) { 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)); } mTab.mListContainer.setVisibility(View.VISIBLE); mTab.mLoadingContainer.setVisibility(View.GONE); mWaitingForData = false; mBaseEntries = apps; mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries); notifyDataSetChanged(); mTab.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 parent, View view, int position, long id) { UserHandle selectedUser = mProfileSpinnerAdapter.getUserHandle(position); if (selectedUser.getIdentifier() != UserHandle.myUserId()) { Intent intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, selectedUser); getActivity().finish(); } } @Override public void onNothingSelected(AdapterView parent) { // Nothing to do } private void updateNumTabs() { int newNum = mApplicationsState.haveDisabledApps() ? mTabs.size() : (mTabs.size()-1); if (newNum != mNumTabs) { mNumTabs = newNum; if (mViewPager != null) { mViewPager.getAdapter().notifyDataSetChanged(); } } } TabInfo tabForType(int type) { for (int i = 0; i < mTabs.size(); i++) { TabInfo tab = mTabs.get(i); if (tab.mListType == type) { return tab; } } return null; } // 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); SettingsActivity sa = (SettingsActivity) getActivity(); sa.startPreferencePanel(InstalledAppDetails.class.getName(), args, R.string.application_info_label, null, this, INSTALLED_APP_DETAILS); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { mOptionsMenu = menu; // note: icons removed for now because the cause the new action // bar UI to be very confusing. 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_NEVER); 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_NEVER); 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); menu.add(0, RESET_APP_PREFERENCES, 4, R.string.reset_app_preferences) .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); updateOptionsMenu(); } @Override public void onPrepareOptionsMenu(Menu menu) { updateOptionsMenu(); } @Override public void onDestroyOptionsMenu() { mOptionsMenu = null; } @Override public void onDestroy() { getActivity().unbindService(mContainerConnection); super.onDestroy(); } 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 (mCurTab != null && mCurTab.mListType == LIST_TYPE_RUNNING) { TabInfo tab = tabForType(LIST_TYPE_RUNNING); boolean showingBackground = tab != null && tab.mRunningProcessesView != null ? tab.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); mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(false); mShowBackground = 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); mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(true); } } void buildResetDialog() { if (mResetDialog == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.reset_app_preferences_title); builder.setMessage(R.string.reset_app_preferences_desc); builder.setPositiveButton(R.string.reset_app_preferences_button, this); builder.setNegativeButton(R.string.cancel, null); mResetDialog = builder.show(); mResetDialog.setOnDismissListener(this); } } @Override public void onDismiss(DialogInterface dialog) { if (mResetDialog == dialog) { mResetDialog = null; } } @Override public void onClick(DialogInterface dialog, int which) { if (mResetDialog == dialog) { final PackageManager pm = getActivity().getPackageManager(); final IPackageManager mIPm = IPackageManager.Stub.asInterface( ServiceManager.getService("package")); final INotificationManager nm = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); final NetworkPolicyManager npm = NetworkPolicyManager.from(getActivity()); final AppOpsManager aom = (AppOpsManager)getActivity().getSystemService( Context.APP_OPS_SERVICE); final Handler handler = new Handler(getActivity().getMainLooper()); (new AsyncTask() { @Override protected Void doInBackground(Void... params) { List apps = pm.getInstalledApplications( PackageManager.GET_DISABLED_COMPONENTS); for (int i=0; i parent, View view, int position, long id) { if (tab.mApplications != null && tab.mApplications.getCount() > position) { ApplicationsState.AppEntry entry = tab.mApplications.getAppEntry(position); mCurrentPkgName = entry.info.packageName; startApplicationDetailsActivity(); } } 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