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
178bfa96c3b10f53a969406755eed36ba98fc1de549Lifu Tang    public void startBatteryDetailPage(
179bfa96c3b10f53a969406755eed36ba98fc1de549Lifu Tang            PreferenceActivity caller, BatterySipper sipper, boolean showLocationButton) {
180c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Initialize mStats if necessary.
181c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        getStats();
182c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
183c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        Bundle args = new Bundle();
184c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putString(PowerUsageDetail.EXTRA_TITLE, sipper.name);
185c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
186c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
187c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
188c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
189c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, mStatsPeriod);
190c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
191c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putInt(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
192c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
193c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (sipper.uidObj != null) {
194c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            args.putInt(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
195c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
196c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
197bfa96c3b10f53a969406755eed36ba98fc1de549Lifu Tang        args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
198c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
199c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        int[] types;
200c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double[] values;
201c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        switch (sipper.drainType) {
202c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case APP:
203c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case USER:
204c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
205c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid uid = sipper.uidObj;
206c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
207c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
208c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
209c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
210c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_gps,
211c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wifi_running,
212c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
213c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
214c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
215c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
216c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_audio,
217c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_video,
218c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
219c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
220c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
221c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
222c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
223c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.gpsTime,
224c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRunningTime,
225c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
226c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
227c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
228c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
229c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    0,
230c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    0
231c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
232c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
233c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (sipper.drainType == DrainType.APP) {
234c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Writer result = new StringWriter();
235c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
236c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mStats.dumpLocked(printWriter, "", mStatsType, uid.getUid());
237c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter.flush();
238c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
239c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
240c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    result = new StringWriter();
241c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter = new FastPrintWriter(result, false, 1024);
242c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mStats.dumpCheckinLocked(printWriter, mStatsType, uid.getUid());
243c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    printWriter.flush();
244c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
245c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            result.toString());
246c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
247c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
248c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            break;
249c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case CELL:
250c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
251c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
252c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time,
253c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_no_coverage
254c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
255c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
256c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
257c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.noCoveragePercent
258c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
259c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
260c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            break;
261c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case WIFI:
262c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
263c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
264c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wifi_running,
265c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
266c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
267c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
268c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
269c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
270c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
271c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
272c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
273c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
274c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
275c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
276c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
277c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
278c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
279c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
280c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
281c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
282c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
283c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } break;
284c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            case BLUETOOTH:
285c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
286c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
287c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time,
288c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu,
289c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_cpu_foreground,
290c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_wake_lock,
291c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_recv,
292c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_send,
293c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_recv,
294c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_data_wifi_send,
295c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
296c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
297c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime,
298c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuTime,
299c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.cpuFgTime,
300c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wakeLockTime,
301c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileRxBytes,
302c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.mobileTxBytes,
303c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiRxBytes,
304c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.wifiTxBytes,
305c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
306c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } break;
307c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            default:
308c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            {
309c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                types = new int[] {
310c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    R.string.usage_type_on_time
311c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
312c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                values = new double[] {
313c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    sipper.usageTime
314c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                };
315c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
316c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
317c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
318c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
319c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
320c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.string.details_title, null, null, 0);
321c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
322c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
323ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang    /**
324ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang     * Refreshes the power usage list.
325ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang     * @param includeZeroConsumption whether includes those applications which have consumed very
326ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang     *                               little power up till now.
327ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang     */
328ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang    public void refreshStats(boolean includeZeroConsumption) {
329c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Initialize mStats if necessary.
330c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        getStats();
331c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
332c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mMaxPower = 0;
333c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mTotalPower = 0;
334c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mWifiPower = 0;
335c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mBluetoothPower = 0;
336c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mAppWifiRunning = 0;
337c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
338c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUsageList.clear();
339c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mWifiSippers.clear();
340c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mBluetoothSippers.clear();
341c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUserSippers.clear();
342c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUserPower.clear();
343c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
344ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang        processAppUsage(includeZeroConsumption);
345c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        processMiscUsage();
346c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
347c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        Collections.sort(mUsageList);
348c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
349c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (mHandler != null) {
350c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            synchronized (mRequestQueue) {
351c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (!mRequestQueue.isEmpty()) {
352c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (mRequestThread != null) {
353c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        mRequestThread.abort();
354c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
355c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread = new NameAndIconLoader();
356c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread.setPriority(Thread.MIN_PRIORITY);
357c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestThread.start();
358c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mRequestQueue.notify();
359c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
360c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
361c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
362c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
363c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
364ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang    private void processAppUsage(boolean includeZeroConsumption) {
365c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        SensorManager sensorManager = (SensorManager) mActivity.getSystemService(
366c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Context.SENSOR_SERVICE);
367c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int which = mStatsType;
368c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int speedSteps = mPowerProfile.getNumSpeedSteps();
369c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double[] powerCpuNormal = new double[speedSteps];
370c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long[] cpuSpeedStepTimes = new long[speedSteps];
371c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int p = 0; p < speedSteps; p++) {
372c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
373c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
374c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double mobilePowerPerByte = getMobilePowerPerByte();
375c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double wifiPowerPerByte = getWifiPowerPerByte();
376c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
377c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long appWakelockTime = 0;
378c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper osApp = null;
379c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mStatsPeriod = uSecTime;
380c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        SparseArray<? extends Uid> uidStats = mStats.getUidStats();
381c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int NU = uidStats.size();
382c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int iu = 0; iu < NU; iu++) {
383c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Uid u = uidStats.valueAt(iu);
384c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double p; // in mAs
385c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double power = 0; // in mAs
386c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double highestDrain = 0;
387c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            String packageWithHighestDrain = null;
388c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
389c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
390c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long cpuTime = 0;
391c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long cpuFgTime = 0;
392c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wakelockTime = 0;
393c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long gpsTime = 0;
394c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, "UID " + u.getUid());
395c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (processStats.size() > 0) {
396c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // Process CPU time
397c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
398c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        : processStats.entrySet()) {
399c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Uid.Proc ps = ent.getValue();
400c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long userTime = ps.getUserTime(which);
401c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long systemTime = ps.getSystemTime(which);
402c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long foregroundTime = ps.getForegroundTime(which);
403c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    cpuFgTime += foregroundTime * 10; // convert to millis
404c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
405c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    int totalTimeAtSpeeds = 0;
406c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    // Get the total first
407c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    for (int step = 0; step < speedSteps; step++) {
408c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
409c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        totalTimeAtSpeeds += cpuSpeedStepTimes[step];
410c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
411c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
412c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    // Then compute the ratio of time spent at each speed
413c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    double processPower = 0;
414c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    for (int step = 0; step < speedSteps; step++) {
415c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
416c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        processPower += ratio * tmpCpuTime * powerCpuNormal[step];
417c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
418c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    cpuTime += tmpCpuTime;
419c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (DEBUG && processPower != 0) {
420c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        Log.i(TAG, String.format("process %s, cpu power=%.2f",
421c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                ent.getKey(), processPower / 1000));
422c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
423c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    power += processPower;
424c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (packageWithHighestDrain == null
425c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            || packageWithHighestDrain.startsWith("*")) {
426c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        highestDrain = processPower;
427c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain = ent.getKey();
428c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    } else if (highestDrain < processPower
429c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            && !ent.getKey().startsWith("*")) {
430c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        highestDrain = processPower;
431c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain = ent.getKey();
432c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
433c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
434c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
435c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (cpuFgTime > cpuTime) {
436c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG && cpuFgTime > cpuTime + 10000) {
437c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Log.i(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
438c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
439c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
440c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
441c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power /= 1000;
442c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && power != 0) Log.i(TAG, String.format("total cpu power=%.2f", power));
443c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
444c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Process wake lock usage
445c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
446c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
447c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    : wakelockStats.entrySet()) {
448c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid.Wakelock wakelock = wakelockEntry.getValue();
449c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // Only care about partial wake locks since full wake locks
450c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                // are canceled when the user turns the screen off.
451c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
452c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (timer != null) {
453c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    wakelockTime += timer.getTotalTimeLocked(uSecTime, which);
454c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
455c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
456c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            wakelockTime /= 1000; // convert to millis
457c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            appWakelockTime += wakelockTime;
458c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
459c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of holding a wake lock
460c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wakelockTime
461c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
462c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
463c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wakelock power=%.2f", p));
464c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
465c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of mobile traffic
466c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
467c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
468c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (mobileRx + mobileTx) * mobilePowerPerByte;
469c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
470c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("mobile power=%.2f", p));
471c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
472c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of wifi traffic
473c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, mStatsType);
474c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, mStatsType);
475c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiRx + wifiTx) * wifiPowerPerByte;
476c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
477c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi power=%.2f", p));
478c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
479c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of keeping WIFI running.
480c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wifiRunningTimeMs = u.getWifiRunningTime(uSecTime, which) / 1000;
481c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mAppWifiRunning += wifiRunningTimeMs;
482c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiRunningTimeMs
483c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
484c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
485c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi running power=%.2f", p));
486c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
487c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add cost of WIFI scans
488c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wifiScanTimeMs = u.getWifiScanTime(uSecTime, which) / 1000;
489c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            p = (wifiScanTimeMs
490c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / 1000;
491c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += p;
492c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG && p != 0) Log.i(TAG, String.format("wifi scanning power=%.2f", p));
49321a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt            for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
49421a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                long batchScanTimeMs = u.getWifiBatchedScanTime(bin, uSecTime, which) / 1000;
49521a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                p = (batchScanTimeMs
49621a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                        * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin));
49721a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                power += p;
49821a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                if (DEBUG && p != 0) {
49921a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                    Log.i(TAG, String.format("wifi batched scanning lvl %d = %.2f", bin, p));
50021a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt                }
50121a2eb5aeae57985356f60db476234fa4cf1a6fbRobert Greenwalt            }
502c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
503c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Process Sensor usage
504c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
505c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
506c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    : sensorStats.entrySet()) {
507c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Uid.Sensor sensor = sensorEntry.getValue();
508c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                int sensorHandle = sensor.getHandle();
509c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatteryStats.Timer timer = sensor.getSensorTime();
510c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
511c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                double multiplier = 0;
512c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                switch (sensorHandle) {
513c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    case Uid.Sensor.GPS:
514c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
515c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        gpsTime = sensorTime;
516c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        break;
517c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    default:
518c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        List<Sensor> sensorList = sensorManager.getSensorList(
519c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                android.hardware.Sensor.TYPE_ALL);
520c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        for (android.hardware.Sensor s : sensorList) {
521c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            if (s.getHandle() == sensorHandle) {
522c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                multiplier = s.getPower();
523c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                                break;
524c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                            }
525c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        }
526c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
527c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                p = (multiplier * sensorTime) / 1000;
528c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                power += p;
529c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG && p != 0) {
530c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Log.i(TAG, String.format("sensor %s power=%.2f", sensor.toString(), p));
531c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
532c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
533c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
534c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, String.format("UID %d total power=%.2f", u.getUid(), power));
535c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
536c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            // Add the app to the list if it is consuming power
537c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            boolean isOtherUser = false;
538c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final int userId = UserHandle.getUserId(u.getUid());
539ad7bfbd3469b0dfd42c6bc9d25b22c29d52fbdadLifu Tang            if (power != 0 || includeZeroConsumption || u.getUid() == 0) {
540c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                BatterySipper app = new BatterySipper(mActivity, mRequestQueue, mHandler,
541c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        packageWithHighestDrain, DrainType.APP, 0, u,
542c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        new double[] {power});
543c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.cpuTime = cpuTime;
544c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.gpsTime = gpsTime;
545c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiRunningTime = wifiRunningTimeMs;
546c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.cpuFgTime = cpuFgTime;
547c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wakeLockTime = wakelockTime;
548c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.mobileRxBytes = mobileRx;
549c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.mobileTxBytes = mobileTx;
550c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiRxBytes = wifiRx;
551c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                app.wifiTxBytes = wifiTx;
552c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == Process.WIFI_UID) {
553c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mWifiSippers.add(app);
554c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (u.getUid() == Process.BLUETOOTH_UID) {
555c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mBluetoothSippers.add(app);
556c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (userId != UserHandle.myUserId()
557c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
558c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    isOtherUser = true;
559c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    List<BatterySipper> list = mUserSippers.get(userId);
560c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (list == null) {
561c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        list = new ArrayList<BatterySipper>();
562c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        mUserSippers.put(userId, list);
563c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
564c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    list.add(app);
565c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else {
566c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mUsageList.add(app);
567c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
568c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == 0) {
569c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    osApp = app;
570c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
571c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
5726cc61f17a1b239217225347d52fbef43fc72066cLifu Tang            if (power != 0 || includeZeroConsumption) {
573c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (u.getUid() == Process.WIFI_UID) {
574c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mWifiPower += power;
575c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (u.getUid() == Process.BLUETOOTH_UID) {
576c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mBluetoothPower += power;
577c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else if (isOtherUser) {
578c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    Double userPower = mUserPower.get(userId);
579c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (userPower == null) {
580c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        userPower = power;
581c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    } else {
582c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        userPower += power;
583c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    }
584c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mUserPower.put(userId, userPower);
585c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                } else {
586c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    if (power > mMaxPower) mMaxPower = power;
587c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    mTotalPower += power;
588c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
589c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
590c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
591c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
592c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // The device has probably been awake for longer than the screen on
593c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // time and application wake lock time would account for.  Assign
594c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // this remainder to the OS, if possible.
595c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (osApp != null) {
596c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long wakeTimeMillis = mStats.computeBatteryUptime(
597c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    SystemClock.uptimeMillis() * 1000, which) / 1000;
598c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            wakeTimeMillis -= appWakelockTime + (mStats.getScreenOnTime(
599c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    SystemClock.elapsedRealtime(), which) / 1000);
600c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (wakeTimeMillis > 0) {
601c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                double power = (wakeTimeMillis
602c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
603c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (DEBUG) Log.i(TAG, "OS wakeLockTime " + wakeTimeMillis + " power " + power);
604c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.wakeLockTime += wakeTimeMillis;
605c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.value += power;
606c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                osApp.values[0] += power;
607c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (osApp.value > mMaxPower) mMaxPower = osApp.value;
608c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                mTotalPower += power;
609c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
610c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
611c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
612c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
613c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addPhoneUsage(long uSecNow) {
614c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
615c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
616c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * phoneOnTimeMs / 1000;
617c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_phone), DrainType.PHONE, phoneOnTimeMs,
618c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_voice_calls, phoneOnPower);
619c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
620c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
621c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addScreenUsage(long uSecNow) {
622c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double power = 0;
623c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
624c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
625c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double screenFullPower =
626c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
627c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
628c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double screenBinPower = screenFullPower * (i + 0.5f)
629c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
630c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
631c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += screenBinPower * brightnessTime;
632c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) {
633c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                Log.i(TAG, "Screen bin power = " + (int) screenBinPower + ", time = "
634c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        + brightnessTime);
635c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
636c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
637c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power /= 1000; // To seconds
638c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_screen), DrainType.SCREEN, screenOnTimeMs,
639c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_display, power);
640c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
641c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
642c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addRadioUsage(long uSecNow) {
643c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double power = 0;
644c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int BINS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
645c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long signalTimeMs = 0;
646c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i = 0; i < BINS; i++) {
647c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, uSecNow, mStatsType) / 1000;
648c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            power += strengthTimeMs / 1000
649c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
650c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            signalTimeMs += strengthTimeMs;
651c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
652c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long scanningTimeMs = mStats.getPhoneSignalScanningTime(uSecNow, mStatsType) / 1000;
653c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        power += scanningTimeMs / 1000 * mPowerProfile.getAveragePower(
654c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                PowerProfile.POWER_RADIO_SCANNING);
655c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs =
656c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                addEntry(mActivity.getString(R.string.power_cell), DrainType.CELL,
657c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        signalTimeMs, R.drawable.ic_settings_cell_standby, power);
658c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (signalTimeMs != 0) {
659c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
660c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    / 1000 * 100.0 / signalTimeMs;
661c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
662c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
663c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
664c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void aggregateSippers(BatterySipper bs, List<BatterySipper> from, String tag) {
665c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i=0; i<from.size(); i++) {
666c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            BatterySipper wbs = from.get(i);
667c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (DEBUG) Log.i(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
668c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.cpuTime += wbs.cpuTime;
669c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.gpsTime += wbs.gpsTime;
670c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiRunningTime += wbs.wifiRunningTime;
671c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.cpuFgTime += wbs.cpuFgTime;
672c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wakeLockTime += wbs.wakeLockTime;
673c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.mobileRxBytes += wbs.mobileRxBytes;
674c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.mobileTxBytes += wbs.mobileTxBytes;
675c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiRxBytes += wbs.wifiRxBytes;
676c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.wifiTxBytes += wbs.wifiTxBytes;
677c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
678c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
679c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
680c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addWiFiUsage(long uSecNow) {
681c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
682c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long runningTimeMs = mStats.getGlobalWifiRunningTime(uSecNow, mStatsType) / 1000;
683c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) Log.i(TAG, "WIFI runningTime=" + runningTimeMs
684c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                + " app runningTime=" + mAppWifiRunning);
685c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        runningTimeMs -= mAppWifiRunning;
686c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (runningTimeMs < 0) runningTimeMs = 0;
687c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double wifiPower = (onTimeMs * 0 /* TODO */
688c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
689c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
690c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) Log.i(TAG, "WIFI power=" + wifiPower + " from procs=" + mWifiPower);
691c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = addEntry(mActivity.getString(R.string.power_wifi), DrainType.WIFI,
692c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                runningTimeMs, R.drawable.ic_settings_wifi, wifiPower + mWifiPower);
693c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        aggregateSippers(bs, mWifiSippers, "WIFI");
694c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
695c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
696c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addIdleUsage(long uSecNow) {
697c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long idleTimeMs = (uSecNow - mStats.getScreenOnTime(uSecNow, mStatsType)) / 1000;
698c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
699c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 1000;
700c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addEntry(mActivity.getString(R.string.power_idle), DrainType.IDLE, idleTimeMs,
701c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                R.drawable.ic_settings_phone_idle, idlePower);
702c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
703c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
704c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addBluetoothUsage(long uSecNow) {
705c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
706c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
707c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 1000;
708c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        int btPingCount = mStats.getBluetoothPingCount();
709c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        btPower += (btPingCount
710c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
711c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = addEntry(mActivity.getString(R.string.power_bluetooth),
712c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                DrainType.BLUETOOTH, btOnTimeMs, R.drawable.ic_settings_bluetooth,
713c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                btPower + mBluetoothPower);
714c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
715c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
716c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
717c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void addUserUsage() {
718c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        for (int i=0; i<mUserSippers.size(); i++) {
719c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final int userId = mUserSippers.keyAt(i);
720c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            final List<BatterySipper> sippers = mUserSippers.valueAt(i);
721c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            UserInfo info = mUm.getUserInfo(userId);
722c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Drawable icon;
723c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            String name;
724c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            if (info != null) {
725c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                icon = UserUtils.getUserIcon(mActivity, mUm, info, mActivity.getResources());
726c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = info != null ? info.name : null;
727c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                if (name == null) {
728c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    name = Integer.toString(info.id);
729c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                }
730c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = mActivity.getResources().getString(
731c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        R.string.running_process_item_user_label, name);
732c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            } else {
733c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                icon = null;
734c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                name = mActivity.getResources().getString(
735c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                        R.string.running_process_item_removed_user_label);
736c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            }
7376cc61f17a1b239217225347d52fbef43fc72066cLifu Tang            Double userPower = mUserPower.get(userId);
7386cc61f17a1b239217225347d52fbef43fc72066cLifu Tang            double power = (userPower != null) ? userPower : 0.0;
739c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            BatterySipper bs = addEntry(name, DrainType.USER, 0, 0, power);
740c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            bs.icon = icon;
741c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            aggregateSippers(bs, sippers, "User");
742c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
743c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
744c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
745c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /**
746c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     * Return estimated power (in mAs) of sending a byte with the mobile radio.
747c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     */
748c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double getMobilePowerPerByte() {
749c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
750c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
751c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 3600;
752c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
753c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileRx = mStats.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
754c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileTx = mStats.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
755c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileData = mobileRx + mobileTx;
756c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
757c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
758c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long mobileBps = radioDataUptimeMs != 0
759c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                ? mobileData * 8 * 1000 / radioDataUptimeMs
760c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                : MOBILE_BPS;
761c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
762c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return MOBILE_POWER / (mobileBps / 8);
763c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
764c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
765c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    /**
766c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
767c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang     */
768c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private double getWifiPowerPerByte() {
769c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
770c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
771c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                / 3600;
772c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return WIFI_POWER / (WIFI_BPS / 8);
773c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
774c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
775c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void processMiscUsage() {
776c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final int which = mStatsType;
777c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        long uSecTime = SystemClock.elapsedRealtime() * 1000;
778c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long uSecNow = mStats.computeBatteryRealtime(uSecTime, which);
779c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        final long timeSinceUnplugged = uSecNow;
780c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (DEBUG) {
781c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Log.i(TAG, "Uptime since last unplugged = " + (timeSinceUnplugged / 1000));
782c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
783c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
784c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addUserUsage();
785c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addPhoneUsage(uSecNow);
786c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addScreenUsage(uSecNow);
787c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addWiFiUsage(uSecNow);
788c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addBluetoothUsage(uSecNow);
789c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        addIdleUsage(uSecNow); // Not including cellular idle power
790c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        // Don't compute radio usage if it's a wifi-only device
791c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (!com.android.settings.Utils.isWifiOnly(mActivity)) {
792c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            addRadioUsage(uSecNow);
793c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
794c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
795c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
796c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
797c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            double power) {
798c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        if (power > mMaxPower) mMaxPower = power;
799c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mTotalPower += power;
800c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        BatterySipper bs = new BatterySipper(mActivity, mRequestQueue, mHandler,
801c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                label, drainType, iconId, null, new double[] {power});
802c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        bs.usageTime = time;
803c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        bs.iconId = iconId;
804c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        mUsageList.add(bs);
805c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return bs;
806c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
807c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
808c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public List<BatterySipper> getUsageList() {
809c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mUsageList;
810c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
811c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
812c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    static final int MSG_UPDATE_NAME_ICON = 1;
813c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    static final int MSG_REPORT_FULLY_DRAWN = 2;
814c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
815c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public double getMaxPower() {
816c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mMaxPower;
817c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
818c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
819c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    public double getTotalPower() {
820c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        return mTotalPower;
821c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
822c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang
823c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    private void load() {
824c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        try {
825c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            byte[] data = mBatteryInfo.getStatistics();
826c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Parcel parcel = Parcel.obtain();
827c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            parcel.unmarshall(data, 0, data.length);
828c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            parcel.setDataPosition(0);
829c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
830c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang                    .createFromParcel(parcel);
831c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
832c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        } catch (RemoteException e) {
833c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang            Log.e(TAG, "RemoteException:", e);
834c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang        }
835c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang    }
836c3e9ac937a4ba948d47cbb83f6999af34fd00b65Lifu Tang}
837