BatteryStatsHelper.java revision c3e9ac937a4ba948d47cbb83f6999af34fd00b65
1c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang/*
2c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * Copyright (C) 2009 The Android Open Source Project
3c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang *
4c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * Licensed under the Apache License, Version 2.0 (the "License");
5c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * you may not use this file except in compliance with the License.
6c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * You may obtain a copy of the License at
7c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang *
8c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang *      http://www.apache.org/licenses/LICENSE-2.0
9c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang *
10c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * Unless required by applicable law or agreed to in writing, software
11c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * distributed under the License is distributed on an "AS IS" BASIS,
12c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * See the License for the specific language governing permissions and
14c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * limitations under the License.
15c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang */
16c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
17c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangpackage com.android.settings.fuelgauge;
18c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
19c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport static android.os.BatteryStats.NETWORK_MOBILE_RX_BYTES;
20c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport static android.os.BatteryStats.NETWORK_MOBILE_TX_BYTES;
21c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport static android.os.BatteryStats.NETWORK_WIFI_RX_BYTES;
22c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport static android.os.BatteryStats.NETWORK_WIFI_TX_BYTES;
23c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
24c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.app.Activity;
25c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.content.Context;
26c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.content.pm.UserInfo;
27c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.graphics.drawable.Drawable;
28c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.hardware.Sensor;
29c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.hardware.SensorManager;
30c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.BatteryStats;
31c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.BatteryStats.Uid;
32c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.Bundle;
33c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.Handler;
34c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.Parcel;
35c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.Process;
36c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.RemoteException;
37c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.ServiceManager;
38c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.SystemClock;
39c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.UserHandle;
40c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.os.UserManager;
41c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.preference.PreferenceActivity;
42c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.telephony.SignalStrength;
43c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.util.Log;
44c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport android.util.SparseArray;
45c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
46c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.internal.app.IBatteryStats;
47c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.internal.os.BatteryStatsImpl;
48c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.internal.os.PowerProfile;
49c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.internal.util.FastPrintWriter;
50c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.settings.R;
51c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
52c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport com.android.settings.users.UserUtils;
53c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
54c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.io.PrintWriter;
55c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.io.StringWriter;
56c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.io.Writer;
57c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.util.ArrayList;
58c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.util.Collections;
59c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.util.List;
60c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangimport java.util.Map;
61c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
62c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang/**
63c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * A helper class for retrieving the power usage information for all applications and services.
64c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang *
65c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * The caller must initialize this class as soon as activity object is ready to use (for example, in
66c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang * onAttach() for Fragment), call create() in onCreate() and call destroy() in onDestroy().
67c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang */
68c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tangpublic class BatteryStatsHelper {
69c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
70c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private static final boolean DEBUG = false;
71c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
72c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private static final String TAG = BatteryStatsHelper.class.getSimpleName();
73c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
74c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private static BatteryStatsImpl sStatsXfer;
75c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private IBatteryStats mBatteryInfo;
76c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private UserManager mUm;
77c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private BatteryStatsImpl mStats;
78c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private PowerProfile mPowerProfile;
79c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
80c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private final List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
81c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private final List<BatterySipper> mWifiSippers = new ArrayList<BatterySipper>();
82c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private final List<BatterySipper> mBluetoothSippers = new ArrayList<BatterySipper>();
83c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private final SparseArray<List<BatterySipper>> mUserSippers
84c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            = new SparseArray<List<BatterySipper>>();
85c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private final SparseArray<Double> mUserPower = new SparseArray<Double>();
86c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
87c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
88c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
89c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private long mStatsPeriod = 0;
90c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double mMaxPower = 1;
91c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double mTotalPower;
92c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double mWifiPower;
93c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double mBluetoothPower;
94c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
95c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    // How much the apps together have left WIFI running.
96c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private long mAppWifiRunning;
97c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
98c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /** Queue for fetching name and icon for an application */
99c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>();
100c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
101c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private Activity mActivity;
102c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private Handler mHandler;
103c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
104c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private class NameAndIconLoader extends Thread {
105c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        private boolean mAbort = false;
106c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
107c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        public NameAndIconLoader() {
108c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            super("BatteryUsage Icon Loader");
109c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
110c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
111c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        public void abort() {
112c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mAbort = true;
113c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
114c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
115c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        @Override
116c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        public void run() {
117c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            while (true) {
118c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatterySipper bs;
119c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                synchronized (mRequestQueue) {
120c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (mRequestQueue.isEmpty() || mAbort) {
121c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
122c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        return;
123c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
124c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    bs = mRequestQueue.remove(0);
125c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
126c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                bs.loadNameAndIcon();
127c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
128c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
129c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
130c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
131c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private NameAndIconLoader mRequestThread;
132c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
133c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public BatteryStatsHelper(Activity activity, Handler handler) {
134c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mActivity = activity;
135c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mHandler = handler;
136c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
137c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
138c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /** Clears the current stats and forces recreating for future use. */
139c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void clearStats() {
140c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mStats = null;
141c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
142c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
143c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public BatteryStatsImpl getStats() {
144c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (mStats == null) {
145c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            load();
146c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
147c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mStats;
148c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
149c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
150c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public PowerProfile getPowerProfile() {
151c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mPowerProfile;
152c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
153c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
154c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void create(Bundle icicle) {
155c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (icicle != null) {
156c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mStats = sStatsXfer;
157c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
158c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mBatteryInfo = IBatteryStats.Stub.asInterface(
159c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                ServiceManager.getService(BatteryStats.SERVICE_NAME));
160c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUm = (UserManager) mActivity.getSystemService(Context.USER_SERVICE);
161c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mPowerProfile = new PowerProfile(mActivity);
162c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
163c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
164c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void pause() {
165c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (mRequestThread != null) {
166c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mRequestThread.abort();
167c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
168c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
169c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
170c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void destroy() {
171c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (mActivity.isChangingConfigurations()) {
172c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            sStatsXfer = mStats;
173c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        } else {
174c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            BatterySipper.sUidCache.clear();
175c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
176c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
177c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
178c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void startBatteryDetailPage(PreferenceActivity caller, BatterySipper sipper) {
179c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Initialize mStats if necessary.
180c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        getStats();
181c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
182c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        Bundle args = new Bundle();
183c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putString(PowerUsageDetail.EXTRA_TITLE, sipper.name);
184c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
185c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
186c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
187c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
188c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, mStatsPeriod);
189c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
190c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
191c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
192c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (sipper.uidObj != null) {
193c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            args.putInt(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
194c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
195c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
196c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
197c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        int[] types;
198c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double[] values;
199c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        switch (sipper.drainType) {
200c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case APP:
201c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case USER:
202c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
203c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid uid = sipper.uidObj;
204c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
205c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
206c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
207c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
208c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_gps,
209c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wifi_running,
210c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
211c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
212c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
213c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
214c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_audio,
215c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_video,
216c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
217c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
218c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
219c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
220c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
221c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.gpsTime,
222c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRunningTime,
223c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
224c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
225c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
226c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
227c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    0,
228c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    0
229c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
230c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
231c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (sipper.drainType == DrainType.APP) {
232c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Writer result = new StringWriter();
233c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
234c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mStats.dumpLocked(printWriter, "", mStatsType, uid.getUid());
235c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter.flush();
236c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
237c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
238c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    result = new StringWriter();
239c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter = new FastPrintWriter(result, false, 1024);
240c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mStats.dumpCheckinLocked(printWriter, mStatsType, uid.getUid());
241c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter.flush();
242c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
243c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            result.toString());
244c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
245c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
246c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            break;
247c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case CELL:
248c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
249c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
250c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time,
251c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_no_coverage
252c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
253c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
254c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
255c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.noCoveragePercent
256c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
257c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
258c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            break;
259c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case WIFI:
260c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
261c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
262c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wifi_running,
263c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
264c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
265c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
266c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
267c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
268c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
269c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
270c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
271c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
272c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
273c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
274c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
275c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
276c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
277c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
278c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
279c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
280c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
281c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } break;
282c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case BLUETOOTH:
283c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
284c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
285c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time,
286c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
287c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
288c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
289c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
290c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
291c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
292c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
293c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
294c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
295c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
296c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
297c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
298c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
299c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
300c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
301c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
302c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
303c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
304c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } break;
305c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            default:
306c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
307c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
308c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time
309c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
310c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
311c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime
312c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
313c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
314c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
315c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
316c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
317c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
318c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.string.details_title, null, null, 0);
319c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
320c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
321c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public void refreshStats() {
322c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Initialize mStats if necessary.
323c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        getStats();
324c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
325c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mMaxPower = 0;
326c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mTotalPower = 0;
327c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mWifiPower = 0;
328c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mBluetoothPower = 0;
329c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mAppWifiRunning = 0;
330c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
331c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUsageList.clear();
332c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mWifiSippers.clear();
333c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mBluetoothSippers.clear();
334c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUserSippers.clear();
335c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUserPower.clear();
336c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
337c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        processAppUsage();
338c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        processMiscUsage();
339c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
340c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        Collections.sort(mUsageList);
341c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
342c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (mHandler != null) {
343c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            synchronized (mRequestQueue) {
344c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (!mRequestQueue.isEmpty()) {
345c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (mRequestThread != null) {
346c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        mRequestThread.abort();
347c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
348c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread = new NameAndIconLoader();
349c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread.setPriority(Thread.MIN_PRIORITY);
350c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread.start();
351c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestQueue.notify();
352c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
353c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
354c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
355c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
356c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
357c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void processAppUsage() {
358c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        SensorManager sensorManager = (SensorManager) mActivity.getSystemService(
359c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Context.SENSOR_SERVICE);
360c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int which = mStatsType;
361c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int speedSteps = mPowerProfile.getNumSpeedSteps();
362c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double[] powerCpuNormal = new double[speedSteps];
363c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long[] cpuSpeedStepTimes = new long[speedSteps];
364c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int p = 0; p < speedSteps; p++) {
365c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
366c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
367c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double mobilePowerPerByte = getMobilePowerPerByte();
368c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double wifiPowerPerByte = getWifiPowerPerByte();
369c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
370c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long appWakelockTime = 0;
371c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper osApp = null;
372c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mStatsPeriod = uSecTime;
373c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
374c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int NU = uidStats.size();
375c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int iu = 0; iu < NU; iu++) {
376c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Uid u = uidStats.valueAt(iu);
377c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double p; // in mAs
378c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double power = 0; // in mAs
379c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double highestDrain = 0;
380c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            String packageWithHighestDrain = null;
381c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
382c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
383c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long cpuTime = 0;
384c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long cpuFgTime = 0;
385c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wakelockTime = 0;
386c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long gpsTime = 0;
387c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, "UID " + u.getUid());
388c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (processStats.size() > 0) {
389c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // Process CPU time
390c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
391c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        : processStats.entrySet()) {
392c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Uid.Proc ps = ent.getValue();
393c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long userTime = ps.getUserTime(which);
394c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long systemTime = ps.getSystemTime(which);
395c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long foregroundTime = ps.getForegroundTime(which);
396c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    cpuFgTime += foregroundTime * 10; // convert to millis
397c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
398c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    int totalTimeAtSpeeds = 0;
399c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    // Get the total first
400c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    for (int step = 0; step < speedSteps; step++) {
401c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
402c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        totalTimeAtSpeeds += cpuSpeedStepTimes[step];
403c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
404c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
405c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    // Then compute the ratio of time spent at each speed
406c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    double processPower = 0;
407c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    for (int step = 0; step < speedSteps; step++) {
408c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
409c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        processPower += ratio * tmpCpuTime * powerCpuNormal[step];
410c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
411c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    cpuTime += tmpCpuTime;
412c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (DEBUG && processPower != 0) {
413c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        Log.i(TAG, String.format("process %s, cpu power=%.2f",
414c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                ent.getKey(), processPower / 1000));
415c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
416c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    power += processPower;
417c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (packageWithHighestDrain == null
418c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            || packageWithHighestDrain.startsWith("*")) {
419c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        highestDrain = processPower;
420c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain = ent.getKey();
421c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    } else if (highestDrain < processPower
422c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            && !ent.getKey().startsWith("*")) {
423c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        highestDrain = processPower;
424c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain = ent.getKey();
425c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
426c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
427c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
428c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (cpuFgTime > cpuTime) {
429c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG && cpuFgTime > cpuTime + 10000) {
430c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Log.i(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
431c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
432c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
433c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
434c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power /= 1000;
435c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && power != 0) Log.i(TAG, String.format("total cpu power=%.2f", power));
436c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
437c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Process wake lock usage
438c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
439c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
440c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    : wakelockStats.entrySet()) {
441c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid.Wakelock wakelock = wakelockEntry.getValue();
442c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // Only care about partial wake locks since full wake locks
443c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // are canceled when the user turns the screen off.
444c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
445c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (timer != null) {
446c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    wakelockTime += timer.getTotalTimeLocked(uSecTime, which);
447c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
448c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
449c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            wakelockTime /= 1000; // convert to millis
450c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            appWakelockTime += wakelockTime;
451c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
452c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of holding a wake lock
453c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wakelockTime
454c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
455c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
456c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wakelock power=%.2f", p));
457c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
458c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of mobile traffic
459c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
460c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
461c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (mobileRx + mobileTx) * mobilePowerPerByte;
462c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
463c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("mobile power=%.2f", p));
464c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
465c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of wifi traffic
466c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, mStatsType);
467c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, mStatsType);
468c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiRx + wifiTx) * wifiPowerPerByte;
469c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
470c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi power=%.2f", p));
471c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
472c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of keeping WIFI running.
473c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wifiRunningTimeMs = u.getWifiRunningTime(uSecTime, which) / 1000;
474c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mAppWifiRunning += wifiRunningTimeMs;
475c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiRunningTimeMs
476c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
477c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
478c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi running power=%.2f", p));
479c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
480c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of WIFI scans
481c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wifiScanTimeMs = u.getWifiScanTime(uSecTime, which) / 1000;
482c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiScanTimeMs
483c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / 1000;
484c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
485c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi scanning power=%.2f", p));
486c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
487c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Process Sensor usage
488c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
489c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
490c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    : sensorStats.entrySet()) {
491c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid.Sensor sensor = sensorEntry.getValue();
492c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                int sensorHandle = sensor.getHandle();
493c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatteryStats.Timer timer = sensor.getSensorTime();
494c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
495c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                double multiplier = 0;
496c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                switch (sensorHandle) {
497c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    case Uid.Sensor.GPS:
498c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
499c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        gpsTime = sensorTime;
500c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        break;
501c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    default:
502c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        List<Sensor> sensorList = sensorManager.getSensorList(
503c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                android.hardware.Sensor.TYPE_ALL);
504c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        for (android.hardware.Sensor s : sensorList) {
505c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            if (s.getHandle() == sensorHandle) {
506c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                multiplier = s.getPower();
507c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                break;
508c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            }
509c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        }
510c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
511c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                p = (multiplier * sensorTime) / 1000;
512c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                power += p;
513c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG && p != 0) {
514c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Log.i(TAG, String.format("sensor %s power=%.2f", sensor.toString(), p));
515c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
516c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
517c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
518c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, String.format("UID %d total power=%.2f", u.getUid(), power));
519c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
520c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add the app to the list if it is consuming power
521c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            boolean isOtherUser = false;
522c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final int userId = UserHandle.getUserId(u.getUid());
523c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (power != 0 || u.getUid() == 0) {
524c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatterySipper app = new BatterySipper(mActivity, mRequestQueue, mHandler,
525c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain, DrainType.APP, 0, u,
526c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        new double[] {power});
527c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.cpuTime = cpuTime;
528c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.gpsTime = gpsTime;
529c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiRunningTime = wifiRunningTimeMs;
530c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.cpuFgTime = cpuFgTime;
531c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wakeLockTime = wakelockTime;
532c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.mobileRxBytes = mobileRx;
533c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.mobileTxBytes = mobileTx;
534c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiRxBytes = wifiRx;
535c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiTxBytes = wifiTx;
536c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == Process.WIFI_UID) {
537c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mWifiSippers.add(app);
538c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (u.getUid() == Process.BLUETOOTH_UID) {
539c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mBluetoothSippers.add(app);
540c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (userId != UserHandle.myUserId()
541c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
542c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    isOtherUser = true;
543c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    List<BatterySipper> list = mUserSippers.get(userId);
544c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (list == null) {
545c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        list = new ArrayList<BatterySipper>();
546c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        mUserSippers.put(userId, list);
547c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
548c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    list.add(app);
549c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else {
550c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mUsageList.add(app);
551c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
552c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == 0) {
553c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    osApp = app;
554c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
555c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
556c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (power != 0) {
557c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == Process.WIFI_UID) {
558c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mWifiPower += power;
559c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (u.getUid() == Process.BLUETOOTH_UID) {
560c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mBluetoothPower += power;
561c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (isOtherUser) {
562c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Double userPower = mUserPower.get(userId);
563c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (userPower == null) {
564c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        userPower = power;
565c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    } else {
566c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        userPower += power;
567c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
568c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mUserPower.put(userId, userPower);
569c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else {
570c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (power > mMaxPower) mMaxPower = power;
571c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mTotalPower += power;
572c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
573c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
574c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
575c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
576c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // The device has probably been awake for longer than the screen on
577c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // time and application wake lock time would account for.  Assign
578c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // this remainder to the OS, if possible.
579c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (osApp != null) {
580c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wakeTimeMillis = mStats.computeBatteryUptime(
581c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    SystemClock.uptimeMillis() * 1000, which) / 1000;
582c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            wakeTimeMillis -= appWakelockTime + (mStats.getScreenOnTime(
583c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    SystemClock.elapsedRealtime(), which) / 1000);
584c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (wakeTimeMillis > 0) {
585c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                double power = (wakeTimeMillis
586c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
587c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG) Log.i(TAG, "OS wakeLockTime " + wakeTimeMillis + " power " + power);
588c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.wakeLockTime += wakeTimeMillis;
589c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.value += power;
590c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.values[0] += power;
591c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (osApp.value > mMaxPower) mMaxPower = osApp.value;
592c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                mTotalPower += power;
593c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
594c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
595c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
596c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
597c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addPhoneUsage(long uSecNow) {
598c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
599c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
600c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * phoneOnTimeMs / 1000;
601c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_phone), DrainType.PHONE, phoneOnTimeMs,
602c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_voice_calls, phoneOnPower);
603c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
604c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
605c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addScreenUsage(long uSecNow) {
606c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double power = 0;
607c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
608c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
609c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double screenFullPower =
610c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
611c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
612c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double screenBinPower = screenFullPower * (i + 0.5f)
613c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
614c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
615c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += screenBinPower * brightnessTime;
616c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) {
617c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Log.i(TAG, "Screen bin power = " + (int) screenBinPower + ", time = "
618c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        + brightnessTime);
619c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
620c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
621c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power /= 1000; // To seconds
622c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_screen), DrainType.SCREEN, screenOnTimeMs,
623c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_display, power);
624c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
625c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
626c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addRadioUsage(long uSecNow) {
627c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double power = 0;
628c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int BINS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
629c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long signalTimeMs = 0;
630c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i = 0; i < BINS; i++) {
631c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, uSecNow, mStatsType) / 1000;
632c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += strengthTimeMs / 1000
633c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
634c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            signalTimeMs += strengthTimeMs;
635c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
636c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long scanningTimeMs = mStats.getPhoneSignalScanningTime(uSecNow, mStatsType) / 1000;
637c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power += scanningTimeMs / 1000 * mPowerProfile.getAveragePower(
638c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                PowerProfile.POWER_RADIO_SCANNING);
639c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs =
640c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                addEntry(mActivity.getString(R.string.power_cell), DrainType.CELL,
641c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        signalTimeMs, R.drawable.ic_settings_cell_standby, power);
642c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (signalTimeMs != 0) {
643c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
644c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    / 1000 * 100.0 / signalTimeMs;
645c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
646c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
647c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
648c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void aggregateSippers(BatterySipper bs, List<BatterySipper> from, String tag) {
649c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i=0; i<from.size(); i++) {
650c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            BatterySipper wbs = from.get(i);
651c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
652c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.cpuTime += wbs.cpuTime;
653c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.gpsTime += wbs.gpsTime;
654c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiRunningTime += wbs.wifiRunningTime;
655c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.cpuFgTime += wbs.cpuFgTime;
656c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wakeLockTime += wbs.wakeLockTime;
657c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.mobileRxBytes += wbs.mobileRxBytes;
658c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.mobileTxBytes += wbs.mobileTxBytes;
659c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiRxBytes += wbs.wifiRxBytes;
660c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiTxBytes += wbs.wifiTxBytes;
661c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
662c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
663c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
664c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addWiFiUsage(long uSecNow) {
665c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
666c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long runningTimeMs = mStats.getGlobalWifiRunningTime(uSecNow, mStatsType) / 1000;
667c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) Log.i(TAG, "WIFI runningTime=" + runningTimeMs
668c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                + " app runningTime=" + mAppWifiRunning);
669c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        runningTimeMs -= mAppWifiRunning;
670c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (runningTimeMs < 0) runningTimeMs = 0;
671c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double wifiPower = (onTimeMs * 0 /* TODO */
672c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
673c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
674c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) Log.i(TAG, "WIFI power=" + wifiPower + " from procs=" + mWifiPower);
675c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = addEntry(mActivity.getString(R.string.power_wifi), DrainType.WIFI,
676c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                runningTimeMs, R.drawable.ic_settings_wifi, wifiPower + mWifiPower);
677c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        aggregateSippers(bs, mWifiSippers, "WIFI");
678c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
679c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
680c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addIdleUsage(long uSecNow) {
681c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long idleTimeMs = (uSecNow - mStats.getScreenOnTime(uSecNow, mStatsType)) / 1000;
682c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
683c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 1000;
684c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_idle), DrainType.IDLE, idleTimeMs,
685c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_phone_idle, idlePower);
686c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
687c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
688c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addBluetoothUsage(long uSecNow) {
689c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
690c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
691c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 1000;
692c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        int btPingCount = mStats.getBluetoothPingCount();
693c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        btPower += (btPingCount
694c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
695c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = addEntry(mActivity.getString(R.string.power_bluetooth),
696c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                DrainType.BLUETOOTH, btOnTimeMs, R.drawable.ic_settings_bluetooth,
697c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                btPower + mBluetoothPower);
698c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
699c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
700c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
701c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addUserUsage() {
702c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i=0; i<mUserSippers.size(); i++) {
703c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final int userId = mUserSippers.keyAt(i);
704c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final List<BatterySipper> sippers = mUserSippers.valueAt(i);
705c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            UserInfo info = mUm.getUserInfo(userId);
706c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Drawable icon;
707c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            String name;
708c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (info != null) {
709c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                icon = UserUtils.getUserIcon(mActivity, mUm, info, mActivity.getResources());
710c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = info != null ? info.name : null;
711c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (name == null) {
712c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    name = Integer.toString(info.id);
713c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
714c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = mActivity.getResources().getString(
715c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        R.string.running_process_item_user_label, name);
716c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } else {
717c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                icon = null;
718c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = mActivity.getResources().getString(
719c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        R.string.running_process_item_removed_user_label);
720c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
721c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double power = mUserPower.get(userId);
722c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            BatterySipper bs = addEntry(name, DrainType.USER, 0, 0, power);
723c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.icon = icon;
724c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            aggregateSippers(bs, sippers, "User");
725c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
726c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
727c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
728c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /**
729c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     * Return estimated power (in mAs) of sending a byte with the mobile radio.
730c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     */
731c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double getMobilePowerPerByte() {
732c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
733c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
734c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 3600;
735c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
736c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileRx = mStats.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
737c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileTx = mStats.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
738c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileData = mobileRx + mobileTx;
739c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
740c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
741c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileBps = radioDataUptimeMs != 0
742c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                ? mobileData * 8 * 1000 / radioDataUptimeMs
743c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                : MOBILE_BPS;
744c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
745c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return MOBILE_POWER / (mobileBps / 8);
746c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
747c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
748c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /**
749c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
750c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     */
751c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double getWifiPowerPerByte() {
752c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
753c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
754c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 3600;
755c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return WIFI_POWER / (WIFI_BPS / 8);
756c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
757c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
758c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void processMiscUsage() {
759c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int which = mStatsType;
760c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long uSecTime = SystemClock.elapsedRealtime() * 1000;
761c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long uSecNow = mStats.computeBatteryRealtime(uSecTime, which);
762c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long timeSinceUnplugged = uSecNow;
763c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) {
764c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Log.i(TAG, "Uptime since last unplugged = " + (timeSinceUnplugged / 1000));
765c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
766c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
767c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addUserUsage();
768c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addPhoneUsage(uSecNow);
769c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addScreenUsage(uSecNow);
770c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addWiFiUsage(uSecNow);
771c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addBluetoothUsage(uSecNow);
772c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addIdleUsage(uSecNow); // Not including cellular idle power
773c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Don't compute radio usage if it's a wifi-only device
774c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (!com.android.settings.Utils.isWifiOnly(mActivity)) {
775c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            addRadioUsage(uSecNow);
776c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
777c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
778c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
779c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
780c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double power) {
781c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (power > mMaxPower) mMaxPower = power;
782c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mTotalPower += power;
783c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = new BatterySipper(mActivity, mRequestQueue, mHandler,
784c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                label, drainType, iconId, null, new double[] {power});
785c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        bs.usageTime = time;
786c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        bs.iconId = iconId;
787c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUsageList.add(bs);
788c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return bs;
789c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
790c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
791c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public List<BatterySipper> getUsageList() {
792c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mUsageList;
793c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
794c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
795c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    static final int MSG_UPDATE_NAME_ICON = 1;
796c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    static final int MSG_REPORT_FULLY_DRAWN = 2;
797c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
798c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public double getMaxPower() {
799c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mMaxPower;
800c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
801c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
802c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public double getTotalPower() {
803c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mTotalPower;
804c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
805c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
806c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void load() {
807c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        try {
808c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            byte[] data = mBatteryInfo.getStatistics();
809c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Parcel parcel = Parcel.obtain();
810c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            parcel.unmarshall(data, 0, data.length);
811c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            parcel.setDataPosition(0);
812c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
813c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    .createFromParcel(parcel);
814c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
815c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        } catch (RemoteException e) {
816c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Log.e(TAG, "RemoteException:", e);
817c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
818c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
819c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang}
820