Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1405900 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Switch to BatteryStatsHelper implementation in the framework."

parents df062746 7c80af41
Loading
Loading
Loading
Loading
+305 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -13,58 +13,105 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.settings.fuelgauge;

import com.android.settings.R;
import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
package com.android.settings.fuelgauge;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.BatteryStats.Uid;
import android.os.UserManager;
import com.android.internal.os.BatterySipper;
import com.android.settings.R;
import com.android.settings.users.UserUtils;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Contains information about package name, icon image, power usage about an
 * application or a system service.
 * Wraps the power usage data of a BatterySipper with information about package name
 * and icon image.
 */
public class BatterySipper implements Comparable<BatterySipper> {
    final Context mContext;
    /* Cache cleared when PowerUsageSummary is destroyed */
public class BatteryEntry {
    public static final int MSG_UPDATE_NAME_ICON = 1;
    public static final int MSG_REPORT_FULLY_DRAWN = 2;

    static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
    final ArrayList<BatterySipper> mRequestQueue;
    final Handler mHandler;
    String name;
    Drawable icon;
    int iconId; // For passing to the detail screen.
    Uid uidObj;
    double value;
    double[] values;
    DrainType drainType;
    long usageTime;
    long cpuTime;
    long gpsTime;
    long wifiRunningTime;
    long cpuFgTime;
    long wakeLockTime;
    long mobileRxPackets;
    long mobileTxPackets;
    long wifiRxPackets;
    long wifiTxPackets;
    long mobileRxBytes;
    long mobileTxBytes;
    long wifiRxBytes;
    long wifiTxBytes;
    double percent;
    double noCoveragePercent;
    String defaultPackageName;
    String[] mPackages;

    static final ArrayList<BatteryEntry> mRequestQueue = new ArrayList<BatteryEntry>();
    static Handler mHandler;

    static private class NameAndIconLoader extends Thread {
        private boolean mAbort = false;

        public NameAndIconLoader() {
            super("BatteryUsage Icon Loader");
        }

        public void abort() {
            mAbort = true;
        }

        @Override
        public void run() {
            while (true) {
                BatteryEntry be;
                synchronized (mRequestQueue) {
                    if (mRequestQueue.isEmpty() || mAbort) {
                        mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
                        mRequestQueue.clear();
                        return;
                    }
                    be = mRequestQueue.remove(0);
                }
                be.loadNameAndIcon();
            }
        }
    }

    private static NameAndIconLoader mRequestThread;

    public static void startRequestQueue() {
        if (mHandler != null) {
            synchronized (mRequestQueue) {
                if (!mRequestQueue.isEmpty()) {
                    if (mRequestThread != null) {
                        mRequestThread.abort();
                    }
                    mRequestThread = new NameAndIconLoader();
                    mRequestThread.setPriority(Thread.MIN_PRIORITY);
                    mRequestThread.start();
                    mRequestQueue.notify();
                }
            }
        }
    }

    public static void stopRequestQueue() {
        synchronized (mRequestQueue) {
            if (mRequestThread != null) {
                mRequestThread.abort();
                mRequestThread = null;
                mHandler = null;
            }
        }
    }

    public static void clearUidCache() {
        sUidCache.clear();
    }

    public final Context context;
    public final BatterySipper sipper;

    public String name;
    public Drawable icon;
    public int iconId; // For passing to the detail screen.
    public String defaultPackageName;

    static class UidToDetail {
        String name;
@@ -72,31 +119,69 @@ public class BatterySipper implements Comparable<BatterySipper> {
        Drawable icon;
    }

