Add new button to report battery usage to the developer.

This displays a new button on the application battery usage details
screen for the user to send a bug report to the developer, if that is
possible to do.  Also adds a button to directly force stop the app
from the details screen, and uses the new facilities to determine
whether the button should be enabled.
This commit is contained in:
Dianne Hackborn
2010-02-21 20:07:27 -08:00
parent d814bb7309
commit cb497546ba
7 changed files with 257 additions and 36 deletions

View File

@@ -28,6 +28,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dip" android:layout_marginTop="2dip"
android:paddingBottom="4dip"
android:ellipsize="marquee" android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"/> android:textAppearance="?android:attr/textAppearanceMedium"/>

View File

@@ -87,6 +87,17 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<!-- Force stop and report buttons -->
<LinearLayout
android:id="@+id/two_buttons_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="6dip"
android:orientation="vertical">
<include
layout="@layout/two_buttons_panel"/>
</LinearLayout>
<TextView <TextView
style="?android:attr/listSeparatorTextViewStyle" style="?android:attr/listSeparatorTextViewStyle"
android:text="@string/details_subtitle" /> android:text="@string/details_subtitle" />

View File

@@ -35,20 +35,20 @@
android:text="@string/no_running_services" android:text="@string/no_running_services"
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge" />
</FrameLayout> </FrameLayout>
<LinearLayout <view class="com.android.settings.RunningServices$LinearColorBar"
android:id="@+id/color_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:background="?android:attr/colorForeground"
android:padding="4dp"> android:padding="4dp">
<TextView android:id="@+id/backgroundText" <TextView android:id="@+id/foregroundText"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceSmallInverse" android:textAppearance="?android:attr/textAppearanceSmallInverse"
android:color="?android:attr/textColorPrimaryInverse" android:color="?android:attr/textColorPrimaryInverse"
android:singleLine="true" /> android:singleLine="true" />
<TextView android:id="@+id/foregroundText" <TextView android:id="@+id/backgroundText"
android:layout_gravity="center_vertical|right" android:layout_gravity="center_vertical|right"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -56,5 +56,5 @@
android:textAppearance="?android:attr/textAppearanceSmallInverse" android:textAppearance="?android:attr/textAppearanceSmallInverse"
android:color="?android:attr/textColorPrimaryInverse" android:color="?android:attr/textColorPrimaryInverse"
android:singleLine="true" /> android:singleLine="true" />
</LinearLayout> </view>
</LinearLayout> </LinearLayout>

View File

