1e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey/* 2e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * Copyright (C) 2015 The Android Open Source Project 3e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * 4e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * you may not use this file except in compliance with the License. 6e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * You may obtain a copy of the License at 7e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * 8e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * 10e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * See the License for the specific language governing permissions and 14e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * limitations under the License. 15e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey */ 16e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 17e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeypackage com.android.settings.deviceinfo; 18e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 19e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.content.ComponentName; 20e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.content.Context; 21e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.content.Intent; 22e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.content.ServiceConnection; 23e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.net.TrafficStats; 24e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.AsyncTask; 25e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.IBinder; 26e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.RemoteException; 27e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.UserHandle; 28e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.storage.StorageManager; 29e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.os.storage.VolumeInfo; 30e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.telecom.Log; 31e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.text.format.DateUtils; 32e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport android.text.format.Formatter; 33e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 34e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport com.android.internal.app.IMediaContainerService; 35e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 36e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport java.util.concurrent.CountDownLatch; 37e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeyimport java.util.concurrent.TimeUnit; 38e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 3939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static com.android.settings.deviceinfo.StorageSettings.TAG; 4039b467482d1bf256a111c757e9b7621c6f523271Jason Monk 41e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkeypublic abstract class MigrateEstimateTask extends AsyncTask<Void, Void, Long> implements 42e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey ServiceConnection { 43e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private static final String EXTRA_SIZE_BYTES = "size_bytes"; 44e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 45e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( 46e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService"); 47e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 48e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey /** 49e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey * Assume roughly a Class 10 card. 50e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey */ 51e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private static final long SPEED_ESTIMATE_BPS = 10 * TrafficStats.MB_IN_BYTES; 52e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 53e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private final Context mContext; 54e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private final StorageManager mStorage; 55e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 56e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private final CountDownLatch mConnected = new CountDownLatch(1); 57e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private IMediaContainerService mService; 58e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 59e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey private long mSizeBytes = -1; 60e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 61e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public MigrateEstimateTask(Context context) { 62e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mContext = context; 63e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mStorage = context.getSystemService(StorageManager.class); 64e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 65e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 66e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public void copyFrom(Intent intent) { 67e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mSizeBytes = intent.getLongExtra(EXTRA_SIZE_BYTES, -1); 68e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 69e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 70e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public void copyTo(Intent intent) { 71e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey intent.putExtra(EXTRA_SIZE_BYTES, mSizeBytes); 72e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 73e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 74e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey @Override 75e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey protected Long doInBackground(Void... params) { 76e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey if (mSizeBytes != -1) { 77e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey return mSizeBytes; 78e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 79e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 80e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey final VolumeInfo privateVol = mContext.getPackageManager().getPrimaryStorageCurrentVolume(); 81e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey final VolumeInfo emulatedVol = mStorage.findEmulatedForPrivate(privateVol); 82e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 836a0082b483eb487c44dec5e8855cf0e1ab92020bJeff Sharkey if (emulatedVol == null) { 846a0082b483eb487c44dec5e8855cf0e1ab92020bJeff Sharkey Log.w(TAG, "Failed to find current primary storage"); 856a0082b483eb487c44dec5e8855cf0e1ab92020bJeff Sharkey return -1L; 866a0082b483eb487c44dec5e8855cf0e1ab92020bJeff Sharkey } 876a0082b483eb487c44dec5e8855cf0e1ab92020bJeff Sharkey 88e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey final String path = emulatedVol.getPath().getAbsolutePath(); 89e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey Log.d(TAG, "Estimating for current path " + path); 90e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 91e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey final Intent intent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); 929965b1438bc347f93401874b84eeabb9b33caba4Xiaohui Chen mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM); 93e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 94e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey try { 95e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey if (mConnected.await(15, TimeUnit.SECONDS)) { 96e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey return mService.calculateDirectorySize(path); 97e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 98e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } catch (InterruptedException | RemoteException e) { 99e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey Log.w(TAG, "Failed to measure " + path); 100e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } finally { 101e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mContext.unbindService(this); 102e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 103e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 104e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey return -1L; 105e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 106e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 107e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey @Override 108e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey protected void onPostExecute(Long result) { 109e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mSizeBytes = result; 110538f6de918a130fd8649250a4465f2b7d87a6ff9Xiaohui Chen long timeMillis = (mSizeBytes * DateUtils.SECOND_IN_MILLIS) / SPEED_ESTIMATE_BPS; 111538f6de918a130fd8649250a4465f2b7d87a6ff9Xiaohui Chen timeMillis = Math.max(timeMillis, DateUtils.SECOND_IN_MILLIS); 112e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 113e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey final String size = Formatter.formatFileSize(mContext, mSizeBytes); 114538f6de918a130fd8649250a4465f2b7d87a6ff9Xiaohui Chen final String time = DateUtils.formatDuration(timeMillis).toString(); 115e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey onPostExecute(size, time); 116e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 117e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 118e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public abstract void onPostExecute(String size, String time); 119e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 120e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey @Override 121e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public void onServiceConnected(ComponentName name, IBinder service) { 122e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mService = IMediaContainerService.Stub.asInterface(service); 123e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey mConnected.countDown(); 124e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 125e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey 126e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey @Override 127e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey public void onServiceDisconnected(ComponentName name) { 128e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey // Ignored; we leave service in place for the background thread to 129e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey // run into DeadObjectException 130e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey } 131e77f0687dd424ccfdc2b1061221c6c8ba4d6ac8dJeff Sharkey} 132