    BatterySipper(Context context, ArrayList<BatterySipper> requestQueue,
            Handler handler, String label, DrainType drainType,
            int iconId, Uid uid, double[] values) {
        mContext = context;
        mRequestQueue = requestQueue;
    public BatteryEntry(Context context, Handler handler, UserManager um, BatterySipper sipper) {
        mHandler = handler;
        this.values = values;
        name = label;
        this.drainType = drainType;
        if (iconId > 0) {
            icon = mContext.getResources().getDrawable(iconId);
        this.context = context;
        this.sipper = sipper;
        switch (sipper.drainType) {
            case IDLE:
                name = context.getResources().getString(R.string.power_idle);
                iconId = R.drawable.ic_settings_phone_idle;
                break;
            case CELL:
                name = context.getResources().getString(R.string.power_cell);
                iconId = R.drawable.ic_settings_cell_standby;
                break;
            case PHONE:
                name = context.getResources().getString(R.string.power_phone);
                iconId = R.drawable.ic_settings_voice_calls;
                break;
            case WIFI:
                name = context.getResources().getString(R.string.power_wifi);
                iconId = R.drawable.ic_settings_wifi;
                break;
            case BLUETOOTH:
                name = context.getResources().getString(R.string.power_bluetooth);
                iconId = R.drawable.ic_settings_bluetooth;
                break;
            case SCREEN:
                name = context.getResources().getString(R.string.power_screen);
                iconId = R.drawable.ic_settings_display;
                break;
            case APP:
                name = sipper.packageWithHighestDrain;
                break;
            case USER: {
                UserInfo info = um.getUserInfo(sipper.userId);
                if (info != null) {
                    icon = UserUtils.getUserIcon(context, um, info, context.getResources());
                    name = info != null ? info.name : null;
                    if (name == null) {
                        name = Integer.toString(info.id);
                    }
                    name = context.getResources().getString(
                            R.string.running_process_item_user_label, name);
                } else {
                    icon = null;
                    name = context.getResources().getString(
                            R.string.running_process_item_removed_user_label);
                }
        if (values != null) value = values[0];
        if ((label == null || iconId == 0) && uid != null) {
            getQuickNameIconForUid(uid);
            } break;
            case UNACCOUNTED:
                name = context.getResources().getString(R.string.power_unaccounted);
                iconId = R.drawable.ic_power_system;
                break;
            case OVERCOUNTED:
                name = context.getResources().getString(R.string.power_overcounted);
                iconId = R.drawable.ic_power_system;
                break;
        }
        uidObj = uid;
        if (iconId > 0) {
            icon = context.getResources().getDrawable(iconId);
        }

    double getSortValue() {
        return value;
        if ((name == null || iconId == 0) && this.sipper.uidObj != null) {
            getQuickNameIconForUid(this.sipper.uidObj);
        }

    double[] getValues() {
        return values;
    }

    public Drawable getIcon() {
@@ -110,28 +195,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
        return name;
    }

    @Override
    public int compareTo(BatterySipper other) {
        // Return the flipped value because we want the items in descending order
        return Double.compare(other.getSortValue(), getSortValue());
    }

    /**
     * Gets a list of packages associated with the current user
     */
    public String[] getPackages() {
        return mPackages;
    }

    public int getUid() {
        // Bail out if the current sipper is not an App sipper.
        if (uidObj == null) {
            return 0;
        }
        return uidObj.getUid();
    }

    void getQuickNameIconForUid(Uid uidObj) {
    void getQuickNameIconForUid(BatteryStats.Uid uidObj) {
        final int uid = uidObj.getUid();
        final String uidString = Integer.toString(uid);
        if (sUidCache.containsKey(uidString)) {
@@ -141,18 +205,18 @@ public class BatterySipper implements Comparable<BatterySipper> {
            icon = utd.icon;
            return;
        }
        PackageManager pm = mContext.getPackageManager();
        PackageManager pm = context.getPackageManager();
        String[] packages = pm.getPackagesForUid(uid);
        icon = pm.getDefaultActivityIcon();
        if (packages == null) {
            //name = Integer.toString(uid);
            if (uid == 0) {
                name = mContext.getResources().getString(R.string.process_kernel_label);
                name = context.getResources().getString(R.string.process_kernel_label);
            } else if ("mediaserver".equals(name)) {
                name = mContext.getResources().getString(R.string.process_mediaserver_label);
                name = context.getResources().getString(R.string.process_mediaserver_label);
            }
            iconId = R.drawable.ic_power_system;
            icon = mContext.getResources().getDrawable(iconId);
            icon = context.getResources().getDrawable(iconId);
            return;
        } else {
            //name = packages[0];
@@ -164,29 +228,25 @@ public class BatterySipper implements Comparable<BatterySipper> {
        }
    }

    public static void clearUidCache() {
        sUidCache.clear();
    }

    /**
     * Loads the app label and icon image and stores into the cache.
     */
    public void loadNameAndIcon() {
        // Bail out if the current sipper is not an App sipper.
        if (uidObj == null) {
        if (sipper.uidObj == null) {
            return;
        }
        PackageManager pm = mContext.getPackageManager();
        final int uid = uidObj.getUid();
        PackageManager pm = context.getPackageManager();
        final int uid = sipper.uidObj.getUid();
        final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
        mPackages = pm.getPackagesForUid(uid);
        if (mPackages == null) {
        sipper.mPackages = pm.getPackagesForUid(uid);
        if (sipper.mPackages == null) {
            name = Integer.toString(uid);
            return;
        }

        String[] packageLabels = new String[mPackages.length];
        System.arraycopy(mPackages, 0, packageLabels, 0, mPackages.length);
        String[] packageLabels = new String[sipper.mPackages.length];
        System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);

        int preferredIndex = -1;
        // Convert package names to user-facing labels where possible
@@ -200,11 +260,11 @@ public class BatterySipper implements Comparable<BatterySipper> {
                    packageLabels[i] = label.toString();
                }
                if (ai.icon != 0) {
                    defaultPackageName = mPackages[i];
                    defaultPackageName = sipper.mPackages[i];
                    icon = ai.loadIcon(pm);
                    break;
                }
            } catch (NameNotFoundException e) {
            } catch (PackageManager.NameNotFoundException e) {
            }
        }
        if (icon == null) icon = defaultActivityIcon;
@@ -213,7 +273,7 @@ public class BatterySipper implements Comparable<BatterySipper> {
            name = packageLabels[0];
        } else {
            // Look for an official name for this UID.
            for (String pkgName : mPackages) {
            for (String pkgName : sipper.mPackages) {
                try {
                    final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
                    if (pi.sharedUserLabel != 0) {
@@ -232,15 +292,14 @@ public class BatterySipper implements Comparable<BatterySipper> {
                }
            }
        }
        final String uidString = Integer.toString(uidObj.getUid());
        final String uidString = Integer.toString(sipper.uidObj.getUid());
        UidToDetail utd = new UidToDetail();
        utd.name = name;
        utd.icon = icon;
        utd.packageName = defaultPackageName;
        sUidCache.put(uidString, utd);
        if (mHandler != null) {
            mHandler.sendMessage(
                    mHandler.obtainMessage(BatteryStatsHelper.MSG_UPDATE_NAME_ICON, this));
            mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
        }
    }
}
Loading