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