| /* |
| * Copyright (C) 2009 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. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.settings.fuelgauge; |
| |
| import android.app.Activity; |
| import android.app.ActivityManager; |
| import android.app.ApplicationErrorReport; |
| import android.app.admin.DevicePolicyManager; |
| import android.content.BroadcastReceiver; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageInfo; |
| import android.content.pm.PackageManager; |
| import android.content.pm.PackageManager.NameNotFoundException; |
| import android.graphics.drawable.Drawable; |
| import android.net.Uri; |
| import android.os.BatteryStats; |
| import android.os.Bundle; |
| import android.os.Process; |
| import android.os.UserHandle; |
| import android.support.v7.preference.Preference; |
| import android.support.v7.preference.Preference.OnPreferenceClickListener; |
| import android.support.v7.preference.PreferenceCategory; |
| import android.text.TextUtils; |
| import android.util.Log; |
| import android.view.View; |
| import android.widget.Button; |
| |
| import com.android.internal.logging.MetricsLogger; |
| import com.android.internal.os.BatterySipper; |
| import com.android.internal.os.BatterySipper.DrainType; |
| import com.android.internal.os.BatteryStatsHelper; |
| import com.android.internal.util.FastPrintWriter; |
| import com.android.settings.AppHeader; |
| import com.android.settings.DisplaySettings; |
| import com.android.settings.R; |
| import com.android.settings.SettingsActivity; |
| import com.android.settings.Utils; |
| import com.android.settings.WirelessSettings; |
| import com.android.settings.applications.InstalledAppDetails; |
| import com.android.settings.applications.LayoutPreference; |
| import com.android.settings.bluetooth.BluetoothSettings; |
| import com.android.settings.location.LocationSettings; |
| import com.android.settings.wifi.WifiSettings; |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| |
| public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener { |
| |
| // Note: Must match the sequence of the DrainType |
| private static int[] sDrainTypeDesciptions = new int[] { |
| R.string.battery_desc_standby, |
| R.string.battery_desc_radio, |
| R.string.battery_desc_voice, |
| R.string.battery_desc_wifi, |
| R.string.battery_desc_bluetooth, |
| R.string.battery_desc_flashlight, |
| R.string.battery_desc_display, |
| R.string.battery_desc_apps, |
| R.string.battery_desc_users, |
| R.string.battery_desc_unaccounted, |
| R.string.battery_desc_overcounted, |
| R.string.battery_desc_camera, |
| }; |
| |
| public static void startBatteryDetailPage( |
| SettingsActivity caller, BatteryStatsHelper helper, int statsType, BatteryEntry entry, |
| boolean showLocationButton, boolean includeAppInfo) { |
| // Initialize mStats if necessary. |
| helper.getStats(); |
| |
| final int dischargeAmount = helper.getStats().getDischargeAmount(statsType); |
| Bundle args = new Bundle(); |
| args.putString(PowerUsageDetail.EXTRA_TITLE, entry.name); |
| args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int) |
| ((entry.sipper.totalPowerMah * dischargeAmount / helper.getTotalPower()) + .5)); |
| args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int) |
| Math.ceil(entry.sipper.totalPowerMah * 100 / helper.getMaxPower())); |
| args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, helper.getStatsPeriod()); |
| args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, entry.defaultPackageName); |
| args.putInt(PowerUsageDetail.EXTRA_ICON_ID, entry.iconId); |
| args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, entry.sipper.noCoveragePercent); |
| if (entry.sipper.uidObj != null) { |
| args.putInt(PowerUsageDetail.EXTRA_UID, entry.sipper.uidObj.getUid()); |
| } |
| args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, entry.sipper.drainType); |
| args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton); |
| args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, !includeAppInfo); |
| |
| int userId = UserHandle.myUserId(); |
| int[] types; |
| double[] values; |
| switch (entry.sipper.drainType) { |
| case APP: |
| case USER: |
| { |
| BatteryStats.Uid uid = entry.sipper.uidObj; |
| types = new int[] { |
| R.string.usage_type_cpu, |
| R.string.usage_type_cpu_foreground, |
| R.string.usage_type_wake_lock, |
| R.string.usage_type_gps, |
| R.string.usage_type_wifi_running, |
| R.string.usage_type_data_recv, |
| R.string.usage_type_data_send, |
| R.string.usage_type_radio_active, |
| R.string.usage_type_data_wifi_recv, |
| R.string.usage_type_data_wifi_send, |
| R.string.usage_type_audio, |
| R.string.usage_type_video, |
| R.string.usage_type_camera, |
| R.string.usage_type_flashlight, |
| R.string.usage_type_computed_power, |
| }; |
| values = new double[] { |
| entry.sipper.cpuTimeMs, |
| entry.sipper.cpuFgTimeMs, |
| entry.sipper.wakeLockTimeMs, |
| entry.sipper.gpsTimeMs, |
| entry.sipper.wifiRunningTimeMs, |
| entry.sipper.mobileRxPackets, |
| entry.sipper.mobileTxPackets, |
| entry.sipper.mobileActive, |
| entry.sipper.wifiRxPackets, |
| entry.sipper.wifiTxPackets, |
| 0, |
| 0, |
| entry.sipper.cameraTimeMs, |
| entry.sipper.flashlightTimeMs, |
| entry.sipper.totalPowerMah, |
| }; |
| |
| if (entry.sipper.drainType == BatterySipper.DrainType.APP) { |
| Writer result = new StringWriter(); |
| PrintWriter printWriter = new FastPrintWriter(result, false, 1024); |
| helper.getStats().dumpLocked(caller, printWriter, "", helper.getStatsType(), |
| uid.getUid()); |
| printWriter.flush(); |
| args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString()); |
| |
| result = new StringWriter(); |
| printWriter = new FastPrintWriter(result, false, 1024); |
| helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(), |
| uid.getUid()); |
| printWriter.flush(); |
| args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS, |
| result.toString()); |
| if (uid.getUid() != 0) { |
| userId = UserHandle.getUserId(uid.getUid()); |
| } |
| } |
| } |
| break; |
| case CELL: |
| { |
| types = new int[] { |
| R.string.usage_type_on_time, |
| R.string.usage_type_no_coverage, |
| R.string.usage_type_radio_active, |
| R.string.usage_type_computed_power, |
| }; |
| values = new double[] { |
| entry.sipper.usageTimeMs, |
| entry.sipper.noCoveragePercent, |
| entry.sipper.mobileActive, |
| entry.sipper.totalPowerMah, |
| }; |
| } |
| break; |
| case WIFI: |
| { |
| types = new int[] { |
| R.string.usage_type_wifi_running, |
| R.string.usage_type_cpu, |
| R.string.usage_type_cpu_foreground, |
| R.string.usage_type_wake_lock, |
| R.string.usage_type_data_recv, |
| R.string.usage_type_data_send, |
| R.string.usage_type_data_wifi_recv, |
| R.string.usage_type_data_wifi_send, |
| R.string.usage_type_computed_power, |
| }; |
| values = new double[] { |
| entry.sipper.wifiRunningTimeMs, |
| entry.sipper.cpuTimeMs, |
| entry.sipper.cpuFgTimeMs, |
| entry.sipper.wakeLockTimeMs, |
| entry.sipper.mobileRxPackets, |
| entry.sipper.mobileTxPackets, |
| entry.sipper.wifiRxPackets, |
| entry.sipper.wifiTxPackets, |
| entry.sipper.totalPowerMah, |
| }; |
| } break; |
| case BLUETOOTH: |
| { |
| types = new int[] { |
| R.string.usage_type_on_time, |
| R.string.usage_type_cpu, |
| R.string.usage_type_cpu_foreground, |
| R.string.usage_type_wake_lock, |
| R.string.usage_type_data_recv, |
| R.string.usage_type_data_send, |
| R.string.usage_type_data_wifi_recv, |
| R.string.usage_type_data_wifi_send, |
| R.string.usage_type_computed_power, |
| }; |
| values = new double[] { |
| entry.sipper.usageTimeMs, |
| entry.sipper.cpuTimeMs, |
| entry.sipper.cpuFgTimeMs, |
| entry.sipper.wakeLockTimeMs, |
| entry.sipper.mobileRxPackets, |
| entry.sipper.mobileTxPackets, |
| entry.sipper.wifiRxPackets, |
| entry.sipper.wifiTxPackets, |
| entry.sipper.totalPowerMah, |
| }; |
| } break; |
| case UNACCOUNTED: |
| { |
| types = new int[] { |
| R.string.usage_type_total_battery_capacity, |
| R.string.usage_type_computed_power, |
| R.string.usage_type_actual_power, |
| }; |
| values = new double[] { |
| helper.getPowerProfile().getBatteryCapacity(), |
| helper.getComputedPower(), |
| helper.getMinDrainedPower(), |
| }; |
| } break; |
| case OVERCOUNTED: |
| { |
| types = new int[] { |
| R.string.usage_type_total_battery_capacity, |
| R.string.usage_type_computed_power, |
| R.string.usage_type_actual_power, |
| }; |
| values = new double[] { |
| helper.getPowerProfile().getBatteryCapacity(), |
| helper.getComputedPower(), |
| helper.getMaxDrainedPower(), |
| }; |
| } break; |
| default: |
| { |
| types = new int[] { |
| R.string.usage_type_on_time, |
| R.string.usage_type_computed_power, |
| }; |
| values = new double[] { |
| entry.sipper.usageTimeMs, |
| entry.sipper.totalPowerMah, |
| }; |
| } |
| } |
| args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types); |
| args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values); |
| |
| caller.startPreferencePanelAsUser(PowerUsageDetail.class.getName(), args, |
| R.string.details_title, null, new UserHandle(userId)); |
| } |
| |
| public static final int ACTION_DISPLAY_SETTINGS = 1; |
| public static final int ACTION_WIFI_SETTINGS = 2; |
| public static final int ACTION_BLUETOOTH_SETTINGS = 3; |
| public static final int ACTION_WIRELESS_SETTINGS = 4; |
| public static final int ACTION_APP_DETAILS = 5; |
| public static final int ACTION_LOCATION_SETTINGS = 6; |
| public static final int ACTION_FORCE_STOP = 7; |
| public static final int ACTION_REPORT = 8; |
| |
| public static final int USAGE_SINCE_UNPLUGGED = 1; |
| public static final int USAGE_SINCE_RESET = 2; |
| |
| public static final String EXTRA_TITLE = "title"; |
| public static final String EXTRA_PERCENT = "percent"; |
| public static final String EXTRA_GAUGE = "gauge"; |
| public static final String EXTRA_UID = "uid"; |
| public static final String EXTRA_USAGE_SINCE = "since"; |
| public static final String EXTRA_USAGE_DURATION = "duration"; |
| public static final String EXTRA_REPORT_DETAILS = "report_details"; |
| public static final String EXTRA_REPORT_CHECKIN_DETAILS = "report_checkin_details"; |
| public static final String EXTRA_DETAIL_TYPES = "types"; // Array of usage types (cpu, gps, etc) |
| public static final String EXTRA_DETAIL_VALUES = "values"; // Array of doubles |
| public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType |
| public static final String EXTRA_ICON_PACKAGE = "iconPackage"; // String |
| public static final String EXTRA_NO_COVERAGE = "noCoverage"; |
| public static final String EXTRA_ICON_ID = "iconId"; // Int |
| public static final String EXTRA_SHOW_LOCATION_BUTTON = "showLocationButton"; // Boolean |
| |
| private static final String TAG = "PowerUsageDetail"; |
| |
| private static final String KEY_DETAILS_PARENT = "details_parent"; |
| private static final String KEY_CONTROLS_PARENT = "controls_parent"; |
| private static final String KEY_MESSAGES_PARENT = "messages_parent"; |
| private static final String KEY_PACKAGES_PARENT = "packages_parent"; |
| private static final String KEY_TWO_BUTTONS = "two_buttons"; |
| private static final String KEY_HIGH_POWER = "high_power"; |
| |
| private PackageManager mPm; |
| private DevicePolicyManager mDpm; |
| private int mUsageSince; |
| private int[] mTypes; |
| private int mUid; |
| private double[] mValues; |
| private Button mForceStopButton; |
| private Button mReportButton; |
| private long mStartTime; |
| private BatterySipper.DrainType mDrainType; |
| private double mNoCoverage; // Percentage of time that there was no coverage |
| |
| private PreferenceCategory mDetailsParent; |
| private PreferenceCategory mControlsParent; |
| private PreferenceCategory mMessagesParent; |
| private PreferenceCategory mPackagesParent; |
| |
| private boolean mUsesGps; |
| private boolean mShowLocationButton; |
| |
| private String[] mPackages; |
| |
| ApplicationInfo mApp; |
| ComponentName mInstaller; |
| private Preference mHighPower; |
| |
| @Override |
| public void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| mPm = getActivity().getPackageManager(); |
| mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE); |
| |
| addPreferencesFromResource(R.xml.power_usage_details); |
| mDetailsParent = (PreferenceCategory) findPreference(KEY_DETAILS_PARENT); |
| mControlsParent = (PreferenceCategory) findPreference(KEY_CONTROLS_PARENT); |
| mMessagesParent = (PreferenceCategory) findPreference(KEY_MESSAGES_PARENT); |
| mPackagesParent = (PreferenceCategory) findPreference(KEY_PACKAGES_PARENT); |
| |
| createDetails(); |
| } |
| |
| @Override |
| protected int getMetricsCategory() { |
| return MetricsLogger.FUELGAUGE_POWER_USAGE_DETAIL; |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| mStartTime = android.os.Process.getElapsedCpuTime(); |
| checkForceStop(); |
| if (mHighPower != null) { |
| mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName)); |
| } |
| |
| setupHeader(); |
| } |
| |
| @Override |
| public void onActivityResult(int requestCode, int resultCode, Intent data) { |
| super.onActivityResult(requestCode, resultCode, data); |
| if (mHighPower != null) { |
| mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName)); |
| } |
| } |
| |
| private void createDetails() { |
| final Bundle args = getArguments(); |
| Context context = getActivity(); |
| mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED); |
| mUid = args.getInt(EXTRA_UID, 0); |
| mPackages = context.getPackageManager().getPackagesForUid(mUid); |
| mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE); |
| mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0); |
| mShowLocationButton = args.getBoolean(EXTRA_SHOW_LOCATION_BUTTON); |
| |
| mTypes = args.getIntArray(EXTRA_DETAIL_TYPES); |
| mValues = args.getDoubleArray(EXTRA_DETAIL_VALUES); |
| |
| LayoutPreference twoButtons = (LayoutPreference) findPreference(KEY_TWO_BUTTONS); |
| mForceStopButton = (Button) twoButtons.findViewById(R.id.left_button); |
| mReportButton = (Button) twoButtons.findViewById(R.id.right_button); |
| mForceStopButton.setEnabled(false); |
| |
| if (mUid >= Process.FIRST_APPLICATION_UID) { |
| mForceStopButton.setText(R.string.force_stop); |
| mForceStopButton.setTag(ACTION_FORCE_STOP); |
| mForceStopButton.setOnClickListener(this); |
| mReportButton.setText(com.android.internal.R.string.report); |
| mReportButton.setTag(ACTION_REPORT); |
| mReportButton.setOnClickListener(this); |
| |
| if (mPackages != null && mPackages.length > 0) { |
| try { |
| mApp = context.getPackageManager().getApplicationInfo( |
| mPackages[0], 0); |
| } catch (NameNotFoundException e) { |
| } |
| } else { |
| Log.d(TAG, "No packages!!"); |
| } |
| // check if error reporting is enabled in secure settings |
| int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), |
| android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0); |
| if (enabled != 0) { |
| if (mApp != null) { |
| mInstaller = ApplicationErrorReport.getErrorReportReceiver( |
| context, mPackages[0], mApp.flags); |
| } |
| mReportButton.setEnabled(mInstaller != null); |
| } else { |
| removePreference(KEY_TWO_BUTTONS); |
| } |
| if (mApp != null |
| && PowerWhitelistBackend.getInstance().isWhitelisted(mApp.packageName)) { |
| mHighPower = findPreference(KEY_HIGH_POWER); |
| mHighPower.setOnPreferenceClickListener(new OnPreferenceClickListener() { |
| @Override |
| public boolean onPreferenceClick(Preference preference) { |
| HighPowerDetail.show(PowerUsageDetail.this, mApp.packageName, 0, false); |
| return true; |
| } |
| }); |
| } else { |
| mControlsParent.removePreference(findPreference(KEY_HIGH_POWER)); |
| } |
| } else { |
| removePreference(KEY_TWO_BUTTONS); |
| mControlsParent.removePreference(findPreference(KEY_HIGH_POWER)); |
| } |
| |
| refreshStats(); |
| |
| fillDetailsSection(); |
| fillPackagesSection(mUid); |
| fillControlsSection(mUid); |
| fillMessagesSection(mUid); |
| } |
| |
| private void setupHeader() { |
| final Bundle args = getArguments(); |
| String title = args.getString(EXTRA_TITLE); |
| String pkg = args.getString(EXTRA_ICON_PACKAGE); |
| int iconId = args.getInt(EXTRA_ICON_ID, 0); |
| Drawable appIcon = null; |
| int uid = -1; |
| final PackageManager pm = getActivity().getPackageManager(); |
| |
| if (!TextUtils.isEmpty(pkg)) { |
| try { |
| ApplicationInfo ai = pm.getPackageInfo(pkg, 0).applicationInfo; |
| if (ai != null) { |
| appIcon = ai.loadIcon(pm); |
| uid = ai.uid; |
| } |
| } catch (NameNotFoundException nnfe) { |
| // Use default icon |
| } |
| } else if (iconId != 0) { |
| appIcon = getActivity().getDrawable(iconId); |
| } |
| if (appIcon == null) { |
| appIcon = getActivity().getPackageManager().getDefaultActivityIcon(); |
| } |
| |
| if (pkg == null && mPackages != null) { |
| pkg = mPackages[0]; |
| } |
| AppHeader.createAppHeader(this, appIcon, title, pkg, uid, |
| mDrainType != DrainType.APP ? android.R.color.white : 0); |
| } |
| |
| public void onClick(View v) { |
| doAction((Integer) v.getTag()); |
| } |
| |
| // utility method used to start sub activity |
| private void startApplicationDetailsActivity() { |
| // start new fragment to display extended information |
| Bundle args = new Bundle(); |
| args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mPackages[0]); |
| |
| SettingsActivity sa = (SettingsActivity) getActivity(); |
| sa.startPreferencePanel(InstalledAppDetails.class.getName(), args, |
| R.string.application_info_label, null, null, 0); |
| } |
| |
| private void doAction(int action) { |
| SettingsActivity sa = (SettingsActivity)getActivity(); |
| switch (action) { |
| case ACTION_DISPLAY_SETTINGS: |
| sa.startPreferencePanel(DisplaySettings.class.getName(), null, |
| R.string.display_settings_title, null, null, 0); |
| break; |
| case ACTION_WIFI_SETTINGS: |
| sa.startPreferencePanel(WifiSettings.class.getName(), null, |
| R.string.wifi_settings, null, null, 0); |
| break; |
| case ACTION_BLUETOOTH_SETTINGS: |
| sa.startPreferencePanel(BluetoothSettings.class.getName(), null, |
| R.string.bluetooth_settings, null, null, 0); |
| break; |
| case ACTION_WIRELESS_SETTINGS: |
| sa.startPreferencePanel(WirelessSettings.class.getName(), null, |
| R.string.radio_controls_title, null, null, 0); |
| break; |
| case ACTION_APP_DETAILS: |
| startApplicationDetailsActivity(); |
| break; |
| case ACTION_LOCATION_SETTINGS: |
| sa.startPreferencePanel(LocationSettings.class.getName(), null, |
| R.string.location_settings_title, null, null, 0); |
| break; |
| case ACTION_FORCE_STOP: |
| killProcesses(); |
| break; |
| case ACTION_REPORT: |
| reportBatteryUse(); |
| break; |
| } |
| } |
| |
| private void fillDetailsSection() { |
| if (mTypes != null && mValues != null) { |
| for (int i = 0; i < mTypes.length; i++) { |
| // Only add an item if the time is greater than zero |
| if (mValues[i] <= 0) continue; |
| final String label = getString(mTypes[i]); |
| String value = null; |
| switch (mTypes[i]) { |
| case R.string.usage_type_data_recv: |
| case R.string.usage_type_data_send: |
| case R.string.usage_type_data_wifi_recv: |
| case R.string.usage_type_data_wifi_send: |
| final long packets = (long) (mValues[i]); |
| value = Long.toString(packets); |
| break; |
| case R.string.usage_type_no_coverage: |
| final int percentage = (int) Math.floor(mValues[i]); |
| value = Utils.formatPercentage(percentage); |
| break; |
| case R.string.usage_type_total_battery_capacity: |
| case R.string.usage_type_computed_power: |
| case R.string.usage_type_actual_power: |
| value = getActivity().getString(R.string.mah, (long)(mValues[i])); |
| break; |
| case R.string.usage_type_gps: |
| mUsesGps = true; |
| // Fall through |
| default: |
| value = Utils.formatElapsedTime(getActivity(), mValues[i], true); |
| } |
| addHorizontalPreference(mDetailsParent, label, value); |
| } |
| } |
| } |
| |
| private void addHorizontalPreference(PreferenceCategory parent, CharSequence title, |
| CharSequence summary) { |
| Preference pref = new Preference(getPrefContext()); |
| pref.setLayoutResource(R.layout.horizontal_preference); |
| pref.setTitle(title); |
| pref.setSummary(summary); |
| pref.setSelectable(false); |
| parent.addPreference(pref); |
| } |
| |
| private void fillControlsSection(int uid) { |
| PackageManager pm = getActivity().getPackageManager(); |
| String[] packages = pm.getPackagesForUid(uid); |
| PackageInfo pi = null; |
| try { |
| pi = packages != null ? pm.getPackageInfo(packages[0], 0) : null; |
| } catch (NameNotFoundException nnfe) { /* Nothing */ } |
| ApplicationInfo ai = pi != null? pi.applicationInfo : null; |
| |
| boolean removeHeader = true; |
| switch (mDrainType) { |
| case APP: |
| // If it is a Java application and only one package is associated with the Uid |
| if (packages != null && packages.length == 1) { |
| addControl(R.string.battery_action_app_details, |
| R.string.battery_sugg_apps_info, ACTION_APP_DETAILS); |
| removeHeader = false; |
| // If the application has a settings screen, jump to that |
| // TODO: |
| } |
| // If power usage detail page is launched from location page, suppress "Location" |
| // button to prevent circular loops. |
| if (mUsesGps && mShowLocationButton) { |
| addControl(R.string.location_settings_title, |
| R.string.battery_sugg_apps_gps, ACTION_LOCATION_SETTINGS); |
| removeHeader = false; |
| } |
| break; |
| case SCREEN: |
| addControl(R.string.display_settings, |
| R.string.battery_sugg_display, |
| ACTION_DISPLAY_SETTINGS); |
| removeHeader = false; |
| break; |
| case WIFI: |
| addControl(R.string.wifi_settings, |
| R.string.battery_sugg_wifi, |
| ACTION_WIFI_SETTINGS); |
| removeHeader = false; |
| break; |
| case BLUETOOTH: |
| addControl(R.string.bluetooth_settings, |
| R.string.battery_sugg_bluetooth_basic, |
| ACTION_BLUETOOTH_SETTINGS); |
| removeHeader = false; |
| break; |
| case CELL: |
| if (mNoCoverage > 10) { |
| addControl(R.string.radio_controls_title, |
| R.string.battery_sugg_radio, |
| ACTION_WIRELESS_SETTINGS); |
| removeHeader = false; |
| } |
| break; |
| } |
| if (removeHeader) { |
| mControlsParent.setTitle(null); |
| } |
| } |
| |
| private void addControl(int pageSummary, int actionTitle, final int action) { |
| Preference pref = new Preference(getPrefContext()); |
| pref.setTitle(actionTitle); |
| pref.setLayoutResource(R.layout.horizontal_preference); |
| pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { |
| @Override |
| public boolean onPreferenceClick(Preference preference) { |
| doAction(action); |
| return true; |
| } |
| }); |
| mControlsParent.addPreference(pref); |
| } |
| |
| private void fillMessagesSection(int uid) { |
| boolean removeHeader = true; |
| switch (mDrainType) { |
| case UNACCOUNTED: |
| addMessage(R.string.battery_msg_unaccounted); |
| removeHeader = false; |
| break; |
| } |
| if (removeHeader) { |
| mMessagesParent.setTitle(null); |
| } |
| } |
| |
| private void addMessage(int message) { |
| addHorizontalPreference(mMessagesParent, getString(message), null); |
| } |
| |
| private void removePackagesSection() { |
| getPreferenceScreen().removePreference(mPackagesParent); |
| } |
| |
| private void killProcesses() { |
| if (mPackages == null) return; |
| ActivityManager am = (ActivityManager)getActivity().getSystemService( |
| Context.ACTIVITY_SERVICE); |
| final int userId = UserHandle.getUserId(mUid); |
| for (int i = 0; i < mPackages.length; i++) { |
| am.forceStopPackageAsUser(mPackages[i], userId); |
| } |
| checkForceStop(); |
| } |
| |
| private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED); |
| } |
| }; |
| |
| private void checkForceStop() { |
| if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) { |
| mForceStopButton.setEnabled(false); |
| return; |
| } |
| for (int i = 0; i < mPackages.length; i++) { |
| if (mDpm.packageHasActiveAdmins(mPackages[i])) { |
| mForceStopButton.setEnabled(false); |
| return; |
| } |
| } |
| for (int i = 0; i < mPackages.length; i++) { |
| try { |
| ApplicationInfo info = mPm.getApplicationInfo(mPackages[i], 0); |
| if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) { |
| mForceStopButton.setEnabled(true); |
| break; |
| } |
| } catch (PackageManager.NameNotFoundException e) { |
| } |
| } |
| Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART, |
| Uri.fromParts("package", mPackages[0], null)); |
| intent.putExtra(Intent.EXTRA_PACKAGES, mPackages); |
| intent.putExtra(Intent.EXTRA_UID, mUid); |
| intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mUid)); |
| getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null, |
| Activity.RESULT_CANCELED, null, null); |
| } |
| |
| private void reportBatteryUse() { |
| if (mPackages == null) return; |
| |
| ApplicationErrorReport report = new ApplicationErrorReport(); |
| report.type = ApplicationErrorReport.TYPE_BATTERY; |
| report.packageName = mPackages[0]; |
| report.installerPackageName = mInstaller.getPackageName(); |
| report.processName = mPackages[0]; |
| report.time = System.currentTimeMillis(); |
| report.systemApp = (mApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
| |
| final Bundle args = getArguments(); |
| ApplicationErrorReport.BatteryInfo batteryInfo = new ApplicationErrorReport.BatteryInfo(); |
| batteryInfo.usagePercent = args.getInt(EXTRA_PERCENT, 1); |
| batteryInfo.durationMicros = args.getLong(EXTRA_USAGE_DURATION, 0); |
| batteryInfo.usageDetails = args.getString(EXTRA_REPORT_DETAILS); |
| batteryInfo.checkinDetails = args.getString(EXTRA_REPORT_CHECKIN_DETAILS); |
| report.batteryInfo = batteryInfo; |
| |
| Intent result = new Intent(Intent.ACTION_APP_ERROR); |
| result.setComponent(mInstaller); |
| result.putExtra(Intent.EXTRA_BUG_REPORT, report); |
| result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| startActivity(result); |
| } |
| |
| private void fillPackagesSection(int uid) { |
| if (uid < 1) { |
| removePackagesSection(); |
| return; |
| } |
| if (mPackages == null || mPackages.length < 2) { |
| removePackagesSection(); |
| return; |
| } |
| |
| PackageManager pm = getPackageManager(); |
| // Convert package names to user-facing labels where possible |
| for (int i = 0; i < mPackages.length; i++) { |
| try { |
| ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0); |
| CharSequence label = ai.loadLabel(pm); |
| if (label != null) { |
| mPackages[i] = label.toString(); |
| } |
| addHorizontalPreference(mPackagesParent, mPackages[i], null); |
| } catch (NameNotFoundException e) { |
| } |
| } |
| } |
| } |