AppStorageSettings.java revision 6a256e77d624967470f60c68dab6d5447e8a24cb
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; 223344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishiimport android.app.LoaderManager; 23cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.Context; 24cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.DialogInterface; 25cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.Intent; 263344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishiimport android.content.Loader; 2708703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.UriPermission; 28cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.ApplicationInfo; 29cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.IPackageDataObserver; 3008703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.pm.PackageManager; 3108703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.content.pm.ProviderInfo; 32cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Bundle; 33cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Environment; 34cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Handler; 35cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Message; 3616634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkeyimport android.os.RemoteException; 379e9f7d11162df92bc430002423a281e22176de41Jeff Sharkeyimport android.os.UserHandle; 381f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.StorageManager; 391f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.VolumeInfo; 4039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference; 4139b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceCategory; 42cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.text.format.Formatter; 43cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.util.Log; 4408703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport android.util.MutableInt; 45cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View; 46cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View.OnClickListener; 47cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.widget.Button; 48cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 49265d3c2a0c36251bf8a9f571d7239b6dd404d942Tamas Berghammerimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 50cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.R; 51cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.Utils; 521f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport com.android.settings.deviceinfo.StorageWizardMoveConfirm; 53ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils; 5467cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState; 5567cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.AppEntry; 5667cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.Callbacks; 573344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishiimport com.android.settingslib.applications.StorageStatsSource; 583344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishiimport com.android.settingslib.applications.StorageStatsSource.AppStorageStats; 591f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 601f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Collections; 611f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.List; 6208703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport java.util.Map; 631f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Objects; 6408703c8bb19b518214bc352199bd46baab597547Felipe Lemeimport java.util.TreeMap; 65cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 668f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritzeimport static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; 678f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritzeimport static android.content.pm.ApplicationInfo.FLAG_SYSTEM; 688f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze 6960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monkpublic class AppStorageSettings extends AppInfoWithHeader 703344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi implements OnClickListener, Callbacks, DialogInterface.OnClickListener, 713344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi LoaderManager.LoaderCallbacks<AppStorageStats> { 72588a0881c13d8ed63ba67b3145254c22211a2019Jason Monk private static final String TAG = AppStorageSettings.class.getSimpleName(); 73cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 74cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk //internal constants used in Handler 75cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int OP_SUCCESSFUL = 1; 76cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int OP_FAILED = 2; 77cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int MSG_CLEAR_USER_DATA = 1; 78cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int MSG_CLEAR_CACHE = 3; 79cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 80cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // invalid size value used initially and also when size retrieval through PackageManager 81cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // fails for whatever reason 82cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int SIZE_INVALID = -1; 83cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 84cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Result code identifiers 85cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public static final int REQUEST_MANAGE_SPACE = 2; 86cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 87cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int DLG_CLEAR_DATA = DLG_BASE + 1; 88cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2; 89cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 90e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private static final String KEY_STORAGE_USED = "storage_used"; 91e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private static final String KEY_CHANGE_STORAGE = "change_storage_button"; 92bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk private static final String KEY_STORAGE_SPACE = "storage_space"; 93c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_STORAGE_CATEGORY = "storage_category"; 9460a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 95c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_TOTAL_SIZE = "total_size"; 96c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_APP_SIZE = "app_size"; 97c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_EXTERNAL_CODE_SIZE = "external_code_size"; 98c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_DATA_SIZE = "data_size"; 99c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_EXTERNAL_DATA_SIZE = "external_data_size"; 100c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CACHE_SIZE = "cache_size"; 101c27f9e179adef2061e0000385f350874a7772c4eJason Monk 102c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CLEAR_DATA = "clear_data_button"; 103c27f9e179adef2061e0000385f350874a7772c4eJason Monk private static final String KEY_CLEAR_CACHE = "clear_cache_button"; 104c27f9e179adef2061e0000385f350874a7772c4eJason Monk 10508703c8bb19b518214bc352199bd46baab597547Felipe Leme private static final String KEY_URI_CATEGORY = "uri_category"; 10608703c8bb19b518214bc352199bd46baab597547Felipe Leme private static final String KEY_CLEAR_URI = "clear_uri_button"; 10708703c8bb19b518214bc352199bd46baab597547Felipe Leme 108cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Views related to cache info 109c27f9e179adef2061e0000385f350874a7772c4eJason Monk private Preference mCacheSize; 110cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private Button mClearDataButton; 111cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private Button mClearCacheButton; 11260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 113e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private Preference mStorageUsed; 114e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private Button mChangeStorageButton; 115cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 11608703c8bb19b518214bc352199bd46baab597547Felipe Leme // Views related to URI permissions 11708703c8bb19b518214bc352199bd46baab597547Felipe Leme private Button mClearUriButton; 11808703c8bb19b518214bc352199bd46baab597547Felipe Leme private LayoutPreference mClearUri; 11908703c8bb19b518214bc352199bd46baab597547Felipe Leme private PreferenceCategory mUri; 12008703c8bb19b518214bc352199bd46baab597547Felipe Leme 121cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private boolean mCanClearData = true; 122cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 1233344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi private AppStorageStats mLastResult; 1246a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi private AppStorageSizesController mSizeController; 125cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 126cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private ClearCacheObserver mClearCacheObserver; 127cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private ClearUserDataObserver mClearDataObserver; 128cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 129cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Resource strings 130cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private CharSequence mInvalidSizeStr; 131cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private CharSequence mComputingStr; 132cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 133e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private VolumeInfo[] mCandidates; 134e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private AlertDialog.Builder mDialogBuilder; 1353344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi private ApplicationInfo mInfo; 136e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk 137cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 138cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onCreate(Bundle savedInstanceState) { 139cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk super.onCreate(savedInstanceState); 140cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 14160a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk addPreferencesFromResource(R.xml.app_storage_settings); 14260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk setupViews(); 143b7a7158b18147afbeacca604788e28d0d1209b07Jason Monk initMoveDialog(); 144cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 145cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 146ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk @Override 147ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk public void onResume() { 148ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk super.onResume(); 1493344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi updateSize(); 150ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk } 151ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk 15260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk private void setupViews() { 153cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mComputingStr = getActivity().getText(R.string.computing_size); 154cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value); 155cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 156cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Set default values on sizes 1576a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi mSizeController = new AppStorageSizesController.Builder() 1586a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setTotalSizePreference(findPreference(KEY_TOTAL_SIZE)) 1596a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setAppSizePreference(findPreference(KEY_APP_SIZE)) 1606a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setDataSizePreference(findPreference(KEY_DATA_SIZE)) 1616a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setCacheSizePreference(findPreference(KEY_CACHE_SIZE)) 1626a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setComputingString(R.string.computing_size) 1636a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .setErrorString(R.string.invalid_size_value) 1646a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi .build(); 1656a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi 166c27f9e179adef2061e0000385f350874a7772c4eJason Monk mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA)) 16760a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk .findViewById(R.id.button); 168cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 169e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mStorageUsed = findPreference(KEY_STORAGE_USED); 170e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE)) 171e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .findViewById(R.id.button); 172e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton.setText(R.string.change); 173e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mChangeStorageButton.setOnClickListener(this); 174cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 175cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Cache section 176c27f9e179adef2061e0000385f350874a7772c4eJason Monk mCacheSize = findPreference(KEY_CACHE_SIZE); 177c27f9e179adef2061e0000385f350874a7772c4eJason Monk mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_CACHE)) 17860a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk .findViewById(R.id.button); 17960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk mClearCacheButton.setText(R.string.clear_cache_btn_text); 18008703c8bb19b518214bc352199bd46baab597547Felipe Leme 18108703c8bb19b518214bc352199bd46baab597547Felipe Leme // URI permissions section 18208703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri = (PreferenceCategory) findPreference(KEY_URI_CATEGORY); 18308703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUri = (LayoutPreference) mUri.findPreference(KEY_CLEAR_URI); 18408703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton = (Button) mClearUri.findViewById(R.id.button); 18508703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setText(R.string.clear_uri_btn_text); 18608703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setOnClickListener(this); 187cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 188cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 189cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 190cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(View v) { 191cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (v == mClearCacheButton) { 1929e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { 193ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka RestrictedLockUtils.sendShowAdminSupportDetailsIntent( 194ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka getActivity(), mAppsControlDisallowedAdmin); 195ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka return; 196ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka } else if (mClearCacheObserver == null) { // Lazy initialization of observer 197cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearCacheObserver = new ClearCacheObserver(); 198cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 199cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver); 200e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk } else if (v == mClearDataButton) { 2019e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { 202ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka RestrictedLockUtils.sendShowAdminSupportDetailsIntent( 203ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka getActivity(), mAppsControlDisallowedAdmin); 204ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka } else if (mAppEntry.info.manageSpaceActivityName != null) { 205cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (!Utils.isMonkeyRunning()) { 206cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Intent intent = new Intent(Intent.ACTION_DEFAULT); 207cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk intent.setClassName(mAppEntry.info.packageName, 208cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mAppEntry.info.manageSpaceActivityName); 209cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk startActivityForResult(intent, REQUEST_MANAGE_SPACE); 210cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 211cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 212cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk showDialogInner(DLG_CLEAR_DATA, 0); 213cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 21416634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } else if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) { 215e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mDialogBuilder.show(); 21608703c8bb19b518214bc352199bd46baab597547Felipe Leme } else if (v == mClearUriButton) { 2179e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) { 218ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka RestrictedLockUtils.sendShowAdminSupportDetailsIntent( 219ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka getActivity(), mAppsControlDisallowedAdmin); 220ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka } else { 221ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka clearUriPermissions(); 222ef550767b0b469534a94c293ea517a19778b58b0Sudheer Shanka } 22360a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk } 22460a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk } 22560a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk 22616634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey private boolean isMoveInProgress() { 22716634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey try { 22816634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey // TODO: define a cleaner API for this 2299e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey AppGlobals.getPackageManager().checkPackageStartable(mPackageName, 2309e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey UserHandle.myUserId()); 23116634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey return false; 2329e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey } catch (RemoteException | SecurityException e) { 2339e9f7d11162df92bc430002423a281e22176de41Jeff Sharkey return true; 23416634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } 23516634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey } 23616634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey 23760a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk @Override 238e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk public void onClick(DialogInterface dialog, int which) { 2391f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Context context = getActivity(); 2401f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 2411f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey // If not current volume, kick off move wizard 242e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final VolumeInfo targetVol = mCandidates[which]; 243954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey final VolumeInfo currentVol = context.getPackageManager().getPackageCurrentVolume( 2441f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey mAppEntry.info); 2451f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey if (!Objects.equals(targetVol, currentVol)) { 2461f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Intent intent = new Intent(context, StorageWizardMoveConfirm.class); 2471f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, targetVol.getId()); 2481f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName); 2491f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey startActivity(intent); 250cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 251e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk dialog.dismiss(); 252cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 253cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 254cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 255cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk protected boolean refreshUi() { 256cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk retrieveAppEntry(); 2579a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds if (mAppEntry == null) { 2589a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds return false; 2599a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds } 2603344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi updateUiWithSize(mLastResult); 26108703c8bb19b518214bc352199bd46baab597547Felipe Leme refreshGrantedUriPermissions(); 2621f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 2631f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final VolumeInfo currentVol = getActivity().getPackageManager() 264954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey .getPackageCurrentVolume(mAppEntry.info); 265e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final StorageManager storage = getContext().getSystemService(StorageManager.class); 266e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mStorageUsed.setSummary(storage.getBestVolumeDescription(currentVol)); 267e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk 268e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk refreshButtons(); 2691f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 270cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return true; 271cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 272cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 273cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void refreshButtons() { 274e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk initMoveDialog(); 2751f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey initDataButtons(); 276cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 277cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 278cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void initDataButtons() { 2798f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final boolean appHasSpaceManagementUI = mAppEntry.info.manageSpaceActivityName != null; 2808f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final boolean appHasActiveAdmins = mDpm.packageHasActiveAdmins(mPackageName); 2818f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze // Check that SYSTEM_APP flag is set, and ALLOW_CLEAR_USER_DATA is not set. 2828f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final boolean isNonClearableSystemApp = 2838f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze (mAppEntry.info.flags & (FLAG_SYSTEM | FLAG_ALLOW_CLEAR_USER_DATA)) == FLAG_SYSTEM; 2848f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final boolean appRestrictsClearingData = isNonClearableSystemApp || appHasActiveAdmins; 2858f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze 2868f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final Intent intent = new Intent(Intent.ACTION_DEFAULT); 2878f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze if (appHasSpaceManagementUI) { 2888f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze intent.setClassName(mAppEntry.info.packageName, mAppEntry.info.manageSpaceActivityName); 2898f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze } 2908f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze final boolean isManageSpaceActivityAvailable = 2918f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze getPackageManager().resolveActivity(intent, 0) != null; 2928f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze 2938f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze if ((!appHasSpaceManagementUI && appRestrictsClearingData) 2948f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze || !isManageSpaceActivityAvailable) { 295cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 296cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 297cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mCanClearData = false; 298cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 2998f17fcaa1dd85c816916ffbed3f66ad80c2bbf0aMatthew Fritze if (appHasSpaceManagementUI) { 300cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.manage_space_text); 301cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 302cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 303cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 304cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setOnClickListener(this); 305cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 3069e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka 3079e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka if (mAppsControlDisallowedBySystem) { 3089e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka mClearDataButton.setEnabled(false); 3099e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka } 310cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 311cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 312e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk private void initMoveDialog() { 3131f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final Context context = getActivity(); 3141f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final StorageManager storage = context.getSystemService(StorageManager.class); 3151f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 3161f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey final List<VolumeInfo> candidates = context.getPackageManager() 317954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey .getPackageCandidateVolumes(mAppEntry.info); 318c27f9e179adef2061e0000385f350874a7772c4eJason Monk if (candidates.size() > 1) { 319c27f9e179adef2061e0000385f350874a7772c4eJason Monk Collections.sort(candidates, VolumeInfo.getDescriptionComparator()); 3201f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey 321e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk CharSequence[] labels = new CharSequence[candidates.size()]; 322e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk int current = -1; 323e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk for (int i = 0; i < candidates.size(); i++) { 324e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk final String volDescrip = storage.getBestVolumeDescription(candidates.get(i)); 325e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk if (Objects.equals(volDescrip, mStorageUsed.getSummary())) { 326e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk current = i; 327e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk } 328e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk labels[i] = volDescrip; 329c27f9e179adef2061e0000385f350874a7772c4eJason Monk } 330e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mCandidates = candidates.toArray(new VolumeInfo[candidates.size()]); 331e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk mDialogBuilder = new AlertDialog.Builder(getContext()) 332e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setTitle(R.string.change_storage) 333e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setSingleChoiceItems(labels, current, this) 334e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk .setNegativeButton(R.string.cancel, null); 335c27f9e179adef2061e0000385f350874a7772c4eJason Monk } else { 336e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk removePreference(KEY_STORAGE_USED); 337e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk removePreference(KEY_CHANGE_STORAGE); 338bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk removePreference(KEY_STORAGE_SPACE); 339cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 340cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 341cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 342cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk /* 343cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Private method to initiate clearing user data when the user clicks the clear data 344cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * button for a system package 345cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk */ 346cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void initiateClearUserData() { 347cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 348cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Invoke uninstall or clear user data based on sysPackage 349cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk String packageName = mAppEntry.info.packageName; 350cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Clearing user data for package : " + packageName); 351cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (mClearDataObserver == null) { 352cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataObserver = new ClearUserDataObserver(); 353cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 354cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk ActivityManager am = (ActivityManager) 355cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk getActivity().getSystemService(Context.ACTIVITY_SERVICE); 356cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk boolean res = am.clearApplicationUserData(packageName, mClearDataObserver); 357cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (!res) { 358cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Clearing data failed for some obscure reason. Just log error for now 359cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Couldnt clear application user data for package:"+packageName); 360cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk showDialogInner(DLG_CANNOT_CLEAR_DATA, 0); 361cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 362cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.recompute_size); 363cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 364cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 365cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 366cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk /* 367cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * Private method to handle clear message notification from observer when 368cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk * the async operation from PackageManager is complete 369cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk */ 370cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private void processClearMsg(Message msg) { 371cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk int result = msg.arg1; 372cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk String packageName = mAppEntry.info.packageName; 373cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setText(R.string.clear_user_data_text); 37460a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk if (result == OP_SUCCESSFUL) { 375cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk Log.i(TAG, "Cleared user data for package : "+packageName); 3763344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi updateSize(); 377cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } else { 378cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(true); 379cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 380cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 381cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 38208703c8bb19b518214bc352199bd46baab597547Felipe Leme private void refreshGrantedUriPermissions() { 38308703c8bb19b518214bc352199bd46baab597547Felipe Leme // Clear UI first (in case the activity has been resumed) 38408703c8bb19b518214bc352199bd46baab597547Felipe Leme removeUriPermissionsFromUi(); 38508703c8bb19b518214bc352199bd46baab597547Felipe Leme 38608703c8bb19b518214bc352199bd46baab597547Felipe Leme // Gets all URI permissions from am. 38708703c8bb19b518214bc352199bd46baab597547Felipe Leme ActivityManager am = (ActivityManager) getActivity().getSystemService( 38808703c8bb19b518214bc352199bd46baab597547Felipe Leme Context.ACTIVITY_SERVICE); 38908703c8bb19b518214bc352199bd46baab597547Felipe Leme List<UriPermission> perms = 39008703c8bb19b518214bc352199bd46baab597547Felipe Leme am.getGrantedUriPermissions(mAppEntry.info.packageName).getList(); 39108703c8bb19b518214bc352199bd46baab597547Felipe Leme 39208703c8bb19b518214bc352199bd46baab597547Felipe Leme if (perms.isEmpty()) { 39308703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setVisibility(View.GONE); 39408703c8bb19b518214bc352199bd46baab597547Felipe Leme return; 39508703c8bb19b518214bc352199bd46baab597547Felipe Leme } 39608703c8bb19b518214bc352199bd46baab597547Felipe Leme 39708703c8bb19b518214bc352199bd46baab597547Felipe Leme PackageManager pm = getActivity().getPackageManager(); 39808703c8bb19b518214bc352199bd46baab597547Felipe Leme 39908703c8bb19b518214bc352199bd46baab597547Felipe Leme // Group number of URIs by app. 40008703c8bb19b518214bc352199bd46baab597547Felipe Leme Map<CharSequence, MutableInt> uriCounters = new TreeMap<>(); 40108703c8bb19b518214bc352199bd46baab597547Felipe Leme for (UriPermission perm : perms) { 40208703c8bb19b518214bc352199bd46baab597547Felipe Leme String authority = perm.getUri().getAuthority(); 40308703c8bb19b518214bc352199bd46baab597547Felipe Leme ProviderInfo provider = pm.resolveContentProvider(authority, 0); 40408703c8bb19b518214bc352199bd46baab597547Felipe Leme CharSequence app = provider.applicationInfo.loadLabel(pm); 40508703c8bb19b518214bc352199bd46baab597547Felipe Leme MutableInt count = uriCounters.get(app); 40608703c8bb19b518214bc352199bd46baab597547Felipe Leme if (count == null) { 40708703c8bb19b518214bc352199bd46baab597547Felipe Leme uriCounters.put(app, new MutableInt(1)); 40808703c8bb19b518214bc352199bd46baab597547Felipe Leme } else { 40908703c8bb19b518214bc352199bd46baab597547Felipe Leme count.value++; 41008703c8bb19b518214bc352199bd46baab597547Felipe Leme } 41108703c8bb19b518214bc352199bd46baab597547Felipe Leme } 41208703c8bb19b518214bc352199bd46baab597547Felipe Leme 41308703c8bb19b518214bc352199bd46baab597547Felipe Leme // Dynamically add the preferences, one per app. 41408703c8bb19b518214bc352199bd46baab597547Felipe Leme int order = 0; 41508703c8bb19b518214bc352199bd46baab597547Felipe Leme for (Map.Entry<CharSequence, MutableInt> entry : uriCounters.entrySet()) { 41608703c8bb19b518214bc352199bd46baab597547Felipe Leme int numberResources = entry.getValue().value; 41708703c8bb19b518214bc352199bd46baab597547Felipe Leme Preference pref = new Preference(getPrefContext()); 41808703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setTitle(entry.getKey()); 41908703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setSummary(getPrefContext().getResources() 42008703c8bb19b518214bc352199bd46baab597547Felipe Leme .getQuantityString(R.plurals.uri_permissions_text, numberResources, 42108703c8bb19b518214bc352199bd46baab597547Felipe Leme numberResources)); 42208703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setSelectable(false); 42308703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setLayoutResource(R.layout.horizontal_preference); 42408703c8bb19b518214bc352199bd46baab597547Felipe Leme pref.setOrder(order); 42508703c8bb19b518214bc352199bd46baab597547Felipe Leme Log.v(TAG, "Adding preference '" + pref + "' at order " + order); 42608703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri.addPreference(pref); 42708703c8bb19b518214bc352199bd46baab597547Felipe Leme } 42808703c8bb19b518214bc352199bd46baab597547Felipe Leme 4299e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka if (mAppsControlDisallowedBySystem) { 4309e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka mClearUriButton.setEnabled(false); 4319e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka } 4329e9e63b7b3b31fcae7242eb07f528487e0913402Sudheer Shanka 43308703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUri.setOrder(order); 43408703c8bb19b518214bc352199bd46baab597547Felipe Leme mClearUriButton.setVisibility(View.VISIBLE); 43508703c8bb19b518214bc352199bd46baab597547Felipe Leme 43608703c8bb19b518214bc352199bd46baab597547Felipe Leme } 43708703c8bb19b518214bc352199bd46baab597547Felipe Leme 43808703c8bb19b518214bc352199bd46baab597547Felipe Leme private void clearUriPermissions() { 43908703c8bb19b518214bc352199bd46baab597547Felipe Leme // Synchronously revoke the permissions. 44008703c8bb19b518214bc352199bd46baab597547Felipe Leme final ActivityManager am = (ActivityManager) getActivity().getSystemService( 44108703c8bb19b518214bc352199bd46baab597547Felipe Leme Context.ACTIVITY_SERVICE); 44208703c8bb19b518214bc352199bd46baab597547Felipe Leme am.clearGrantedUriPermissions(mAppEntry.info.packageName); 44308703c8bb19b518214bc352199bd46baab597547Felipe Leme 44408703c8bb19b518214bc352199bd46baab597547Felipe Leme // Update UI 44508703c8bb19b518214bc352199bd46baab597547Felipe Leme refreshGrantedUriPermissions(); 44608703c8bb19b518214bc352199bd46baab597547Felipe Leme } 44708703c8bb19b518214bc352199bd46baab597547Felipe Leme 44808703c8bb19b518214bc352199bd46baab597547Felipe Leme private void removeUriPermissionsFromUi() { 44908703c8bb19b518214bc352199bd46baab597547Felipe Leme // Remove all preferences but the clear button. 45008703c8bb19b518214bc352199bd46baab597547Felipe Leme int count = mUri.getPreferenceCount(); 45108703c8bb19b518214bc352199bd46baab597547Felipe Leme for (int i = count - 1; i >= 0; i--) { 45208703c8bb19b518214bc352199bd46baab597547Felipe Leme Preference pref = mUri.getPreference(i); 45308703c8bb19b518214bc352199bd46baab597547Felipe Leme if (pref != mClearUri) { 45408703c8bb19b518214bc352199bd46baab597547Felipe Leme mUri.removePreference(pref); 45508703c8bb19b518214bc352199bd46baab597547Felipe Leme } 45608703c8bb19b518214bc352199bd46baab597547Felipe Leme } 45708703c8bb19b518214bc352199bd46baab597547Felipe Leme } 45808703c8bb19b518214bc352199bd46baab597547Felipe Leme 459cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 460cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk protected AlertDialog createDialog(int id, int errorCode) { 461cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk switch (id) { 462cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case DLG_CLEAR_DATA: 463cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return new AlertDialog.Builder(getActivity()) 464cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setTitle(getActivity().getText(R.string.clear_data_dlg_title)) 465cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setMessage(getActivity().getText(R.string.clear_data_dlg_text)) 466cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 467cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(DialogInterface dialog, int which) { 468cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Clear user data here 469cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk initiateClearUserData(); 470cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 471cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }) 472cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setNegativeButton(R.string.dlg_cancel, null) 473cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .create(); 474cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case DLG_CANNOT_CLEAR_DATA: 475cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return new AlertDialog.Builder(getActivity()) 476cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setTitle(getActivity().getText(R.string.clear_failed_dlg_title)) 477cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setMessage(getActivity().getText(R.string.clear_failed_dlg_text)) 478cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .setNeutralButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { 479cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onClick(DialogInterface dialog, int which) { 480cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mClearDataButton.setEnabled(false); 481cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk //force to recompute changed value 482cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk setIntentAndFinish(false, false); 483cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 484cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }) 485cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk .create(); 486cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 487cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return null; 488cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 489cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 490cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk @Override 491cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onPackageSizeChanged(String packageName) { 4923344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 4933344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 4943344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi @Override 4953344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi public Loader<AppStorageStats> onCreateLoader(int id, Bundle args) { 4963344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi Context context = getContext(); 4973344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi return new FetchPackageStorageAsyncLoader( 4983344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi context, new StorageStatsSource(context), mInfo, UserHandle.of(mUserId)); 4993344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5003344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5013344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi @Override 5023344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi public void onLoadFinished(Loader<AppStorageStats> loader, AppStorageStats result) { 5036a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi mSizeController.setResult(result); 5043344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi updateUiWithSize(result); 5053344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5063344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5073344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi @Override 5083344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi public void onLoaderReset(Loader<AppStorageStats> loader) { 5093344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5103344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5113344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi private void updateSize() { 5123344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi PackageManager packageManager = getPackageManager(); 5133344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi try { 5143344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mInfo = packageManager.getApplicationInfo(mPackageName, 0); 5153344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } catch (PackageManager.NameNotFoundException e) { 5163344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi Log.e(TAG, "Could not find package", e); 5173344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5183344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5193344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi if (mInfo == null) { 5203344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi return; 5213344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5223344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5233344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi getLoaderManager().restartLoader(1, Bundle.EMPTY, this); 5243344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5253344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5263344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi private void updateUiWithSize(AppStorageStats result) { 5276a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi mSizeController.updateUi(getContext()); 5286a256e77d624967470f60c68dab6d5447e8a24cbDaniel Nishi 5293344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi if (result == null) { 5303344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearDataButton.setEnabled(false); 5313344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearCacheButton.setEnabled(false); 5323344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } else { 5333344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi long codeSize = result.getCodeBytes(); 5343344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi long dataSize = result.getDataBytes(); 5353344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi long cacheSize = result.getCacheBytes(); 5363344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi 5373344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi if (dataSize <= 0 || !mCanClearData) { 5383344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearDataButton.setEnabled(false); 5393344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } else { 5403344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearDataButton.setEnabled(true); 5413344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearDataButton.setOnClickListener(this); 5423344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5433344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi if (cacheSize <= 0) { 5443344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearCacheButton.setEnabled(false); 5453344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } else { 5463344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearCacheButton.setEnabled(true); 5473344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearCacheButton.setOnClickListener(this); 5483344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5493344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi } 5503344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi if (mAppsControlDisallowedBySystem) { 5513344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearCacheButton.setEnabled(false); 5523344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi mClearDataButton.setEnabled(false); 553cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 554cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 555cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 556cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk private final Handler mHandler = new Handler() { 557cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void handleMessage(Message msg) { 558cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk if (getView() == null) { 559cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk return; 560cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 561cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk switch (msg.what) { 562cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case MSG_CLEAR_USER_DATA: 563cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk processClearMsg(msg); 564cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk break; 565cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk case MSG_CLEAR_CACHE: 566cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk // Refresh size info 5673344782bac06e871dd7da1c721cb299861f6b6ceDaniel Nishi updateSize(); 568cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk break; 569cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 570cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 571cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk }; 572cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 5738a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren @Override 5746507613ebcd22e4691c2af92a5c161bd327db336Fan Zhang public int getMetricsCategory() { 5759d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wren return MetricsEvent.APPLICATIONS_APP_STORAGE; 5768a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren } 5778a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren 578cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk class ClearCacheObserver extends IPackageDataObserver.Stub { 579cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onRemoveCompleted(final String packageName, final boolean succeeded) { 580cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk final Message msg = mHandler.obtainMessage(MSG_CLEAR_CACHE); 581cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; 582cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mHandler.sendMessage(msg); 583cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 584cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 585cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk 586cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk class ClearUserDataObserver extends IPackageDataObserver.Stub { 587cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk public void onRemoveCompleted(final String packageName, final boolean succeeded) { 588cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA); 58960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED; 590cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk mHandler.sendMessage(msg); 591cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 592cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk } 593cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk} 594