AppStorageSettings.java revision 39b467482d1bf256a111c757e9b7621c6f523271
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;
25cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.ApplicationInfo;
26cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.content.pm.IPackageDataObserver;
2716634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkeyimport android.content.pm.IPackageManager;
28cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Bundle;
29cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Environment;
30cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Handler;
31cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.os.Message;
3216634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkeyimport android.os.RemoteException;
331f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.StorageManager;
341f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport android.os.storage.VolumeInfo;
3539b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference;
3639b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceCategory;
37cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.text.format.Formatter;
38cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.util.Log;
39cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View;
40cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.view.View.OnClickListener;
41cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport android.widget.Button;
42cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
438a963babe2e36b7a41f77b8d2598c97658196e58Chris Wrenimport com.android.internal.logging.MetricsLogger;
44cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.R;
45cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monkimport com.android.settings.Utils;
461f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport com.android.settings.deviceinfo.StorageWizardMoveConfirm;
4767cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState;
4867cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.AppEntry;
4967cd6ab93a526fe65877743e458590f4e6f187eeTony Mantlerimport com.android.settingslib.applications.ApplicationsState.Callbacks;
501f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
511f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Collections;
521f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.List;
531f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkeyimport java.util.Objects;
54cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
5560a09ea2388db01a661beeb9995a7ecf770a4200Jason Monkpublic class AppStorageSettings extends AppInfoWithHeader
56e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        implements OnClickListener, Callbacks, DialogInterface.OnClickListener {
57588a0881c13d8ed63ba67b3145254c22211a2019Jason Monk    private static final String TAG = AppStorageSettings.class.getSimpleName();
58cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
59cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    //internal constants used in Handler
60cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int OP_SUCCESSFUL = 1;
61cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int OP_FAILED = 2;
62cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int MSG_CLEAR_USER_DATA = 1;
63cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int MSG_CLEAR_CACHE = 3;
64cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
65cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    // invalid size value used initially and also when size retrieval through PackageManager
66cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    // fails for whatever reason
67cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int SIZE_INVALID = -1;
68cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
69cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    // Result code identifiers
70cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    public static final int REQUEST_MANAGE_SPACE = 2;
71cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
72cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
73cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2;
74cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
75e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private static final String KEY_STORAGE_USED = "storage_used";
76e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private static final String KEY_CHANGE_STORAGE = "change_storage_button";
77bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk    private static final String KEY_STORAGE_SPACE = "storage_space";
78c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_STORAGE_CATEGORY = "storage_category";
7960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk
80c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_TOTAL_SIZE = "total_size";
81c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_APP_SIZE = "app_size";
82c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_EXTERNAL_CODE_SIZE = "external_code_size";
83c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_DATA_SIZE = "data_size";
84c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_EXTERNAL_DATA_SIZE = "external_data_size";
85c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_CACHE_SIZE = "cache_size";
86c27f9e179adef2061e0000385f350874a7772c4eJason Monk
87c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_CLEAR_DATA = "clear_data_button";
88c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private static final String KEY_CLEAR_CACHE = "clear_cache_button";
89c27f9e179adef2061e0000385f350874a7772c4eJason Monk
90c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mTotalSize;
91c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mAppSize;
92c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mDataSize;
93c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mExternalCodeSize;
94c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mExternalDataSize;
95cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
96cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    // Views related to cache info
97c27f9e179adef2061e0000385f350874a7772c4eJason Monk    private Preference mCacheSize;
98cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private Button mClearDataButton;
99cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private Button mClearCacheButton;
10060a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk
101e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private Preference mStorageUsed;
102e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private Button mChangeStorageButton;
103cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
104cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private boolean mCanClearData = true;
105cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private boolean mHaveSizes = false;
106cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
107cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastCodeSize = -1;
108cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastDataSize = -1;
109cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastExternalCodeSize = -1;
110cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastExternalDataSize = -1;
111cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastCacheSize = -1;
112cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private long mLastTotalSize = -1;
113cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
114cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private ClearCacheObserver mClearCacheObserver;
115cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private ClearUserDataObserver mClearDataObserver;
116cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
117cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    // Resource strings
118cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private CharSequence mInvalidSizeStr;
119cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private CharSequence mComputingStr;
120cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
121e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private VolumeInfo[] mCandidates;
122e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private AlertDialog.Builder mDialogBuilder;
123e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk
124cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    @Override
125cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    public void onCreate(Bundle savedInstanceState) {
126cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        super.onCreate(savedInstanceState);
127cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
12860a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk        addPreferencesFromResource(R.xml.app_storage_settings);
12960a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk        setupViews();
130cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
131cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
132ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk    @Override
133ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk    public void onResume() {
134ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk        super.onResume();
135ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk        mState.requestSize(mPackageName, mUserId);
136ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk    }
137ece9d5145f38ec077be9d7f3a2e145500b296a29Jason Monk
13860a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk    private void setupViews() {
139cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        mComputingStr = getActivity().getText(R.string.computing_size);
140cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
141cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
142cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // Set default values on sizes
143c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mTotalSize = findPreference(KEY_TOTAL_SIZE);
144c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mAppSize =  findPreference(KEY_APP_SIZE);
145c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mDataSize =  findPreference(KEY_DATA_SIZE);
146c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mExternalCodeSize = findPreference(KEY_EXTERNAL_CODE_SIZE);
147c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mExternalDataSize = findPreference(KEY_EXTERNAL_DATA_SIZE);
148cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
149cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (Environment.isExternalStorageEmulated()) {
150c27f9e179adef2061e0000385f350874a7772c4eJason Monk            PreferenceCategory category = (PreferenceCategory) findPreference(KEY_STORAGE_CATEGORY);
151c27f9e179adef2061e0000385f350874a7772c4eJason Monk            category.removePreference(mExternalCodeSize);
152c27f9e179adef2061e0000385f350874a7772c4eJason Monk            category.removePreference(mExternalDataSize);
153cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
154c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA))
15560a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk                .findViewById(R.id.button);
156cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
157e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        mStorageUsed = findPreference(KEY_STORAGE_USED);
158e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
159e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                .findViewById(R.id.button);
160e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        mChangeStorageButton.setText(R.string.change);
161e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        mChangeStorageButton.setOnClickListener(this);
162cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
163cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // Cache section
164c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mCacheSize = findPreference(KEY_CACHE_SIZE);
165c27f9e179adef2061e0000385f350874a7772c4eJason Monk        mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_CACHE))
16660a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk                .findViewById(R.id.button);
16760a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk        mClearCacheButton.setText(R.string.clear_cache_btn_text);
168cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
169cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
170cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    @Override
171cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    public void onClick(View v) {
172cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (v == mClearCacheButton) {
173cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            // Lazy initialization of observer
174cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mClearCacheObserver == null) {
175cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearCacheObserver = new ClearCacheObserver();
176cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
177cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver);
178e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        } else if (v == mClearDataButton) {
179cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mAppEntry.info.manageSpaceActivityName != null) {
180cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                if (!Utils.isMonkeyRunning()) {
181cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    Intent intent = new Intent(Intent.ACTION_DEFAULT);
182cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    intent.setClassName(mAppEntry.info.packageName,
183cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                            mAppEntry.info.manageSpaceActivityName);
184cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    startActivityForResult(intent, REQUEST_MANAGE_SPACE);
185cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                }
186cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            } else {
187cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                showDialogInner(DLG_CLEAR_DATA, 0);
188cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
18916634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey        } else if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) {
190e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            mDialogBuilder.show();
19160a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk        }
19260a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk    }
19360a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk
19416634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey    private boolean isMoveInProgress() {
19516634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey        final IPackageManager pm = AppGlobals.getPackageManager();
19616634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey        try {
19716634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey            // TODO: define a cleaner API for this
19816634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey            return pm.isPackageFrozen(mPackageName);
19916634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey        } catch (RemoteException e) {
20016634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey            return false;
20116634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey        }
20216634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey    }
20316634fd0ff74f243aa26ad4714df3a0921bdbe20Jeff Sharkey
20460a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk    @Override
205e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    public void onClick(DialogInterface dialog, int which) {
2061f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        final Context context = getActivity();
2071f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
2081f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        // If not current volume, kick off move wizard
209e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        final VolumeInfo targetVol = mCandidates[which];
210954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey        final VolumeInfo currentVol = context.getPackageManager().getPackageCurrentVolume(
2111f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey                mAppEntry.info);
2121f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        if (!Objects.equals(targetVol, currentVol)) {
2131f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey            final Intent intent = new Intent(context, StorageWizardMoveConfirm.class);
2141f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey            intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, targetVol.getId());
2151f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
2161f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey            startActivity(intent);
217cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
218e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        dialog.dismiss();
219cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
220cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
221cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private String getSizeStr(long size) {
222cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (size == SIZE_INVALID) {
223cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            return mInvalidSizeStr.toString();
224cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
225cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        return Formatter.formatFileSize(getActivity(), size);
226cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
227cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
228cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private void refreshSizeInfo() {
229cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (mAppEntry.size == ApplicationsState.SIZE_INVALID
230cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                || mAppEntry.size == ApplicationsState.SIZE_UNKNOWN) {
231cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
232cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (!mHaveSizes) {
233c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mAppSize.setSummary(mComputingStr);
234c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mDataSize.setSummary(mComputingStr);
235c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mCacheSize.setSummary(mComputingStr);
236c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mTotalSize.setSummary(mComputingStr);
237cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
238cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setEnabled(false);
239cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearCacheButton.setEnabled(false);
240cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
241cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        } else {
242cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mHaveSizes = true;
243cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            long codeSize = mAppEntry.codeSize;
244cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            long dataSize = mAppEntry.dataSize;
245cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (Environment.isExternalStorageEmulated()) {
246cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                codeSize += mAppEntry.externalCodeSize;
247cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                dataSize +=  mAppEntry.externalDataSize;
248cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            } else {
249cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                if (mLastExternalCodeSize != mAppEntry.externalCodeSize) {
250cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    mLastExternalCodeSize = mAppEntry.externalCodeSize;
251c27f9e179adef2061e0000385f350874a7772c4eJason Monk                    mExternalCodeSize.setSummary(getSizeStr(mAppEntry.externalCodeSize));
252cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                }
253cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                if (mLastExternalDataSize !=  mAppEntry.externalDataSize) {
254cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    mLastExternalDataSize =  mAppEntry.externalDataSize;
255c27f9e179adef2061e0000385f350874a7772c4eJason Monk                    mExternalDataSize.setSummary(getSizeStr( mAppEntry.externalDataSize));
256cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                }
257cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
258cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mLastCodeSize != codeSize) {
259cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mLastCodeSize = codeSize;
260c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mAppSize.setSummary(getSizeStr(codeSize));
261cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
262cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mLastDataSize != dataSize) {
263cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mLastDataSize = dataSize;
264c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mDataSize.setSummary(getSizeStr(dataSize));
265cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
266cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            long cacheSize = mAppEntry.cacheSize + mAppEntry.externalCacheSize;
267cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mLastCacheSize != cacheSize) {
268cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mLastCacheSize = cacheSize;
269c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mCacheSize.setSummary(getSizeStr(cacheSize));
270cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
271cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mLastTotalSize != mAppEntry.size) {
272cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mLastTotalSize = mAppEntry.size;
273c27f9e179adef2061e0000385f350874a7772c4eJason Monk                mTotalSize.setSummary(getSizeStr(mAppEntry.size));
274cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
275cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
276cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if ((mAppEntry.dataSize+ mAppEntry.externalDataSize) <= 0 || !mCanClearData) {
277cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearDataButton.setEnabled(false);
278cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            } else {
279cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearDataButton.setEnabled(true);
280cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearDataButton.setOnClickListener(this);
281cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
282cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (cacheSize <= 0) {
283cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearCacheButton.setEnabled(false);
284cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            } else {
285cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearCacheButton.setEnabled(true);
286cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearCacheButton.setOnClickListener(this);
287cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
288cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
289cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (mAppControlRestricted) {
290cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearCacheButton.setEnabled(false);
291cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setEnabled(false);
292cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
293cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
294cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
295cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    @Override
296cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    protected boolean refreshUi() {
297cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        retrieveAppEntry();
2989a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds        if (mAppEntry == null) {
2999a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds            return false;
3009a1c0dce7a496f51087cf0497b931a31c64b0a65Julia Reynolds        }
301cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        refreshSizeInfo();
3021f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
3031f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        final VolumeInfo currentVol = getActivity().getPackageManager()
304954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey                .getPackageCurrentVolume(mAppEntry.info);
305e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        final StorageManager storage = getContext().getSystemService(StorageManager.class);
306e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        mStorageUsed.setSummary(storage.getBestVolumeDescription(currentVol));
307e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk
308e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        refreshButtons();
3091f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
310cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        return true;
311cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
312cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
313cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private void refreshButtons() {
314e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk        initMoveDialog();
3151f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        initDataButtons();
316cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
317cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
318cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private void initDataButtons() {
319cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // If the app doesn't have its own space management UI
320cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // And it's a system app that doesn't allow clearing user data or is an active admin
321cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // Then disable the Clear Data button.
322cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (mAppEntry.info.manageSpaceActivityName == null
323cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                && ((mAppEntry.info.flags&(ApplicationInfo.FLAG_SYSTEM
324cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA))
325cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        == ApplicationInfo.FLAG_SYSTEM
326cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        || mDpm.packageHasActiveAdmins(mPackageName))) {
327cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setText(R.string.clear_user_data_text);
328cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setEnabled(false);
329cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mCanClearData = false;
330cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        } else {
331cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (mAppEntry.info.manageSpaceActivityName != null) {
332cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearDataButton.setText(R.string.manage_space_text);
333cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            } else {
334cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                mClearDataButton.setText(R.string.clear_user_data_text);
335cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
336cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setOnClickListener(this);
337cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
338cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
339cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (mAppControlRestricted) {
340cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setEnabled(false);
341cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
342cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
343cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
344e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk    private void initMoveDialog() {
3451f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        final Context context = getActivity();
3461f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        final StorageManager storage = context.getSystemService(StorageManager.class);
3471f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
3481f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey        final List<VolumeInfo> candidates = context.getPackageManager()
349954d8dad5e395544f95ca211466bcc7195d31877Jeff Sharkey                .getPackageCandidateVolumes(mAppEntry.info);
350c27f9e179adef2061e0000385f350874a7772c4eJason Monk        if (candidates.size() > 1) {
351c27f9e179adef2061e0000385f350874a7772c4eJason Monk            Collections.sort(candidates, VolumeInfo.getDescriptionComparator());
3521f4efd7360dea3038fe2096b1d4bccaae8e2a09fJeff Sharkey
353e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            CharSequence[] labels = new CharSequence[candidates.size()];
354e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            int current = -1;
355e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            for (int i = 0; i < candidates.size(); i++) {
356e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                final String volDescrip = storage.getBestVolumeDescription(candidates.get(i));
357e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                if (Objects.equals(volDescrip, mStorageUsed.getSummary())) {
358e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                    current = i;
359e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                }
360e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                labels[i] = volDescrip;
361c27f9e179adef2061e0000385f350874a7772c4eJason Monk            }
362e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            mCandidates = candidates.toArray(new VolumeInfo[candidates.size()]);
363e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            mDialogBuilder = new AlertDialog.Builder(getContext())
364e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                    .setTitle(R.string.change_storage)
365e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                    .setSingleChoiceItems(labels, current, this)
366e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk                    .setNegativeButton(R.string.cancel, null);
367c27f9e179adef2061e0000385f350874a7772c4eJason Monk        } else {
368e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            removePreference(KEY_STORAGE_USED);
369e8400c2fb78e80979b5190d4abc9685442cdfc25Jason Monk            removePreference(KEY_CHANGE_STORAGE);
370bd45c3cbe0ccb9d5a1ebeabccda1e803d613e729Jason Monk            removePreference(KEY_STORAGE_SPACE);
371cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
372cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
373cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
374cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    /*
375cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     * Private method to initiate clearing user data when the user clicks the clear data
376cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     * button for a system package
377cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     */
378cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private void initiateClearUserData() {
379cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        mClearDataButton.setEnabled(false);
380cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        // Invoke uninstall or clear user data based on sysPackage
381cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        String packageName = mAppEntry.info.packageName;
382cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        Log.i(TAG, "Clearing user data for package : " + packageName);
383cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (mClearDataObserver == null) {
384cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataObserver = new ClearUserDataObserver();
385cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
386cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        ActivityManager am = (ActivityManager)
387cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                getActivity().getSystemService(Context.ACTIVITY_SERVICE);
388cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
389cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (!res) {
390cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            // Clearing data failed for some obscure reason. Just log error for now
391cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
392cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
393cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        } else {
394cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setText(R.string.recompute_size);
395cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
396cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
397cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
398cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    /*
399cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     * Private method to handle clear message notification from observer when
400cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     * the async operation from PackageManager is complete
401cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk     */
402cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private void processClearMsg(Message msg) {
403cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        int result = msg.arg1;
404cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        String packageName = mAppEntry.info.packageName;
405cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        mClearDataButton.setText(R.string.clear_user_data_text);
40660a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk        if (result == OP_SUCCESSFUL) {
407cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            Log.i(TAG, "Cleared user data for package : "+packageName);
40807025891683aef83d850b0a91b37aa75b11ce33cJason Monk            mState.requestSize(mPackageName, mUserId);
409cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        } else {
410cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mClearDataButton.setEnabled(true);
411cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
412cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
413cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
414cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    @Override
415cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    protected AlertDialog createDialog(int id, int errorCode) {
416cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        switch (id) {
417cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            case DLG_CLEAR_DATA:
418cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                return new AlertDialog.Builder(getActivity())
419cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setTitle(getActivity().getText(R.string.clear_data_dlg_title))
420cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setMessage(getActivity().getText(R.string.clear_data_dlg_text))
421cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
422cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                            public void onClick(DialogInterface dialog, int which) {
423cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                                // Clear user data here
424cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                                initiateClearUserData();
425cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                            }
426cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        })
427cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setNegativeButton(R.string.dlg_cancel, null)
428cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .create();
429cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            case DLG_CANNOT_CLEAR_DATA:
430cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                return new AlertDialog.Builder(getActivity())
431cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setTitle(getActivity().getText(R.string.clear_failed_dlg_title))
432cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setMessage(getActivity().getText(R.string.clear_failed_dlg_text))
433cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .setNeutralButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
434cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                            public void onClick(DialogInterface dialog, int which) {
435cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                                mClearDataButton.setEnabled(false);
436cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                                //force to recompute changed value
437cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                                setIntentAndFinish(false, false);
438cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                            }
439cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        })
440cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                        .create();
441cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
442cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        return null;
443cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
444cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
445cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    @Override
446cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    public void onPackageSizeChanged(String packageName) {
447cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (packageName.equals(mAppEntry.info.packageName)) {
448cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            refreshSizeInfo();
449cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
450cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
451cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
452cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private final Handler mHandler = new Handler() {
453cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        public void handleMessage(Message msg) {
454cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            if (getView() == null) {
455cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                return;
456cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
457cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            switch (msg.what) {
458cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                case MSG_CLEAR_USER_DATA:
459cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    processClearMsg(msg);
460cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    break;
461cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                case MSG_CLEAR_CACHE:
462cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    // Refresh size info
46307025891683aef83d850b0a91b37aa75b11ce33cJason Monk                    mState.requestSize(mPackageName, mUserId);
464cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    break;
465cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            }
466cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
467cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    };
468cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
469cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    public static CharSequence getSummary(AppEntry appEntry, Context context) {
470cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (appEntry.size == ApplicationsState.SIZE_INVALID
471cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                || appEntry.size == ApplicationsState.SIZE_UNKNOWN) {
472cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            return context.getText(R.string.computing_size);
473cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        } else {
474cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            CharSequence storageType = context.getString(
475cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    (appEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0
476cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    ? R.string.storage_type_external
477cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    : R.string.storage_type_internal);
478cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            return context.getString(R.string.storage_summary_format,
479cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk                    getSize(appEntry, context), storageType);
480cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
481cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
482cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
483cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    private static CharSequence getSize(AppEntry appEntry, Context context) {
484cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        long size = appEntry.size;
485cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        if (size == SIZE_INVALID) {
486cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            return context.getText(R.string.invalid_size_value);
487cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
488cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        return Formatter.formatFileSize(context, size);
489cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
490cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
4918a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    @Override
4928a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    protected int getMetricsCategory() {
4938a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren        return MetricsLogger.APPLICATIONS_APP_STORAGE;
4948a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren    }
4958a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren
496cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    class ClearCacheObserver extends IPackageDataObserver.Stub {
497cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        public void onRemoveCompleted(final String packageName, final boolean succeeded) {
498cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            final Message msg = mHandler.obtainMessage(MSG_CLEAR_CACHE);
499cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED;
500cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk            mHandler.sendMessage(msg);
501cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
502cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
503cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk
504cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    class ClearUserDataObserver extends IPackageDataObserver.Stub {
505cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk       public void onRemoveCompleted(final String packageName, final boolean succeeded) {
506cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk           final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA);
50760a09ea2388db01a661beeb9995a7ecf770a4200Jason Monk           msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED;
508cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk           mHandler.sendMessage(msg);
509cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk        }
510cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk    }
511cd91128a2de5d111c59fe442c72b764d9a9acb3aJason Monk}
512