1547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler/*
2547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * Copyright (C) 2011 The Android Open Source Project
3547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler *
4547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
5547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * you may not use this file except in compliance with the License.
6547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * You may obtain a copy of the License at
7547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler *
8547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
9547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler *
10547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * Unless required by applicable law or agreed to in writing, software
11547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
12547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * See the License for the specific language governing permissions and
14547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * limitations under the License.
15547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler */
16547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
17547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerpackage com.android.settingslib.deviceinfo;
18547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
19547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.app.ActivityManager;
20547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.ComponentName;
21547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.Context;
22547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.Intent;
23547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.ServiceConnection;
24547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.pm.ApplicationInfo;
25547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.pm.IPackageStatsObserver;
26547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.pm.PackageManager;
27547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.pm.PackageStats;
28547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.content.pm.UserInfo;
29547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.Environment;
30547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.Handler;
31547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.HandlerThread;
32547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.IBinder;
33547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.Looper;
34547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.Message;
35547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.UserHandle;
36547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.UserManager;
37547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.storage.StorageVolume;
38547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.os.storage.VolumeInfo;
39547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.util.Log;
4047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Banimport android.util.SparseArray;
41547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport android.util.SparseLongArray;
42547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
43547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport com.android.internal.app.IMediaContainerService;
44547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport com.android.internal.util.ArrayUtils;
45547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport com.google.android.collect.Sets;
46547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
47547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.io.File;
48547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.lang.ref.WeakReference;
49547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.util.ArrayList;
50547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.util.HashMap;
51547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.util.List;
52547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.util.Objects;
53547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerimport java.util.Set;
54547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
55547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler/**
56547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * Utility for measuring the disk usage of internal storage or a physical
57547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * {@link StorageVolume}. Connects with a remote {@link IMediaContainerService}
58547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler * and delivers results to {@link MeasurementReceiver}.
59547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler */
60547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantlerpublic class StorageMeasurement {
61547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static final String TAG = "StorageMeasurement";
62547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
63547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static final boolean LOCAL_LOGV = true;
64547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);
65547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
66547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
67547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
68547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
69547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");
70547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
71547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    /** Media types to measure on external storage. */
72547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static final Set<String> sMeasureMediaTypes = Sets.newHashSet(
73547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
74547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
75547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
76547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
77547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);
78547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
79547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public static class MeasurementDetails {
809496a2da0500934353abb6042fab6661eb49555aTony Mantler        public long totalSize;
819496a2da0500934353abb6042fab6661eb49555aTony Mantler        public long availSize;
829496a2da0500934353abb6042fab6661eb49555aTony Mantler
83547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        /**
8447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * Total apps disk usage per profiles of the current user.
85547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * <p>
86547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * When measuring internal storage, this value includes the code size of
8747adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * all apps (regardless of install status for the given profile), and
8847adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * internal disk used by the profile's apps. When the device
89547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * emulates external storage, this value also includes emulated storage
9047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * used by the profile's apps.
91547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * <p>
92547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * When measuring a physical {@link StorageVolume}, this value includes
9347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * usage by all apps on that volume and only for the primary profile.
9447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * <p>
9547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * Key is {@link UserHandle}.
96547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         */
9747adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        public SparseLongArray appsSize = new SparseLongArray();
98547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
99547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        /**
10047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * Total cache disk usage by apps (over all users and profiles).
101547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         */
102547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public long cacheSize;
103547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
104547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        /**
105547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * Total media disk usage, categorized by types such as
10647adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * {@link Environment#DIRECTORY_MUSIC} for every user profile of the current user.
107547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * <p>
108547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * When measuring internal storage, this reflects media on emulated
10947adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * storage for the respective profile.
110547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * <p>
111547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * When measuring a physical {@link StorageVolume}, this reflects media
112547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * on that volume.
11347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * <p>
11447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * Key of the {@link SparseArray} is {@link UserHandle}.
115547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         */
11647adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        public SparseArray<HashMap<String, Long>> mediaSize = new SparseArray<>();
117547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
118547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        /**
11947adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * Misc external disk usage for the current user's profiles, unaccounted in
12047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban         * {@link #mediaSize}. Key is {@link UserHandle}.
121547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         */
12247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        public SparseLongArray miscSize = new SparseLongArray();
123547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
124547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        /**
125547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * Total disk usage for users, which is only meaningful for emulated
126547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         * internal storage. Key is {@link UserHandle}.
127547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler         */
128547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public SparseLongArray usersSize = new SparseLongArray();
129547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
130547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
131547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public interface MeasurementReceiver {
1329496a2da0500934353abb6042fab6661eb49555aTony Mantler        void onDetailsChanged(MeasurementDetails details);
133547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
134547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
135547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private WeakReference<MeasurementReceiver> mReceiver;
136547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
137547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private final Context mContext;
138547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
139547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private final VolumeInfo mVolume;
140547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private final VolumeInfo mSharedVolume;
141547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
142547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private final MainHandler mMainHandler;
143547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private final MeasurementHandler mMeasurementHandler;
144547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
145547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public StorageMeasurement(Context context, VolumeInfo volume, VolumeInfo sharedVolume) {
146547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mContext = context.getApplicationContext();
147547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
148547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mVolume = volume;
149547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mSharedVolume = sharedVolume;
150547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
151547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        // Start the thread that will measure the disk usage.
152547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
153547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        handlerThread.start();
154547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
155547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mMainHandler = new MainHandler();
156547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mMeasurementHandler = new MeasurementHandler(handlerThread.getLooper());
157547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
158547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
159547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public void setReceiver(MeasurementReceiver receiver) {
160547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        if (mReceiver == null || mReceiver.get() == null) {
161547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mReceiver = new WeakReference<MeasurementReceiver>(receiver);
162547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
163547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
164547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
165547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public void forceMeasure() {
166547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        invalidate();
167547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        measure();
168547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
169547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
170547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public void measure() {
171547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        if (!mMeasurementHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
172547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
173547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
174547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
175547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
176547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    public void onDestroy() {
177547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mReceiver = null;
178547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mMeasurementHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
179547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
180547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
181547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
182547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private void invalidate() {
183547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
184547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
185547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
186547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static class StatsObserver extends IPackageStatsObserver.Stub {
187547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private final boolean mIsPrivate;
188547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private final MeasurementDetails mDetails;
189547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private final int mCurrentUser;
190547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private final Message mFinished;
191547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
192547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private int mRemaining;
193547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
194547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public StatsObserver(boolean isPrivate, MeasurementDetails details, int currentUser,
19547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                List<UserInfo> profiles, Message finished, int remaining) {
196547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mIsPrivate = isPrivate;
197547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mDetails = details;
198547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mCurrentUser = currentUser;
19947adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            if (isPrivate) {
20047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                // Add the profile ids as keys to detail's app sizes.
20147adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                for (UserInfo userInfo : profiles) {
20247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                    mDetails.appsSize.put(userInfo.id, 0);
20347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                }
20447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            }
205547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mFinished = finished;
206547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            mRemaining = remaining;
207547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
208547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
209547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        @Override
210547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
211547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            synchronized (mDetails) {
212547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                if (succeeded) {
213547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    addStatsLocked(stats);
214547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
215547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                if (--mRemaining == 0) {
216547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    mFinished.sendToTarget();
217547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
218547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
219547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
220547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
221547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private void addStatsLocked(PackageStats stats) {
222547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (mIsPrivate) {
223547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                long codeSize = stats.codeSize;
224547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                long dataSize = stats.dataSize;
225547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                long cacheSize = stats.cacheSize;
226547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                if (Environment.isExternalStorageEmulated()) {
227547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    // Include emulated storage when measuring internal. OBB is
228547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    // shared on emulated storage, so treat as code.
229547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    codeSize += stats.externalCodeSize + stats.externalObbSize;
230547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    dataSize += stats.externalDataSize + stats.externalMediaSize;
231547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    cacheSize += stats.externalCacheSize;
232547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
233547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
23447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                // Count code and data for current user's profiles (keys prepared in constructor)
23547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                addValueIfKeyExists(mDetails.appsSize, stats.userHandle, codeSize + dataSize);
236547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
237547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // User summary only includes data (code is only counted once
238547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // for the current user)
239547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                addValue(mDetails.usersSize, stats.userHandle, dataSize);
240547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
241547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // Include cache for all users
242547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                mDetails.cacheSize += cacheSize;
243547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
244547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            } else {
245547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // Physical storage; only count external sizes
24647adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                addValue(mDetails.appsSize, mCurrentUser,
24747adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                        stats.externalCodeSize + stats.externalDataSize
24847adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                        + stats.externalMediaSize + stats.externalObbSize);
249547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                mDetails.cacheSize += stats.externalCacheSize;
250547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
251547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
252547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
253547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
254547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private class MainHandler extends Handler {
255547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        @Override
256547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public void handleMessage(Message msg) {
257547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final MeasurementDetails details = (MeasurementDetails) msg.obj;
258547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
259547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (receiver != null) {
260547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                receiver.onDetailsChanged(details);
261547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
262547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
263547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
264547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
265547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private class MeasurementHandler extends Handler {
266547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public static final int MSG_MEASURE = 1;
267547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public static final int MSG_CONNECTED = 2;
268547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public static final int MSG_DISCONNECT = 3;
269547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public static final int MSG_COMPLETED = 4;
270547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public static final int MSG_INVALIDATE = 5;
271547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
272547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private Object mLock = new Object();
273547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
274547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private IMediaContainerService mDefaultContainer;
275547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
276547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private volatile boolean mBound = false;
277547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
278547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private MeasurementDetails mCached;
279547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
280547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        private final ServiceConnection mDefContainerConn = new ServiceConnection() {
281547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            @Override
282547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            public void onServiceConnected(ComponentName name, IBinder service) {
283547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                final IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(
284547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        service);
285547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                mDefaultContainer = imcs;
286547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                mBound = true;
287547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                sendMessage(obtainMessage(MSG_CONNECTED, imcs));
288547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
289547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
290547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            @Override
291547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            public void onServiceDisconnected(ComponentName name) {
292547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                mBound = false;
293547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                removeMessages(MSG_CONNECTED);
294547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
295547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        };
296547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
297547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public MeasurementHandler(Looper looper) {
298547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            super(looper);
299547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
300547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
301547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        @Override
302547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        public void handleMessage(Message msg) {
303547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            switch (msg.what) {
304547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                case MSG_MEASURE: {
305547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    if (mCached != null) {
306547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        mMainHandler.obtainMessage(0, mCached).sendToTarget();
307547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        break;
308547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    }
309547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
310547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    synchronized (mLock) {
311547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        if (mBound) {
312547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            removeMessages(MSG_DISCONNECT);
313547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
314547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        } else {
315547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
316547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            mContext.bindServiceAsUser(service, mDefContainerConn,
317547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                                    Context.BIND_AUTO_CREATE, UserHandle.OWNER);
318547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        }
319547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    }
320547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    break;
321547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
322547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                case MSG_CONNECTED: {
323547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    final IMediaContainerService imcs = (IMediaContainerService) msg.obj;
324547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    measureExactStorage(imcs);
325547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    break;
326547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
327547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                case MSG_DISCONNECT: {
328547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    synchronized (mLock) {
329547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        if (mBound) {
330547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            mBound = false;
331547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                            mContext.unbindService(mDefContainerConn);
332547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                        }
333547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    }
334547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    break;
335547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
336547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                case MSG_COMPLETED: {
337547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    mCached = (MeasurementDetails) msg.obj;
338547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    mMainHandler.obtainMessage(0, mCached).sendToTarget();
339547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    break;
340547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
341547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                case MSG_INVALIDATE: {
342547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    mCached = null;
343547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    break;
344547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
345547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
346547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
347547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
348547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
349547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private void measureExactStorage(IMediaContainerService imcs) {
350547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final UserManager userManager = mContext.getSystemService(UserManager.class);
351547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final PackageManager packageManager = mContext.getPackageManager();
352547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
353547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final List<UserInfo> users = userManager.getUsers();
35447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        final List<UserInfo> currentProfiles = userManager.getEnabledProfiles(
35547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                ActivityManager.getCurrentUser());
356547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
357547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final MeasurementDetails details = new MeasurementDetails();
358547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
359547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                details);
360547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
361ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler        if (mVolume == null || !mVolume.isMountedReadable()) {
362ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler            finished.sendToTarget();
363ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler            return;
364ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler        }
365ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler
366547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
36747adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            for (UserInfo currentUserInfo : currentProfiles) {
36847adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                final int userId = currentUserInfo.id;
36947adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                final File basePath = mSharedVolume.getPathForUser(userId);
37047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                HashMap<String, Long> mediaMap = new HashMap<>(sMeasureMediaTypes.size());
37147adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                details.mediaSize.put(userId, mediaMap);
37247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban
37347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                // Measure media types for emulated storage, or for primary physical
37447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                // external volume
37547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                for (String type : sMeasureMediaTypes) {
37647adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                    final File path = new File(basePath, type);
37747adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                    final long size = getDirectorySize(imcs, path);
37847adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                    mediaMap.put(type, size);
37947adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                }
380547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
38147adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                // Measure misc files not counted under media
38247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                addValue(details.miscSize, userId, measureMisc(imcs, basePath));
38347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            }
384547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
385547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (mSharedVolume.getType() == VolumeInfo.TYPE_EMULATED) {
386547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // Measure total emulated storage of all users; internal apps data
387547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                // will be spliced in later
388547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                for (UserInfo user : users) {
389547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    final File userPath = mSharedVolume.getPathForUser(user.id);
390547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    final long size = getDirectorySize(imcs, userPath);
391547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    addValue(details.usersSize, user.id, size);
392547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
393547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
394547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
395547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
3969496a2da0500934353abb6042fab6661eb49555aTony Mantler        final File file = mVolume.getPath();
397ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler        if (file != null) {
398ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler            details.totalSize = file.getTotalSpace();
399ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler            details.availSize = file.getFreeSpace();
400ca2954830c017c49523d5e2c7cb5916c76a52375Tony Mantler        }
4019496a2da0500934353abb6042fab6661eb49555aTony Mantler
402547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        // Measure all apps hosted on this volume for all users
403547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
404547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
405547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    PackageManager.GET_UNINSTALLED_PACKAGES
406547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    | PackageManager.GET_DISABLED_COMPONENTS);
407547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
408547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final List<ApplicationInfo> volumeApps = new ArrayList<>();
409547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            for (ApplicationInfo app : apps) {
410547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
411547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    volumeApps.add(app);
412547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
413547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
414547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
415547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final int count = users.size() * volumeApps.size();
416547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (count == 0) {
417547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                finished.sendToTarget();
418547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                return;
419547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
420547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
42147adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            final StatsObserver observer = new StatsObserver(true, details,
42247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban                    ActivityManager.getCurrentUser(), currentProfiles, finished, count);
423547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            for (UserInfo user : users) {
424547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                for (ApplicationInfo app : volumeApps) {
425547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                    packageManager.getPackageSizeInfo(app.packageName, user.id, observer);
426547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                }
427547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
428547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
429547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        } else {
430547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            finished.sendToTarget();
431547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            return;
432547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
433547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
434547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
435547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static long getDirectorySize(IMediaContainerService imcs, File path) {
436547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        try {
437547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final long size = imcs.calculateDirectorySize(path.toString());
438547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Log.d(TAG, "getDirectorySize(" + path + ") returned " + size);
439547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            return size;
440547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        } catch (Exception e) {
441547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            Log.w(TAG, "Could not read memory from default container service for " + path, e);
442547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            return 0;
443547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
444547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
445547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
446547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private long measureMisc(IMediaContainerService imcs, File dir) {
447547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        final File[] files = dir.listFiles();
448547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        if (ArrayUtils.isEmpty(files)) return 0;
449547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
450547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        // Get sizes of all top level nodes except the ones already computed
451547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        long miscSize = 0;
452547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        for (File file : files) {
453547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            final String name = file.getName();
454547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (sMeasureMediaTypes.contains(name)) {
455547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                continue;
456547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
457547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
458547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            if (file.isFile()) {
459547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                miscSize += file.length();
460547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            } else if (file.isDirectory()) {
461547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler                miscSize += getDirectorySize(imcs, file);
462547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler            }
463547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        }
464547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        return miscSize;
465547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
466547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler
467547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    private static void addValue(SparseLongArray array, int key, long value) {
468547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler        array.put(key, array.get(key) + value);
469547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler    }
47047adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban
47147adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban    private static void addValueIfKeyExists(SparseLongArray array, int key, long value) {
47247adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        final int index = array.indexOfKey(key);
47347adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        if (index >= 0) {
47447adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban            array.put(key, array.valueAt(index) + value);
47547adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban        }
47647adcb9feadfe8230b6c95b096d7a8653c358507Zoltan Szatmary-Ban    }
477547e4caebe0aac21d0856de96e121b8bf63fd9bdTony Mantler}
478