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