Home | History | Annotate | Download | only in appinfo
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.applications.appinfo;
     18 
     19 import android.app.LoaderManager;
     20 import android.content.Context;
     21 import android.content.Loader;
     22 import android.content.pm.PackageInfo;
     23 import android.os.BatteryStats;
     24 import android.os.Bundle;
     25 import android.os.UserManager;
     26 import android.support.annotation.VisibleForTesting;
     27 import android.support.v7.preference.Preference;
     28 import android.support.v7.preference.PreferenceScreen;
     29 
     30 import com.android.internal.os.BatterySipper;
     31 import com.android.internal.os.BatteryStatsHelper;
     32 import com.android.settings.R;
     33 import com.android.settings.SettingsActivity;
     34 import com.android.settings.Utils;
     35 import com.android.settings.core.BasePreferenceController;
     36 import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
     37 import com.android.settings.fuelgauge.BatteryEntry;
     38 import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
     39 import com.android.settings.fuelgauge.BatteryUtils;
     40 import com.android.settingslib.core.lifecycle.Lifecycle;
     41 import com.android.settingslib.core.lifecycle.LifecycleObserver;
     42 import com.android.settingslib.core.lifecycle.events.OnPause;
     43 import com.android.settingslib.core.lifecycle.events.OnResume;
     44 
     45 import java.util.ArrayList;
     46 import java.util.List;
     47 
     48 public class AppBatteryPreferenceController extends BasePreferenceController
     49         implements LoaderManager.LoaderCallbacks<BatteryStatsHelper>,
     50         LifecycleObserver, OnResume, OnPause {
     51 
     52     private static final String KEY_BATTERY = "battery";
     53 
     54     @VisibleForTesting
     55     BatterySipper mSipper;
     56     @VisibleForTesting
     57     BatteryStatsHelper mBatteryHelper;
     58     @VisibleForTesting
     59     BatteryUtils mBatteryUtils;
     60 
     61     private Preference mPreference;
     62     private final AppInfoDashboardFragment mParent;
     63     private String mBatteryPercent;
     64     private final String mPackageName;
     65 
     66     public AppBatteryPreferenceController(Context context, AppInfoDashboardFragment parent,
     67             String packageName, Lifecycle lifecycle) {
     68         super(context, KEY_BATTERY);
     69         mParent = parent;
     70         mBatteryUtils = BatteryUtils.getInstance(mContext);
     71         mPackageName = packageName;
     72         if (lifecycle != null) {
     73             lifecycle.addObserver(this);
     74         }
     75     }
     76 
     77     @Override
     78     public int getAvailabilityStatus() {
     79         return mContext.getResources().getBoolean(R.bool.config_show_app_info_settings_battery)
     80                 ? AVAILABLE
     81                 : CONDITIONALLY_UNAVAILABLE;
     82     }
     83 
     84     @Override
     85     public void displayPreference(PreferenceScreen screen) {
     86         super.displayPreference(screen);
     87         mPreference = screen.findPreference(getPreferenceKey());
     88         mPreference.setEnabled(false);
     89     }
     90 
     91     @Override
     92     public boolean handlePreferenceTreeClick(Preference preference) {
     93         if (!KEY_BATTERY.equals(preference.getKey())) {
     94             return false;
     95         }
     96         if (isBatteryStatsAvailable()) {
     97             final UserManager userManager =
     98                     (UserManager) mContext.getSystemService(Context.USER_SERVICE);
     99             final BatteryEntry entry = new BatteryEntry(mContext, null, userManager, mSipper);
    100             entry.defaultPackageName = mPackageName;
    101             AdvancedPowerUsageDetail.startBatteryDetailPage(
    102                     (SettingsActivity) mParent.getActivity(), mParent, mBatteryHelper,
    103                     BatteryStats.STATS_SINCE_CHARGED, entry, mBatteryPercent,
    104                     null /* mAnomalies */);
    105         } else {
    106             AdvancedPowerUsageDetail.startBatteryDetailPage(
    107                     (SettingsActivity) mParent.getActivity(), mParent, mPackageName);
    108         }
    109         return true;
    110     }
    111 
    112     @Override
    113     public void onResume() {
    114         mParent.getLoaderManager().restartLoader(
    115                 mParent.LOADER_BATTERY, Bundle.EMPTY, this);
    116     }
    117 
    118     @Override
    119     public void onPause() {
    120         mParent.getLoaderManager().destroyLoader(mParent.LOADER_BATTERY);
    121     }
    122 
    123     @Override
    124     public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) {
    125         return new BatteryStatsHelperLoader(mContext);
    126     }
    127 
    128     @Override
    129     public void onLoadFinished(Loader<BatteryStatsHelper> loader,
    130             BatteryStatsHelper batteryHelper) {
    131         mBatteryHelper = batteryHelper;
    132         final PackageInfo packageInfo = mParent.getPackageInfo();
    133         if (packageInfo != null) {
    134             mSipper = findTargetSipper(batteryHelper, packageInfo.applicationInfo.uid);
    135             if (mParent.getActivity() != null) {
    136                 updateBattery();
    137             }
    138         }
    139     }
    140 
    141     @Override
    142     public void onLoaderReset(Loader<BatteryStatsHelper> loader) {
    143     }
    144 
    145     @VisibleForTesting
    146     void updateBattery() {
    147         mPreference.setEnabled(true);
    148         if (isBatteryStatsAvailable()) {
    149             final int dischargeAmount = mBatteryHelper.getStats().getDischargeAmount(
    150                     BatteryStats.STATS_SINCE_CHARGED);
    151 
    152             final List<BatterySipper> usageList = new ArrayList<>(mBatteryHelper.getUsageList());
    153             final double hiddenAmount = mBatteryUtils.removeHiddenBatterySippers(usageList);
    154             final int percentOfMax = (int) mBatteryUtils.calculateBatteryPercent(
    155                     mSipper.totalPowerMah, mBatteryHelper.getTotalPower(), hiddenAmount,
    156                     dischargeAmount);
    157             mBatteryPercent = Utils.formatPercentage(percentOfMax);
    158             mPreference.setSummary(mContext.getString(R.string.battery_summary, mBatteryPercent));
    159         } else {
    160             mPreference.setSummary(mContext.getString(R.string.no_battery_summary));
    161         }
    162     }
    163 
    164     @VisibleForTesting
    165     boolean isBatteryStatsAvailable() {
    166         return mBatteryHelper != null && mSipper != null;
    167     }
    168 
    169     @VisibleForTesting
    170     BatterySipper findTargetSipper(BatteryStatsHelper batteryHelper, int uid) {
    171         final List<BatterySipper> usageList = batteryHelper.getUsageList();
    172         for (int i = 0, size = usageList.size(); i < size; i++) {
    173             final BatterySipper sipper = usageList.get(i);
    174             if (sipper.getUid() == uid) {
    175                 return sipper;
    176             }
    177         }
    178         return null;
    179     }
    180 
    181 }
    182