Home | History | Annotate | Download | only in fuelgauge
      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.fuelgauge;
     18 
     19 import android.app.Activity;
     20 import android.app.admin.DevicePolicyManager;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.pm.PackageManager;
     24 import android.os.BatteryStats;
     25 import android.os.Bundle;
     26 import android.os.UserHandle;
     27 import android.os.UserManager;
     28 import android.support.annotation.VisibleForTesting;
     29 import android.support.v14.preference.PreferenceFragment;
     30 import android.support.v7.preference.Preference;
     31 import android.view.View;
     32 
     33 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     34 import com.android.internal.os.BatterySipper;
     35 import com.android.internal.os.BatteryStatsHelper;
     36 import com.android.internal.util.ArrayUtils;
     37 import com.android.settings.R;
     38 import com.android.settings.SettingsActivity;
     39 import com.android.settings.Utils;
     40 import com.android.settings.applications.AppHeaderController;
     41 import com.android.settings.applications.LayoutPreference;
     42 import com.android.settings.core.PreferenceController;
     43 import com.android.settings.dashboard.DashboardFragment;
     44 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
     45 import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
     46 import com.android.settings.overlay.FeatureFactory;
     47 import com.android.settingslib.applications.AppUtils;
     48 import com.android.settingslib.applications.ApplicationsState;
     49 
     50 import java.util.ArrayList;
     51 import java.util.List;
     52 
     53 /**
     54  * Power usage detail fragment for each app, this fragment contains
     55  *
     56  * 1. Detail battery usage information for app(i.e. usage time, usage amount)
     57  * 2. Battery related controls for app(i.e uninstall, force stop)
     58  *
     59  */
     60 public class AdvancedPowerUsageDetail extends DashboardFragment implements
     61         ButtonActionDialogFragment.AppButtonsDialogListener {
     62 
     63     public static final String TAG = "AdvancedPowerUsageDetail";
     64     public static final String EXTRA_UID = "extra_uid";
     65     public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
     66     public static final String EXTRA_FOREGROUND_TIME = "extra_foreground_time";
     67     public static final String EXTRA_BACKGROUND_TIME = "extra_background_time";
     68     public static final String EXTRA_LABEL = "extra_label";
     69     public static final String EXTRA_ICON_ID = "extra_icon_id";
     70     public static final String EXTRA_POWER_USAGE_PERCENT = "extra_power_usage_percent";
     71     public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
     72 
     73     private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";
     74     private static final String KEY_PREF_BACKGROUND = "app_usage_background";
     75     private static final String KEY_PREF_POWER_USAGE = "app_power_usage";
     76     private static final String KEY_PREF_HEADER = "header_view";
     77 
     78     private static final int REQUEST_UNINSTALL = 0;
     79     private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
     80 
     81     @VisibleForTesting
     82     LayoutPreference mHeaderPreference;
     83     @VisibleForTesting
     84     ApplicationsState mState;
     85     @VisibleForTesting
     86     ApplicationsState.AppEntry mAppEntry;
     87     @VisibleForTesting
     88     BatteryUtils mBatteryUtils;
     89 
     90     private Preference mForegroundPreference;
     91     private Preference mBackgroundPreference;
     92     private Preference mPowerUsagePreference;
     93     private AppButtonsPreferenceController mAppButtonsPreferenceController;
     94 
     95     private DevicePolicyManagerWrapper mDpm;
     96     private UserManager mUserManager;
     97     private PackageManager mPackageManager;
     98 
     99     public static void startBatteryDetailPage(SettingsActivity caller, PreferenceFragment fragment,
    100             BatteryStatsHelper helper, int which, BatteryEntry entry, String usagePercent) {
    101         // Initialize mStats if necessary.
    102         helper.getStats();
    103 
    104         final Bundle args = new Bundle();
    105         final BatterySipper sipper = entry.sipper;
    106         final BatteryStats.Uid uid = sipper.uidObj;
    107         final BatteryUtils batteryUtils = BatteryUtils.getInstance(caller);
    108         final boolean isTypeApp = sipper.drainType == BatterySipper.DrainType.APP;
    109 
    110         final long foregroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(
    111                 BatteryUtils.StatusType.FOREGROUND, uid, which) : sipper.usageTimeMs;
    112         final long backgroundTimeMs = isTypeApp ? batteryUtils.getProcessTimeMs(
    113                 BatteryUtils.StatusType.BACKGROUND, uid, which) : 0;
    114 
    115         if (ArrayUtils.isEmpty(sipper.mPackages)) {
    116             // populate data for system app
    117             args.putString(EXTRA_LABEL, entry.getLabel());
    118             args.putInt(EXTRA_ICON_ID, entry.iconId);
    119             args.putString(EXTRA_PACKAGE_NAME, null);
    120         } else {
    121             // populate data for normal app
    122             args.putString(EXTRA_PACKAGE_NAME, entry.defaultPackageName);
    123         }
    124 
    125         args.putInt(EXTRA_UID, sipper.getUid());
    126         args.putLong(EXTRA_BACKGROUND_TIME, backgroundTimeMs);
    127         args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs);
    128         args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent);
    129         args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) sipper.totalPowerMah);
    130 
    131         caller.startPreferencePanelAsUser(fragment, AdvancedPowerUsageDetail.class.getName(), args,
    132                 R.string.battery_details_title, null,
    133                 new UserHandle(UserHandle.getUserId(sipper.getUid())));
    134     }
    135 
    136     public static void startBatteryDetailPage(SettingsActivity caller, PreferenceFragment fragment,
    137             String packageName) {
    138         final Bundle args = new Bundle(2);
    139         args.putString(EXTRA_PACKAGE_NAME, packageName);
    140         args.putString(EXTRA_POWER_USAGE_PERCENT, Utils.formatPercentage(0));
    141 
    142         caller.startPreferencePanelAsUser(fragment, AdvancedPowerUsageDetail.class.getName(), args,
    143                 R.string.battery_details_title, null, new UserHandle(UserHandle.myUserId()));
    144     }
    145 
    146     @Override
    147     public void onAttach(Activity activity) {
    148         super.onAttach(activity);
    149 
    150         mState = ApplicationsState.getInstance(getActivity().getApplication());
    151         mDpm = new DevicePolicyManagerWrapperImpl(
    152                 (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
    153         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
    154         mPackageManager = activity.getPackageManager();
    155         mBatteryUtils = BatteryUtils.getInstance(getContext());
    156     }
    157 
    158     @Override
    159     public void onCreate(Bundle icicle) {
    160         super.onCreate(icicle);
    161 
    162         mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);
    163         mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);
    164         mPowerUsagePreference = findPreference(KEY_PREF_POWER_USAGE);
    165         mHeaderPreference = (LayoutPreference) findPreference(KEY_PREF_HEADER);
    166 
    167         final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
    168         if (packageName != null) {
    169             mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
    170         }
    171     }
    172 
    173     @Override
    174     public void onResume() {
    175         super.onResume();
    176 
    177         initHeader();
    178 
    179         final Bundle bundle = getArguments();
    180         final Context context = getContext();
    181 
    182         final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
    183         final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
    184         final String usagePercent = bundle.getString(EXTRA_POWER_USAGE_PERCENT);
    185         final int powerMah = bundle.getInt(EXTRA_POWER_USAGE_AMOUNT);
    186         mForegroundPreference.setSummary(Utils.formatElapsedTime(context, foregroundTimeMs, false));
    187         mBackgroundPreference.setSummary(Utils.formatElapsedTime(context, backgroundTimeMs, false));
    188         mPowerUsagePreference.setSummary(
    189                 getString(R.string.battery_detail_power_percentage, usagePercent, powerMah));
    190     }
    191 
    192     @VisibleForTesting
    193     void initHeader() {
    194         final View appSnippet = mHeaderPreference.findViewById(R.id.app_snippet);
    195         final Activity context = getActivity();
    196         final Bundle bundle = getArguments();
    197         AppHeaderController controller = FeatureFactory.getFactory(context)
    198                 .getApplicationFeatureProvider(context)
    199                 .newAppHeaderController(this, appSnippet)
    200                 .setButtonActions(AppHeaderController.ActionType.ACTION_NONE,
    201                         AppHeaderController.ActionType.ACTION_NONE);
    202 
    203         if (mAppEntry == null) {
    204             controller.setLabel(bundle.getString(EXTRA_LABEL));
    205 
    206             final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
    207             if (iconId == 0) {
    208                 controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
    209             } else {
    210                 controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
    211             }
    212         } else {
    213             mState.ensureIcon(mAppEntry);
    214             controller.setLabel(mAppEntry);
    215             controller.setIcon(mAppEntry);
    216             boolean isInstantApp = AppUtils.isInstant(mAppEntry.info);
    217             CharSequence summary = isInstantApp
    218                     ? null : getString(Utils.getInstallationStatus(mAppEntry.info));
    219             controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
    220             controller.setSummary(summary);
    221         }
    222 
    223         controller.done(context, true /* rebindActions */);
    224     }
    225 
    226     @Override
    227     public int getMetricsCategory() {
    228         return MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL;
    229     }
    230 
    231     @Override
    232     protected String getLogTag() {
    233         return TAG;
    234     }
    235 
    236     @Override
    237     protected int getPreferenceScreenResId() {
    238         return R.xml.power_usage_detail_ia;
    239     }
    240 
    241     @Override
    242     protected List<PreferenceController> getPreferenceControllers(Context context) {
    243         final List<PreferenceController> controllers = new ArrayList<>();
    244         final Bundle bundle = getArguments();
    245         final int uid = bundle.getInt(EXTRA_UID, 0);
    246         final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
    247 
    248         controllers.add(new BackgroundActivityPreferenceController(context, uid));
    249         controllers.add(new BatteryOptimizationPreferenceController(
    250                 (SettingsActivity) getActivity(), this, packageName));
    251         mAppButtonsPreferenceController = new AppButtonsPreferenceController(
    252                 (SettingsActivity) getActivity(), this, getLifecycle(), packageName, mState, mDpm,
    253                 mUserManager, mPackageManager, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
    254         controllers.add(mAppButtonsPreferenceController);
    255 
    256         return controllers;
    257     }
    258 
    259     @Override
    260     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    261         super.onActivityResult(requestCode, resultCode, data);
    262         if (mAppButtonsPreferenceController != null) {
    263             mAppButtonsPreferenceController.handleActivityResult(requestCode, resultCode, data);
    264         }
    265     }
    266 
    267     @Override
    268     public void handleDialogClick(int id) {
    269         if (mAppButtonsPreferenceController != null) {
    270             mAppButtonsPreferenceController.handleDialogClick(id);
    271         }
    272     }
    273 }
    274