@@ -23,14 +23,13 @@ import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ActivityManager.RunningAppProcessInfo; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver; import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
@@ -43,7 +42,6 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.RemoteException; import android.os.RemoteException;
import android.text.format.Formatter; import android.text.format.Formatter;
import android.util.Config;
import android.util.Log; import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -234,25 +232,6 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
// Register listener // Register listener
mUninstallButton.setOnClickListener(this); mUninstallButton.setOnClickListener(this);
} }
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> rList = am.getRunningAppProcesses();
boolean running = false;
if (rList != null) {
for (RunningAppProcessInfo info : rList) {
if (info.pkgList != null) {
for (String rpkg : info.pkgList) {
if (rpkg.equals(mAppInfo.packageName)) {
running = true;
break;
}
}
}
}
}
mForceStopButton.setEnabled(running);
if (running) {
mForceStopButton.setOnClickListener(this);
}
} }
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@@ -292,6 +271,7 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
mForceStopButton = (Button) btnPanel.findViewById(R.id.left_button); mForceStopButton = (Button) btnPanel.findViewById(R.id.left_button);
mForceStopButton.setText(R.string.force_stop); mForceStopButton.setText(R.string.force_stop);
mUninstallButton = (Button)btnPanel.findViewById(R.id.right_button); mUninstallButton = (Button)btnPanel.findViewById(R.id.right_button);
mForceStopButton.setEnabled(false);
initControlButtons(); initControlButtons();
// Initialize clear data and move install location buttons // Initialize clear data and move install location buttons
View data_buttons_panel = findViewById(R.id.data_buttons_panel); View data_buttons_panel = findViewById(R.id.data_buttons_panel);
@@ -384,6 +364,7 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
showDialogInner(DLG_APP_NOT_FOUND); showDialogInner(DLG_APP_NOT_FOUND);
return; return;
} }
checkForceStop();
refreshAppAttributes(pkgInfo); refreshAppAttributes(pkgInfo);
} }
@@ -604,6 +585,23 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
ActivityManager am = (ActivityManager)getSystemService( ActivityManager am = (ActivityManager)getSystemService(
Context.ACTIVITY_SERVICE); Context.ACTIVITY_SERVICE);
am.forceStopPackage(pkgName); am.forceStopPackage(pkgName);
checkForceStop();
}
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mForceStopButton.setEnabled(getResultCode() != RESULT_CANCELED);
}
};
private void checkForceStop() {
Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
Uri.fromParts("package", mAppInfo.packageName, null));
intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mAppInfo.packageName });
intent.putExtra(Intent.EXTRA_UID, mAppInfo.uid);
sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
Activity.RESULT_CANCELED, null, null);
} }
/* /*

View File

@@ -35,6 +35,9 @@ import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
@@ -53,6 +56,7 @@ import android.view.ViewGroup;
import android.widget.AbsListView; import android.widget.AbsListView;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
@@ -93,13 +97,16 @@ public class RunningServices extends ListActivity
int mProcessBgColor; int mProcessBgColor;
LinearColorBar mColorBar;
TextView mBackgroundProcessText; TextView mBackgroundProcessText;
TextView mForegroundProcessText; TextView mForegroundProcessText;
int mLastNumBackgroundProcesses = -1; int mLastNumBackgroundProcesses = -1;
int mLastNumForegroundProcesses = -1; int mLastNumForegroundProcesses = -1;
int mLastNumServiceProcesses = -1;
long mLastBackgroundProcessMemory = -1; long mLastBackgroundProcessMemory = -1;
long mLastForegroundProcessMemory = -1; long mLastForegroundProcessMemory = -1;
long mLastServiceProcessMemory = -1;
long mLastAvailMemory = -1; long mLastAvailMemory = -1;
Dialog mCurDialog; Dialog mCurDialog;
@@ -392,6 +399,8 @@ public class RunningServices extends ListActivity
long mBackgroundProcessMemory; long mBackgroundProcessMemory;
int mNumForegroundProcesses; int mNumForegroundProcesses;
long mForegroundProcessMemory; long mForegroundProcessMemory;
int mNumServiceProcesses;
long mServiceProcessMemory;
boolean update(Context context, ActivityManager am) { boolean update(Context context, ActivityManager am) {
final PackageManager pm = context.getPackageManager(); final PackageManager pm = context.getPackageManager();
@@ -576,6 +585,7 @@ public class RunningServices extends ListActivity
mAllProcessItems.addAll(mProcessItems); mAllProcessItems.addAll(mProcessItems);
mNumBackgroundProcesses = 0; mNumBackgroundProcesses = 0;
mNumForegroundProcesses = 0; mNumForegroundProcesses = 0;
mNumServiceProcesses = 0;
NRP = mRunningProcesses.size(); NRP = mRunningProcesses.size();
for (int i=0; i<NRP; i++) { for (int i=0; i<NRP; i++) {
ProcessItem proc = mRunningProcesses.valueAt(i); ProcessItem proc = mRunningProcesses.valueAt(i);
@@ -590,13 +600,19 @@ public class RunningServices extends ListActivity
ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) { ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
mNumForegroundProcesses++; mNumForegroundProcesses++;
mAllProcessItems.add(proc); mAllProcessItems.add(proc);
} else {
Log.i(TAG, "Unknown non-service process: "
+ proc.mProcessName + " #" + proc.mPid);
} }
} else {
mNumServiceProcesses++;
} }
} }
try { try {
mBackgroundProcessMemory = 0; mBackgroundProcessMemory = 0;
mForegroundProcessMemory = 0; mForegroundProcessMemory = 0;
mServiceProcessMemory = 0;
final int numProc = mAllProcessItems.size(); final int numProc = mAllProcessItems.size();
int[] pids = new int[numProc]; int[] pids = new int[numProc];
for (int i=0; i<numProc; i++) { for (int i=0; i<numProc; i++) {
@@ -608,9 +624,8 @@ public class RunningServices extends ListActivity
ProcessItem proc = mAllProcessItems.get(i); ProcessItem proc = mAllProcessItems.get(i);
changed |= proc.updateSize(context, mem[i], mSequence); changed |= proc.updateSize(context, mem[i], mSequence);
if (proc.mCurSeq == mSequence) { if (proc.mCurSeq == mSequence) {
continue; mServiceProcessMemory += proc.mSize;
} } else if (proc.mRunningProcessInfo.importance >=
if (proc.mRunningProcessInfo.importance >=
ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
mBackgroundProcessMemory += proc.mSize; mBackgroundProcessMemory += proc.mSize;
} else if (proc.mRunningProcessInfo.importance <= } else if (proc.mRunningProcessInfo.importance <=
@@ -725,6 +740,67 @@ public class RunningServices extends ListActivity
} }
} }
public static class LinearColorBar extends LinearLayout {
private float mRedRatio;
private float mYellowRatio;
private float mGreenRatio;
final Rect mRect = new Rect();
final Paint mPaint = new Paint();
public LinearColorBar(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
mPaint.setStyle(Paint.Style.FILL);
}
public void setRatios(float red, float yellow, float green) {
mRedRatio = red;
mYellowRatio = yellow;
mGreenRatio = green;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
mRect.top = 0;
mRect.bottom = getHeight();
int left = 0;
int right = left + (int)(width*mRedRatio);
if (left < right) {
mRect.left = left;
mRect.right = right;
mPaint.setColor(0xffff8080);
canvas.drawRect(mRect, mPaint);
width -= (right-left);
left = right;
}
right = left + (int)(width*mYellowRatio);
if (left < right) {
mRect.left = left;
mRect.right = right;
mPaint.setColor(0xffffff00);
canvas.drawRect(mRect, mPaint);
width -= (right-left);
left = right;
}
right = left + width;
if (left < right) {
mRect.left = left;
mRect.right = right;
mPaint.setColor(0xff80ff80);
canvas.drawRect(mRect, mPaint);
}
}
}
final Handler mHandler = new Handler() { final Handler mHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
@@ -823,6 +899,7 @@ public class RunningServices extends ListActivity
setContentView(R.layout.running_services); setContentView(R.layout.running_services);
getListView().setDivider(null); getListView().setDivider(null);
getListView().setAdapter(new ServiceListAdapter(mState)); getListView().setAdapter(new ServiceListAdapter(mState));
mColorBar = (LinearColorBar)findViewById(R.id.color_bar);
mBackgroundProcessText = (TextView)findViewById(R.id.backgroundText); mBackgroundProcessText = (TextView)findViewById(R.id.backgroundText);
mForegroundProcessText = (TextView)findViewById(R.id.foregroundText); mForegroundProcessText = (TextView)findViewById(R.id.foregroundText);
@@ -864,6 +941,14 @@ public class RunningServices extends ListActivity
mForegroundProcessText.setText(getResources().getString( mForegroundProcessText.setText(getResources().getString(
R.string.service_foreground_processes, mLastNumForegroundProcesses, sizeStr)); R.string.service_foreground_processes, mLastNumForegroundProcesses, sizeStr));
} }
mLastNumServiceProcesses = mState.mNumServiceProcesses;
mLastServiceProcessMemory = mState.mServiceProcessMemory;
float totalMem = mLastBackgroundProcessMemory
+ mLastForegroundProcessMemory + mLastServiceProcessMemory;
mColorBar.setRatios(mLastForegroundProcessMemory/totalMem,
mLastServiceProcessMemory/totalMem,
mLastForegroundProcessMemory/totalMem);
} }
@Override @Override

View File

@@ -18,6 +18,9 @@ package com.android.settings.fuelgauge;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ApplicationErrorReport;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -26,9 +29,12 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -37,6 +43,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.android.settings.InstalledAppDetails; import com.android.settings.InstalledAppDetails;
import com.android.settings.ManageApplications;
import com.android.settings.R; import com.android.settings.R;
public class PowerUsageDetail extends Activity implements Button.OnClickListener { public class PowerUsageDetail extends Activity implements Button.OnClickListener {
@@ -68,6 +75,8 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
public static final int ACTION_WIRELESS_SETTINGS = 4; public static final int ACTION_WIRELESS_SETTINGS = 4;
public static final int ACTION_APP_DETAILS = 5; public static final int ACTION_APP_DETAILS = 5;
public static final int ACTION_SECURITY_SETTINGS = 6; public static final int ACTION_SECURITY_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_UNPLUGGED = 1;
public static final int USAGE_SINCE_RESET = 2; public static final int USAGE_SINCE_RESET = 2;
@@ -78,6 +87,8 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
public static final String EXTRA_UID = "uid"; public static final String EXTRA_UID = "uid";
public static final String EXTRA_USAGE_SINCE = "since"; public static final String EXTRA_USAGE_SINCE = "since";
public static final String EXTRA_USAGE_DURATION = "duration"; 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_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_DETAIL_VALUES = "values"; // Array of doubles
public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType
@@ -92,6 +103,9 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
private int mUid; private int mUid;
private double[] mValues; private double[] mValues;
private TextView mTitleView; private TextView mTitleView;
private ViewGroup mTwoButtonsPanel;
private Button mForceStopButton;
private Button mReportButton;
private ViewGroup mDetailsParent; private ViewGroup mDetailsParent;
private ViewGroup mControlsParent; private ViewGroup mControlsParent;
private long mStartTime; private long mStartTime;
@@ -105,6 +119,9 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
private static final String TAG = "PowerUsageDetail"; private static final String TAG = "PowerUsageDetail";
private String[] mPackages; private String[] mPackages;
ApplicationInfo mApp;
ComponentName mInstaller;
@Override @Override
protected void onCreate(Bundle icicle) { protected void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
@@ -116,6 +133,7 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
mStartTime = android.os.Process.getElapsedCpuTime(); mStartTime = android.os.Process.getElapsedCpuTime();
checkForceStop();
} }
@Override @Override
@@ -163,6 +181,11 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
((TextView)findViewById(R.id.battery_percentage)) ((TextView)findViewById(R.id.battery_percentage))
.setText(String.format("%d%%", percentage)); .setText(String.format("%d%%", percentage));
mTwoButtonsPanel = (ViewGroup) findViewById(R.id.two_buttons_panel);
mForceStopButton = (Button) findViewById(R.id.left_button);
mReportButton = (Button) findViewById(R.id.right_button);
mForceStopButton.setEnabled(false);
ImageView gaugeImage = (ImageView) findViewById(R.id.gauge); ImageView gaugeImage = (ImageView) findViewById(R.id.gauge);
mGauge = new PercentageBar(); mGauge = new PercentageBar();
mGauge.percent = gaugeValue; mGauge.percent = gaugeValue;
@@ -178,6 +201,34 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
fillDetailsSection(); fillDetailsSection();
fillPackagesSection(mUid); fillPackagesSection(mUid);
fillControlsSection(mUid); fillControlsSection(mUid);
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);
// check if error reporting is enabled in secure settings
int enabled = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.SEND_ACTION_APP_ERROR, 0);
if (enabled != 0) {
if (mPackages != null && mPackages.length > 0) {
try {
mApp = getPackageManager().getApplicationInfo(mPackages[0], 0);
mInstaller = ApplicationErrorReport.getErrorReportReceiver(
this, mPackages[0], mApp.flags);
} catch (NameNotFoundException e) {
}
}
mReportButton.setEnabled(mInstaller != null);
} else {
mTwoButtonsPanel.setVisibility(View.GONE);
}
} else {
mTwoButtonsPanel.setVisibility(View.GONE);
}
} }
public void onClick(View v) { public void onClick(View v) {
@@ -201,12 +252,18 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
case ACTION_APP_DETAILS: case ACTION_APP_DETAILS:
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(this, InstalledAppDetails.class); intent.setClass(this, InstalledAppDetails.class);
intent.putExtra("com.android.settings.ApplicationPkgName", mPackages[0]); intent.putExtra(ManageApplications.APP_PKG_NAME, mPackages[0]);
startActivity(intent); startActivity(intent);
break; break;
case ACTION_SECURITY_SETTINGS: case ACTION_SECURITY_SETTINGS:
startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS)); startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
break; break;
case ACTION_FORCE_STOP:
killProcesses();
break;
case ACTION_REPORT:
reportBatteryUse();
break;
} }
} }
@@ -332,6 +389,60 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
for (int i = 0; i < mPackages.length; i++) { for (int i = 0; i < mPackages.length; i++) {
am.forceStopPackage(mPackages[i]); am.forceStopPackage(mPackages[i]);
} }
checkForceStop();
}
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mForceStopButton.setEnabled(getResultCode() != RESULT_CANCELED);
}
};
private void checkForceStop() {
if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) {
mForceStopButton.setEnabled(false);
return;
}
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);
sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
Activity.RESULT_CANCELED, null, null);
}
private void reportBatteryUse() {
if (mPackages == null) return;
final Intent intent = getIntent();
final int percentage = intent.getIntExtra(EXTRA_PERCENT, 1);
final long duration = intent.getLongExtra(EXTRA_USAGE_DURATION, 0);
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;
StringBuilder builder = new StringBuilder();
builder.append("Application used " + percentage + "% of battery over "
+ Utils.formatElapsedTime(this, duration / 1000));
builder.append('\n');
builder.append(intent.getStringExtra(EXTRA_REPORT_DETAILS));
builder.append('\n');
builder.append("----------------------------------------------");
builder.append('\n');
builder.append(intent.getStringExtra(EXTRA_REPORT_CHECKIN_DETAILS));
builder.append('\n');
report.batteryText = builder.toString();
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) { private void fillPackagesSection(int uid) {
@@ -344,7 +455,7 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
LayoutInflater inflater = getLayoutInflater(); LayoutInflater inflater = getLayoutInflater();
PackageManager pm = getPackageManager(); PackageManager pm = getPackageManager();
final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); //final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
mPackages = pm.getPackagesForUid(uid); mPackages = pm.getPackagesForUid(uid);
if (mPackages == null || mPackages.length < 2) { if (mPackages == null || mPackages.length < 2) {
removePackagesSection(); removePackagesSection();
@@ -356,13 +467,13 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
try { try {
ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0); ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0);
CharSequence label = ai.loadLabel(pm); CharSequence label = ai.loadLabel(pm);
Drawable icon = defaultActivityIcon; //Drawable icon = defaultActivityIcon;
if (label != null) { if (label != null) {
mPackages[i] = label.toString(); mPackages[i] = label.toString();
} }
if (ai.icon != 0) { //if (ai.icon != 0) {
icon = ai.loadIcon(pm); // icon = ai.loadIcon(pm);
} //}
ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item, ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item,
null); null);
packagesParent.addView(item); packagesParent.addView(item);

View File

@@ -48,6 +48,9 @@ import com.android.internal.os.PowerProfile;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.fuelgauge.PowerUsageDetail.DrainType; import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -78,6 +81,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
private static final int MIN_POWER_THRESHOLD = 5; private static final int MIN_POWER_THRESHOLD = 5;
private static final int MAX_ITEMS_TO_LIST = 10; private static final int MAX_ITEMS_TO_LIST = 10;
private long mStatsPeriod = 0;
private double mMaxPower = 1; private double mMaxPower = 1;
private double mTotalPower; private double mTotalPower;
private PowerProfile mPowerProfile; private PowerProfile mPowerProfile;
@@ -132,6 +136,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
Math.ceil(sipper.getSortValue() * 100 / mTotalPower)); Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
intent.putExtra(PowerUsageDetail.EXTRA_GAUGE, (int) intent.putExtra(PowerUsageDetail.EXTRA_GAUGE, (int)
Math.ceil(sipper.getSortValue() * 100 / mMaxPower)); Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
intent.putExtra(PowerUsageDetail.EXTRA_USAGE_DURATION, mStatsPeriod);
intent.putExtra(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName); intent.putExtra(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
intent.putExtra(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId); intent.putExtra(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
intent.putExtra(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent); intent.putExtra(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
@@ -165,6 +170,15 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
0 0
}; };
Writer result = new StringWriter();
PrintWriter printWriter = new PrintWriter(result);
mStats.dumpLocked(printWriter, "", mStatsType, uid.getUid());
intent.putExtra(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
result = new StringWriter();
printWriter = new PrintWriter(result);
mStats.dumpCheckinLocked(printWriter, mStatsType, uid.getUid());
intent.putExtra(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS, result.toString());
} }
break; break;
case CELL: case CELL:
@@ -303,6 +317,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
} }
final double averageCostPerByte = getAverageDataCost(); final double averageCostPerByte = getAverageDataCost();
long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which); long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
mStatsPeriod = uSecTime;
updateStatsPeriod(uSecTime); updateStatsPeriod(uSecTime);
SparseArray<? extends Uid> uidStats = mStats.getUidStats(); SparseArray<? extends Uid> uidStats = mStats.getUidStats();
final int NU = uidStats.size(); final int NU = uidStats.size();