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