AppStorageSettings.java revision 08703c8bb19b518214bc352199bd46baab597547
1cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk/* 2cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Copyright (C) 2015 The Android Open Source Project 3cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * 4cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 5cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * you may not use this file except in compliance with the License. 6cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * You may obtain a copy of the License at 7cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * 8cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * http://www.apache.org/licenses/LICENSE-2.0 9cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * 10cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Unless required by applicable law or agreed to in writing, software 11cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * distributed under the License is distributed on an "AS IS" BASIS, 12cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * See the License for the specific language governing permissions and 14cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * limitations under the License. 15cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk */ 16cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 17cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkpackage com.android.settings.applications; 18cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 19cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.app.ActivityManager; 20cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.app.AlertDialog; 2116634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkeyimport android.app.AppGlobals; 22cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.Context; 23cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.DialogInterface; 24cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.Intent; 2508703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.UriPermission; 26cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.ApplicationInfo; 27cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.IPackageDataObserver; 2808703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.pm.PackageManager; 2908703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.pm.ProviderInfo; 30cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Bundle; 31cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Environment; 32cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Handler; 33cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Message; 3416634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkeyimport android.os.RemoteException; 359e9f7d11162df92bc430002423a281e22176de41Jeff Sharkeyimport android.os.UserHandle; 361f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.StorageManager; 371f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.VolumeInfo; 3839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference; 3939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceCategory; 40cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.text.format.Formatter; 41cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.util.Log; 4208703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.util.MutableInt; 43cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View; 44cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View.OnClickListener; 45cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.widget.Button; 46cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 478a963babe2e36b7a41f77b8d2598c97658196e58Chris Wrenimport com.android.internal.logging.MetricsLogger; 48cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.R; 49cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.Utils; 501f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport com.android.settings.deviceinfo.StorageWizardMoveConfirm; 5167cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState; 5267cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.AppEntry; 5367cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.Callbacks; 541f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 5508703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport java.util.ArrayList; 561f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Collections; 571f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.List; 5808703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport java.util.Map; 591f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Objects; 6008703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport java.util.TreeMap; 61cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 6260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monkpublic class AppStorageSettings extends AppInfoWithHeader 63e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk implements OnClickListener, Callbacks, DialogInterface.OnClickListener { 64588a0881c13d8ed63ba67b3145254c22211a2019Jason Monk private static final String TAG = AppStorageSettings.class.getSimpleName(); 65cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 66cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk //internal constants used in Handler 67cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int OP_SUCCESSFUL = 1; 68cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int OP_FAILED = 2; 69cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int MSG_CLEAR_USER_DATA = 1; 70cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int MSG_CLEAR_CACHE = 3; 71cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 72cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // invalid size value used initially and also when size retrieval through PackageManager 73cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // fails for whatever reason 74cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int SIZE_INVALID = -1; 75cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 76cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Result code identifiers 77cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public static final int REQUEST_MANAGE_SPACE = 2; 78cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 79cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int DLG_CLEAR_DATA = DLG_BASE + 1; 80cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2; 81cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 82e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private static final String KEY_STORAGE_USED = "storage_used"; 83e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private static final String KEY_CHANGE_STORAGE = "change_storage_button"; 84bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk private static final String KEY_STORAGE_SPACE = "storage_space"; 85c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_STORAGE_CATEGORY = "storage_category"; 8660a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 87c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_TOTAL_SIZE = "total_size"; 88c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_APP_SIZE = "app_size"; 89c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_EXTERNAL_CODE_SIZE = "external_code_size"; 90c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_DATA_SIZE = "data_size"; 91c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_EXTERNAL_DATA_SIZE = "external_data_size"; 92c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CACHE_SIZE = "cache_size"; 93c27f9e179adef2061e0000385f350874a7772c4eJason Monk 94c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CLEAR_DATA = "clear_data_button"; 95c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CLEAR_CACHE = "clear_cache_button"; 96c27f9e179adef2061e0000385f350874a7772c4eJason Monk 9708703c8bb19b518214bc352199bd46baab597547Felipe Leme private static final String KEY_URI_CATEGORY = "uri_category"; 9808703c8bb19b518214bc352199bd46baab597547Felipe Leme private static final String KEY_CLEAR_URI = "clear_uri_button"; 9908703c8bb19b518214bc352199bd46baab597547Felipe Leme 100c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mTotalSize; 101c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mAppSize; 102c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mDataSize; 103c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mExternalCodeSize; 104c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mExternalDataSize; 105cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 106cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Views related to cache info 107c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mCacheSize; 108cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private Button mClearDataButton; 109cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private Button mClearCacheButton; 11060a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 111e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private Preference mStorageUsed; 112e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private Button mChangeStorageButton; 113cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 11408703c8bb19b518214bc352199bd46baab597547Felipe Leme // Views related to URI permissions 11508703c8bb19b518214bc352199bd46baab597547Felipe Leme private Button mClearUriButton; 11608703c8bb19b518214bc352199bd46baab597547Felipe Leme private LayoutPreference mClearUri; 11708703c8bb19b518214bc352199bd46baab597547Felipe Leme private PreferenceCategory mUri; 11808703c8bb19b518214bc352199bd46baab597547Felipe Leme 119cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private boolean mCanClearData = true; 120cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private boolean mHaveSizes = false; 121cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 122cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastCodeSize = -1; 123cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastDataSize = -1; 124cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastExternalCodeSize = -1; 125cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastExternalDataSize = -1; 126cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastCacheSize = -1; 127cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private long mLastTotalSize = -1; 128cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 129cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private ClearCacheObserver mClearCacheObserver; 130cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private ClearUserDataObserver mClearDataObserver; 131cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 132cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Resource strings 133cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private CharSequence mInvalidSizeStr; 134cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private CharSequence mComputingStr; 135cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 136e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private VolumeInfo[] mCandidates; 137e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private AlertDialog.Builder mDialogBuilder; 138e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk 139cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 140cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onCreate(Bundle savedInstanceState) { 141cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk super.onCreate(savedInstanceState); 142cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 14360a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk addPreferencesFromResource(R.xml.app_storage_settings); 14460a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk setupViews(); 145cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 146cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 147ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk @Override 148ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk public void onResume() { 149ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk super.onResume(); 150ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk mState.requestSize(mPackageName, mUserId); 151ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk } 152ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk 15360a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk private void setupViews() { 154cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mComputingStr = getActivity().getText(R.string.computing_size); 155cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value); 156cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 157cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Set default values on sizes 158c27f9e179adef2061e0000385f350874a7772c4eJason Monk mTotalSize = findPreference(KEY_TOTAL_SIZE); 159c27f9e179adef2061e0000385f350874a7772c4eJason Monk mAppSize = findPreference(KEY_APP_SIZE); 160c27f9e179adef2061e0000385f350874a7772c4eJason Monk mDataSize = findPreference(KEY_DATA_SIZE); 161c27f9e179adef2061e0000385f350874a7772c4eJason Monk mExternalCodeSize = findPreference(KEY_EXTERNAL_CODE_SIZE); 162c27f9e179adef2061e0000385f350874a7772c4eJason Monk mExternalDataSize = findPreference(KEY_EXTERNAL_DATA_SIZE); 163cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 164cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (Environment.isExternalStorageEmulated()) { 165c27f9e179adef2061e0000385f350874a7772c4eJason Monk PreferenceCategory category = (PreferenceCategory) findPreference(KEY_STORAGE_CATEGORY); 166c27f9e179adef2061e0000385f350874a7772c4eJason Monk category.removePreference(mExternalCodeSize); 167c27f9e179adef2061e0000385f350874a7772c4eJason Monk category.removePreference(mExternalDataSize); 168cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 169c27f9e179adef2061e0000385f350874a7772c4eJason Monk mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA)) 17060a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk .findViewById(R.id.button); 171cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 172e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mStorageUsed = findPreference(KEY_STORAGE_USED); 173e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE)) 174e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .findViewById(R.id.button); 175e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton.setText(R.string.change); 176e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton.setOnClickListener(this); 177cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 178cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Cache section 179c27f9e179adef2061e0000385f350874a7772c4eJason Monk mCacheSize = findPreference(KEY_CACHE_SIZE); 180c27f9e179adef2061e0000385f350874a7772c4eJason Monk mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_CACHE)) 18160a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk .findViewById(R.id.button); 18260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk mClearCacheButton.setText(R.string.clear_cache_btn_text); 18308703c8bb19b518214bc352199bd46baab597547Felipe Leme 18408703c8bb19b518214bc352199bd46baab597547Felipe Leme // URI permissions section 18508703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri = (PreferenceCategory) findPreference(KEY_URI_CATEGORY); 18608703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUri = (LayoutPreference) mUri.findPreference(KEY_CLEAR_URI); 18708703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton = (Button) mClearUri.findViewById(R.id.button); 18808703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setText(R.string.clear_uri_btn_text); 18908703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setOnClickListener(this); 190cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 191cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 192cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 193cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(View v) { 194cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (v == mClearCacheButton) { 195cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Lazy initialization of observer 196cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mClearCacheObserver == null) { 197cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheObserver = new ClearCacheObserver(); 198cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 199cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver); 200e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk } else if (v == mClearDataButton) { 201cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppEntry.info.manageSpaceActivityName != null) { 202cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (!Utils.isMonkeyRunning()) { 203cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Intent intent = new Intent(Intent.ACTION_DEFAULT); 204cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk intent.setClassName(mAppEntry.info.packageName, 205cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mAppEntry.info.manageSpaceActivityName); 206cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk startActivityForResult(intent, REQUEST_MANAGE_SPACE); 207cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 208cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 209cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk showDialogInner(DLG_CLEAR_DATA, 0); 210cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 21116634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } else if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) { 212e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mDialogBuilder.show(); 21308703c8bb19b518214bc352199bd46baab597547Felipe Leme } else if (v == mClearUriButton) { 21408703c8bb19b518214bc352199bd46baab597547Felipe Leme clearUriPermissions(); 21560a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk } 21660a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk } 21760a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 21816634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey private boolean isMoveInProgress() { 21916634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey try { 22016634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey // TODO: define a cleaner API for this 2219e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey AppGlobals.getPackageManager().checkPackageStartable(mPackageName, 2229e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey UserHandle.myUserId()); 22316634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey return false; 2249e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey } catch (RemoteException | SecurityException e) { 2259e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey return true; 22616634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } 22716634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } 22816634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey 22960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk @Override 230e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk public void onClick(DialogInterface dialog, int which) { 2311f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Context context = getActivity(); 2321f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 2331f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey // If not current volume, kick off move wizard 234e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final VolumeInfo targetVol = mCandidates[which]; 235954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey final VolumeInfo currentVol = context.getPackageManager().getPackageCurrentVolume( 2361f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey mAppEntry.info); 2371f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey if (!Objects.equals(targetVol, currentVol)) { 2381f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Intent intent = new Intent(context, StorageWizardMoveConfirm.class); 2391f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, targetVol.getId()); 2401f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName); 2411f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey startActivity(intent); 242cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 243e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk dialog.dismiss(); 244cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 245cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 246cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private String getSizeStr(long size) { 247cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (size == SIZE_INVALID) { 248cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return mInvalidSizeStr.toString(); 249cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 250cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return Formatter.formatFileSize(getActivity(), size); 251cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 252cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 253cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void refreshSizeInfo() { 254cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppEntry.size == ApplicationsState.SIZE_INVALID 255cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk || mAppEntry.size == ApplicationsState.SIZE_UNKNOWN) { 256cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1; 257cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (!mHaveSizes) { 258c27f9e179adef2061e0000385f350874a7772c4eJason Monk mAppSize.setSummary(mComputingStr); 259c27f9e179adef2061e0000385f350874a7772c4eJason Monk mDataSize.setSummary(mComputingStr); 260c27f9e179adef2061e0000385f350874a7772c4eJason Monk mCacheSize.setSummary(mComputingStr); 261c27f9e179adef2061e0000385f350874a7772c4eJason Monk mTotalSize.setSummary(mComputingStr); 262cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 263cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 264cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheButton.setEnabled(false); 265cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 266cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mHaveSizes = true; 267cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk long codeSize = mAppEntry.codeSize; 268cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk long dataSize = mAppEntry.dataSize; 269cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (Environment.isExternalStorageEmulated()) { 270cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk codeSize += mAppEntry.externalCodeSize; 271cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk dataSize += mAppEntry.externalDataSize; 272cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 273cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastExternalCodeSize != mAppEntry.externalCodeSize) { 274cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastExternalCodeSize = mAppEntry.externalCodeSize; 275c27f9e179adef2061e0000385f350874a7772c4eJason Monk mExternalCodeSize.setSummary(getSizeStr(mAppEntry.externalCodeSize)); 276cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 277cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastExternalDataSize != mAppEntry.externalDataSize) { 278cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastExternalDataSize = mAppEntry.externalDataSize; 279c27f9e179adef2061e0000385f350874a7772c4eJason Monk mExternalDataSize.setSummary(getSizeStr( mAppEntry.externalDataSize)); 280cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 281cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 282cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastCodeSize != codeSize) { 283cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastCodeSize = codeSize; 284c27f9e179adef2061e0000385f350874a7772c4eJason Monk mAppSize.setSummary(getSizeStr(codeSize)); 285cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 286cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastDataSize != dataSize) { 287cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastDataSize = dataSize; 288c27f9e179adef2061e0000385f350874a7772c4eJason Monk mDataSize.setSummary(getSizeStr(dataSize)); 289cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 290cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk long cacheSize = mAppEntry.cacheSize + mAppEntry.externalCacheSize; 291cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastCacheSize != cacheSize) { 292cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastCacheSize = cacheSize; 293c27f9e179adef2061e0000385f350874a7772c4eJason Monk mCacheSize.setSummary(getSizeStr(cacheSize)); 294cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 295cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mLastTotalSize != mAppEntry.size) { 296cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mLastTotalSize = mAppEntry.size; 297c27f9e179adef2061e0000385f350874a7772c4eJason Monk mTotalSize.setSummary(getSizeStr(mAppEntry.size)); 298cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 299cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 300cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if ((mAppEntry.dataSize+ mAppEntry.externalDataSize) <= 0 || !mCanClearData) { 301cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 302cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 303cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(true); 304cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setOnClickListener(this); 305cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 306cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (cacheSize <= 0) { 307cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheButton.setEnabled(false); 308cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 309cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheButton.setEnabled(true); 310cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheButton.setOnClickListener(this); 311cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 312cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 313cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppControlRestricted) { 314cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheButton.setEnabled(false); 315cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 316cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 317cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 318cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 319cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 320cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk protected boolean refreshUi() { 321cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk retrieveAppEntry(); 3229a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds if (mAppEntry == null) { 3239a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds return false; 3249a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds } 325cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk refreshSizeInfo(); 32608703c8bb19b518214bc352199bd46baab597547Felipe Leme refreshGrantedUriPermissions(); 3271f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 3281f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final VolumeInfo currentVol = getActivity().getPackageManager() 329954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey .getPackageCurrentVolume(mAppEntry.info); 330e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final StorageManager storage = getContext().getSystemService(StorageManager.class); 331e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mStorageUsed.setSummary(storage.getBestVolumeDescription(currentVol)); 332e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk 333e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk refreshButtons(); 3341f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 335cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return true; 336cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 337cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 338cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void refreshButtons() { 339e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk initMoveDialog(); 3401f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey initDataButtons(); 341cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 342cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 343cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void initDataButtons() { 344cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // If the app doesn't have its own space management UI 345cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // And it's a system app that doesn't allow clearing user data or is an active admin 346cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Then disable the Clear Data button. 347cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppEntry.info.manageSpaceActivityName == null 348cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk && ((mAppEntry.info.flags&(ApplicationInfo.FLAG_SYSTEM 349cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)) 350cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk == ApplicationInfo.FLAG_SYSTEM 351cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk || mDpm.packageHasActiveAdmins(mPackageName))) { 352cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 353cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 354cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mCanClearData = false; 355cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 356cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppEntry.info.manageSpaceActivityName != null) { 357cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.manage_space_text); 358cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 359cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 360cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 361cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setOnClickListener(this); 362cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 363cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 364cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mAppControlRestricted) { 365cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 366cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 367cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 368cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 369e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private void initMoveDialog() { 3701f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Context context = getActivity(); 3711f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final StorageManager storage = context.getSystemService(StorageManager.class); 3721f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 3731f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final List<VolumeInfo> candidates = context.getPackageManager() 374954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey .getPackageCandidateVolumes(mAppEntry.info); 375c27f9e179adef2061e0000385f350874a7772c4eJason Monk if (candidates.size() > 1) { 376c27f9e179adef2061e0000385f350874a7772c4eJason Monk Collections.sort(candidates, VolumeInfo.getDescriptionComparator()); 3771f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 378e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk CharSequence[] labels = new CharSequence[candidates.size()]; 379e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk int current = -1; 380e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk for (int i = 0; i < candidates.size(); i++) { 381e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final String volDescrip = storage.getBestVolumeDescription(candidates.get(i)); 382e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk if (Objects.equals(volDescrip, mStorageUsed.getSummary())) { 383e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk current = i; 384e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk } 385e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk labels[i] = volDescrip; 386c27f9e179adef2061e0000385f350874a7772c4eJason Monk } 387e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mCandidates = candidates.toArray(new VolumeInfo[candidates.size()]); 388e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mDialogBuilder = new AlertDialog.Builder(getContext()) 389e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setTitle(R.string.change_storage) 390e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setSingleChoiceItems(labels, current, this) 391e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setNegativeButton(R.string.cancel, null); 392c27f9e179adef2061e0000385f350874a7772c4eJason Monk } else { 393e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk removePreference(KEY_STORAGE_USED); 394e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk removePreference(KEY_CHANGE_STORAGE); 395bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk removePreference(KEY_STORAGE_SPACE); 396cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 397cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 398cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 399cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk /* 400cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Private method to initiate clearing user data when the user clicks the clear data 401cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * button for a system package 402cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk */ 403cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void initiateClearUserData() { 404cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 405cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Invoke uninstall or clear user data based on sysPackage 406cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk String packageName = mAppEntry.info.packageName; 407cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Clearing user data for package : " + packageName); 408cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mClearDataObserver == null) { 409cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataObserver = new ClearUserDataObserver(); 410cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 411cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk ActivityManager am = (ActivityManager) 412cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk getActivity().getSystemService(Context.ACTIVITY_SERVICE); 413cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk boolean res = am.clearApplicationUserData(packageName, mClearDataObserver); 414cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (!res) { 415cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Clearing data failed for some obscure reason. Just log error for now 416cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Couldnt clear application user data for package:"+packageName); 417cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk showDialogInner(DLG_CANNOT_CLEAR_DATA, 0); 418cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 419cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.recompute_size); 420cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 421cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 422cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 423cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk /* 424cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Private method to handle clear message notification from observer when 425cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * the async operation from PackageManager is complete 426cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk */ 427cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void processClearMsg(Message msg) { 428cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk int result = msg.arg1; 429cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk String packageName = mAppEntry.info.packageName; 430cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 43160a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk if (result == OP_SUCCESSFUL) { 432cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Cleared user data for package : "+packageName); 43307025891683aef83d850b0a91b37aa75b11ce33cJason Monk mState.requestSize(mPackageName, mUserId); 434cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 435cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(true); 436cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 437cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 438cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 43908703c8bb19b518214bc352199bd46baab597547Felipe Leme private void refreshGrantedUriPermissions() { 44008703c8bb19b518214bc352199bd46baab597547Felipe Leme // Clear UI first (in case the activity has been resumed) 44108703c8bb19b518214bc352199bd46baab597547Felipe Leme removeUriPermissionsFromUi(); 44208703c8bb19b518214bc352199bd46baab597547Felipe Leme 44308703c8bb19b518214bc352199bd46baab597547Felipe Leme // Gets all URI permissions from am. 44408703c8bb19b518214bc352199bd46baab597547Felipe Leme ActivityManager am = (ActivityManager) getActivity().getSystemService( 44508703c8bb19b518214bc352199bd46baab597547Felipe Leme Context.ACTIVITY_SERVICE); 44608703c8bb19b518214bc352199bd46baab597547Felipe Leme List<UriPermission> perms = 44708703c8bb19b518214bc352199bd46baab597547Felipe Leme am.getGrantedUriPermissions(mAppEntry.info.packageName).getList(); 44808703c8bb19b518214bc352199bd46baab597547Felipe Leme 44908703c8bb19b518214bc352199bd46baab597547Felipe Leme if (perms.isEmpty()) { 45008703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setVisibility(View.GONE); 45108703c8bb19b518214bc352199bd46baab597547Felipe Leme return; 45208703c8bb19b518214bc352199bd46baab597547Felipe Leme } 45308703c8bb19b518214bc352199bd46baab597547Felipe Leme 45408703c8bb19b518214bc352199bd46baab597547Felipe Leme PackageManager pm = getActivity().getPackageManager(); 45508703c8bb19b518214bc352199bd46baab597547Felipe Leme 45608703c8bb19b518214bc352199bd46baab597547Felipe Leme // Group number of URIs by app. 45708703c8bb19b518214bc352199bd46baab597547Felipe Leme Map<CharSequence, MutableInt> uriCounters = new TreeMap<>(); 45808703c8bb19b518214bc352199bd46baab597547Felipe Leme for (UriPermission perm : perms) { 45908703c8bb19b518214bc352199bd46baab597547Felipe Leme String authority = perm.getUri().getAuthority(); 46008703c8bb19b518214bc352199bd46baab597547Felipe Leme ProviderInfo provider = pm.resolveContentProvider(authority, 0); 46108703c8bb19b518214bc352199bd46baab597547Felipe Leme CharSequence app = provider.applicationInfo.loadLabel(pm); 46208703c8bb19b518214bc352199bd46baab597547Felipe Leme MutableInt count = uriCounters.get(app); 46308703c8bb19b518214bc352199bd46baab597547Felipe Leme if (count == null) { 46408703c8bb19b518214bc352199bd46baab597547Felipe Leme uriCounters.put(app, new MutableInt(1)); 46508703c8bb19b518214bc352199bd46baab597547Felipe Leme } else { 46608703c8bb19b518214bc352199bd46baab597547Felipe Leme count.value++; 46708703c8bb19b518214bc352199bd46baab597547Felipe Leme } 46808703c8bb19b518214bc352199bd46baab597547Felipe Leme } 46908703c8bb19b518214bc352199bd46baab597547Felipe Leme 47008703c8bb19b518214bc352199bd46baab597547Felipe Leme // Dynamically add the preferences, one per app. 47108703c8bb19b518214bc352199bd46baab597547Felipe Leme int order = 0; 47208703c8bb19b518214bc352199bd46baab597547Felipe Leme for (Map.Entry<CharSequence, MutableInt> entry : uriCounters.entrySet()) { 47308703c8bb19b518214bc352199bd46baab597547Felipe Leme int numberResources = entry.getValue().value; 47408703c8bb19b518214bc352199bd46baab597547Felipe Leme Preference pref = new Preference(getPrefContext()); 47508703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setTitle(entry.getKey()); 47608703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setSummary(getPrefContext().getResources() 47708703c8bb19b518214bc352199bd46baab597547Felipe Leme .getQuantityString(R.plurals.uri_permissions_text, numberResources, 47808703c8bb19b518214bc352199bd46baab597547Felipe Leme numberResources)); 47908703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setSelectable(false); 48008703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setLayoutResource(R.layout.horizontal_preference); 48108703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setOrder(order); 48208703c8bb19b518214bc352199bd46baab597547Felipe Leme Log.v(TAG, "Adding preference '" + pref + "' at order " + order); 48308703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri.addPreference(pref); 48408703c8bb19b518214bc352199bd46baab597547Felipe Leme } 48508703c8bb19b518214bc352199bd46baab597547Felipe Leme 48608703c8bb19b518214bc352199bd46baab597547Felipe Leme if (mAppControlRestricted) { 48708703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setEnabled(false); 48808703c8bb19b518214bc352199bd46baab597547Felipe Leme } 48908703c8bb19b518214bc352199bd46baab597547Felipe Leme 49008703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUri.setOrder(order); 49108703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setVisibility(View.VISIBLE); 49208703c8bb19b518214bc352199bd46baab597547Felipe Leme 49308703c8bb19b518214bc352199bd46baab597547Felipe Leme } 49408703c8bb19b518214bc352199bd46baab597547Felipe Leme 49508703c8bb19b518214bc352199bd46baab597547Felipe Leme private void clearUriPermissions() { 49608703c8bb19b518214bc352199bd46baab597547Felipe Leme // Synchronously revoke the permissions. 49708703c8bb19b518214bc352199bd46baab597547Felipe Leme final ActivityManager am = (ActivityManager) getActivity().getSystemService( 49808703c8bb19b518214bc352199bd46baab597547Felipe Leme Context.ACTIVITY_SERVICE); 49908703c8bb19b518214bc352199bd46baab597547Felipe Leme am.clearGrantedUriPermissions(mAppEntry.info.packageName); 50008703c8bb19b518214bc352199bd46baab597547Felipe Leme 50108703c8bb19b518214bc352199bd46baab597547Felipe Leme // Update UI 50208703c8bb19b518214bc352199bd46baab597547Felipe Leme refreshGrantedUriPermissions(); 50308703c8bb19b518214bc352199bd46baab597547Felipe Leme } 50408703c8bb19b518214bc352199bd46baab597547Felipe Leme 50508703c8bb19b518214bc352199bd46baab597547Felipe Leme private void removeUriPermissionsFromUi() { 50608703c8bb19b518214bc352199bd46baab597547Felipe Leme // Remove all preferences but the clear button. 50708703c8bb19b518214bc352199bd46baab597547Felipe Leme int count = mUri.getPreferenceCount(); 50808703c8bb19b518214bc352199bd46baab597547Felipe Leme for (int i = count - 1; i >= 0; i--) { 50908703c8bb19b518214bc352199bd46baab597547Felipe Leme Preference pref = mUri.getPreference(i); 51008703c8bb19b518214bc352199bd46baab597547Felipe Leme if (pref != mClearUri) { 51108703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri.removePreference(pref); 51208703c8bb19b518214bc352199bd46baab597547Felipe Leme } 51308703c8bb19b518214bc352199bd46baab597547Felipe Leme } 51408703c8bb19b518214bc352199bd46baab597547Felipe Leme } 51508703c8bb19b518214bc352199bd46baab597547Felipe Leme 516cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 517cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk protected AlertDialog createDialog(int id, int errorCode) { 518cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk switch (id) { 519cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case DLG_CLEAR_DATA: 520cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return new AlertDialog.Builder(getActivity()) 521cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setTitle(getActivity().getText(R.string.clear_data_dlg_title)) 522cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setMessage(getActivity().getText(R.string.clear_data_dlg_text)) 523cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 524cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(DialogInterface dialog, int which) { 525cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Clear user data here 526cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk initiateClearUserData(); 527cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 528cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }) 529cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setNegativeButton(R.string.dlg_cancel, null) 530cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .create(); 531cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case DLG_CANNOT_CLEAR_DATA: 532cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return new AlertDialog.Builder(getActivity()) 533cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setTitle(getActivity().getText(R.string.clear_failed_dlg_title)) 534cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setMessage(getActivity().getText(R.string.clear_failed_dlg_text)) 535cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setNeutralButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 536cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(DialogInterface dialog, int which) { 537cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 538cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk //force to recompute changed value 539cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk setIntentAndFinish(false, false); 540cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 541cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }) 542cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .create(); 543cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 544cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return null; 545cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 546cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 547cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 548cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onPackageSizeChanged(String packageName) { 549cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (packageName.equals(mAppEntry.info.packageName)) { 550cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk refreshSizeInfo(); 551cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 552cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 553cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 554cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private final Handler mHandler = new Handler() { 555cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void handleMessage(Message msg) { 556cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (getView() == null) { 557cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return; 558cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 559cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk switch (msg.what) { 560cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case MSG_CLEAR_USER_DATA: 561cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk processClearMsg(msg); 562cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk break; 563cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case MSG_CLEAR_CACHE: 564cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Refresh size info 56507025891683aef83d850b0a91b37aa75b11ce33cJason Monk mState.requestSize(mPackageName, mUserId); 566cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk break; 567cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 568cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 569cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }; 570cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 571cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public static CharSequence getSummary(AppEntry appEntry, Context context) { 572cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (appEntry.size == ApplicationsState.SIZE_INVALID 573cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk || appEntry.size == ApplicationsState.SIZE_UNKNOWN) { 574cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return context.getText(R.string.computing_size); 575cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 576cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk CharSequence storageType = context.getString( 577cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk (appEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 578cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk ? R.string.storage_type_external 579cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk : R.string.storage_type_internal); 580cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return context.getString(R.string.storage_summary_format, 581cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk getSize(appEntry, context), storageType); 582cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 583cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 584cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 585cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static CharSequence getSize(AppEntry appEntry, Context context) { 586cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk long size = appEntry.size; 587cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (size == SIZE_INVALID) { 588cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return context.getText(R.string.invalid_size_value); 589cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 590cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return Formatter.formatFileSize(context, size); 591cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 592cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 5938a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren @Override 5948a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren protected int getMetricsCategory() { 5958a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren return MetricsLogger.APPLICATIONS_APP_STORAGE; 5968a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren } 5978a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren 598cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk class ClearCacheObserver extends IPackageDataObserver.Stub { 599cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onRemoveCompleted(final String packageName, final boolean succeeded) { 600cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk final Message msg = mHandler.obtainMessage(MSG_CLEAR_CACHE); 601cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; 602cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mHandler.sendMessage(msg); 603cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 604cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 605cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 606cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk class ClearUserDataObserver extends IPackageDataObserver.Stub { 607cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onRemoveCompleted(final String packageName, final boolean succeeded) { 608cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA); 60960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; 610cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mHandler.sendMessage(msg); 611cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 612cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 613cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk} 614