diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-06-11 10:25:54 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-06-11 12:46:21 -0700 |
commit | ea38e678537cf740b5f30c1d69c7a332e98cdd2c (patch) | |
tree | 89abba14dc69839337e71a7f7d43f005eb3cdd4f /src | |
parent | a316d99b346028a6c1eb3b5a184403ef0f55a538 (diff) | |
download | packages_apps_Settings-ea38e678537cf740b5f30c1d69c7a332e98cdd2c.zip packages_apps_Settings-ea38e678537cf740b5f30c1d69c7a332e98cdd2c.tar.gz packages_apps_Settings-ea38e678537cf740b5f30c1d69c7a332e98cdd2c.tar.bz2 |
Show history of battery level.
Also clean up to remove dead code for running services and old
battery usage UI.
Finally some string improvements from Roy.
Change-Id: I8765a4c744b92edd1505f14c47fea57b918e5d7b
Diffstat (limited to 'src')
10 files changed, 539 insertions, 2264 deletions
diff --git a/src/com/android/settings/applications/RunningProcessesViewOld.java b/src/com/android/settings/applications/RunningProcessesViewOld.java deleted file mode 100644 index dc7302c..0000000 --- a/src/com/android/settings/applications/RunningProcessesViewOld.java +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (C) 2010 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.applications; - -import com.android.settings.R; - -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentSender; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.text.format.DateUtils; -import android.text.format.Formatter; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.TextView; - -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - -public class RunningProcessesViewOld extends FrameLayout - implements AdapterView.OnItemClickListener { - - static final String TAG = "RunningServices"; - - /** Maximum number of services to retrieve */ - static final int MAX_SERVICES = 100; - - static final int MSG_UPDATE_TIMES = 1; - static final int MSG_UPDATE_CONTENTS = 2; - static final int MSG_REFRESH_UI = 3; - - static final long TIME_UPDATE_DELAY = 1000; - static final long CONTENTS_UPDATE_DELAY = 2000; - - // Memory pages are 4K. - static final long PAGE_SIZE = 4*1024; - - long SECONDARY_SERVER_MEM; - - final HashMap<View, ActiveItem> mActiveItems = new HashMap<View, ActiveItem>(); - - ActivityManager mAm; - - RunningState mState; - - StringBuilder mBuilder = new StringBuilder(128); - - RunningState.BaseItem mCurSelected; - - int mProcessBgColor; - - ListView mListView; - LinearColorBar mColorBar; - TextView mBackgroundProcessText; - TextView mForegroundProcessText; - - int mLastNumBackgroundProcesses = -1; - int mLastNumForegroundProcesses = -1; - int mLastNumServiceProcesses = -1; - long mLastBackgroundProcessMemory = -1; - long mLastForegroundProcessMemory = -1; - long mLastServiceProcessMemory = -1; - long mLastAvailMemory = -1; - - Dialog mCurDialog; - - byte[] mBuffer = new byte[1024]; - - class ActiveItem { - View mRootView; - RunningState.BaseItem mItem; - ActivityManager.RunningServiceInfo mService; - ViewHolder mHolder; - long mFirstRunTime; - - void updateTime(Context context) { - if (mItem.mIsProcess) { - String size = mItem.mSizeStr != null ? mItem.mSizeStr : ""; - if (!size.equals(mItem.mCurSizeStr)) { - mItem.mCurSizeStr = size; - mHolder.size.setText(size); - } - } else { - if (mItem.mActiveSince >= 0) { - mHolder.size.setText(DateUtils.formatElapsedTime(mBuilder, - (SystemClock.uptimeMillis()-mFirstRunTime)/1000)); - } else { - mHolder.size.setText(context.getResources().getText( - R.string.service_restarting)); - } - } - } - } - - static class ViewHolder { - ImageView separator; - ImageView icon; - TextView name; - TextView description; - TextView size; - } - - static class TimeTicker extends TextView { - public TimeTicker(Context context, AttributeSet attrs) { - super(context, attrs); - } - } - - class ServiceListAdapter extends BaseAdapter { - final RunningState mState; - final LayoutInflater mInflater; - ArrayList<RunningState.BaseItem> mItems; - - ServiceListAdapter(RunningState state) { - mState = state; - mInflater = (LayoutInflater)getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - refreshItems(); - } - - void refreshItems() { - ArrayList<RunningState.BaseItem> newItems = mState.getCurrentItems(); - if (mItems != newItems) { - mItems = newItems; - } - if (mItems == null) { - mItems = new ArrayList<RunningState.BaseItem>(); - } - } - - public boolean hasStableIds() { - return true; - } - - public int getCount() { - return mItems.size(); - } - - public Object getItem(int position) { - return mItems.get(position); - } - - public long getItemId(int position) { - return mItems.get(position).hashCode(); - } - - public boolean areAllItemsEnabled() { - return false; - } - - public boolean isEnabled(int position) { - return !mItems.get(position).mIsProcess; - } - - public View getView(int position, View convertView, ViewGroup parent) { - View v; - if (convertView == null) { - v = newView(parent); - } else { - v = convertView; - } - bindView(v, position); - return v; - } - - public View newView(ViewGroup parent) { - View v = mInflater.inflate(R.layout.running_services_item, parent, false); - ViewHolder h = new ViewHolder(); - h.separator = (ImageView)v.findViewById(R.id.separator); - h.icon = (ImageView)v.findViewById(R.id.icon); - h.name = (TextView)v.findViewById(R.id.name); - h.description = (TextView)v.findViewById(R.id.description); - h.size = (TextView)v.findViewById(R.id.size); - v.setTag(h); - return v; - } - - public void bindView(View view, int position) { - synchronized (mState.mLock) { - ViewHolder vh = (ViewHolder) view.getTag(); - if (position >= mItems.size()) { - // List must have changed since we last reported its - // size... ignore here, we will be doing a data changed - // to refresh the entire list. - return; - } - RunningState.BaseItem item = mItems.get(position); - vh.name.setText(item.mDisplayLabel); - vh.separator.setVisibility(item.mNeedDivider - ? View.VISIBLE : View.INVISIBLE); - ActiveItem ai = new ActiveItem(); - ai.mRootView = view; - ai.mItem = item; - ai.mHolder = vh; - ai.mFirstRunTime = item.mActiveSince; - vh.description.setText(item.mDescription); - if (item.mIsProcess) { - view.setBackgroundColor(mProcessBgColor); - vh.icon.setImageDrawable(null); - vh.icon.setVisibility(View.GONE); - vh.description.setText(item.mDescription); - item.mCurSizeStr = null; - } else { - view.setBackgroundDrawable(null); - vh.icon.setImageDrawable(item.mPackageInfo.loadIcon( - getContext().getPackageManager())); - vh.icon.setVisibility(View.VISIBLE); - vh.description.setText(item.mDescription); - ai.mFirstRunTime = item.mActiveSince; - } - ai.updateTime(getContext()); - mActiveItems.put(view, ai); - } - } - } - - 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); - } - } - } - - HandlerThread mBackgroundThread; - final class BackgroundHandler extends Handler { - public BackgroundHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_CONTENTS: - Message cmd = mHandler.obtainMessage(MSG_REFRESH_UI); - cmd.arg1 = mState.update(getContext(), mAm) ? 1 : 0; - mHandler.sendMessage(cmd); - removeMessages(MSG_UPDATE_CONTENTS); - msg = obtainMessage(MSG_UPDATE_CONTENTS); - sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY); - break; - } - } - }; - - BackgroundHandler mBackgroundHandler; - - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_TIMES: - Iterator<ActiveItem> it = mActiveItems.values().iterator(); - while (it.hasNext()) { - ActiveItem ai = it.next(); - if (ai.mRootView.getWindowToken() == null) { - // Clean out any dead views, just in case. - it.remove(); - continue; - } - ai.updateTime(getContext()); - } - removeMessages(MSG_UPDATE_TIMES); - msg = obtainMessage(MSG_UPDATE_TIMES); - sendMessageDelayed(msg, TIME_UPDATE_DELAY); - break; - case MSG_REFRESH_UI: - refreshUi(msg.arg1 != 0); - break; - } - } - }; - - private boolean matchText(byte[] buffer, int index, String text) { - int N = text.length(); - if ((index+N) >= buffer.length) { - return false; - } - for (int i=0; i<N; i++) { - if (buffer[index+i] != text.charAt(i)) { - return false; - } - } - return true; - } - - private long extractMemValue(byte[] buffer, int index) { - while (index < buffer.length && buffer[index] != '\n') { - if (buffer[index] >= '0' && buffer[index] <= '9') { - int start = index; - index++; - while (index < buffer.length && buffer[index] >= '0' - && buffer[index] <= '9') { - index++; - } - String str = new String(buffer, 0, start, index-start); - return ((long)Integer.parseInt(str)) * 1024; - } - index++; - } - return 0; - } - - private long readAvailMem() { - try { - long memFree = 0; - long memCached = 0; - FileInputStream is = new FileInputStream("/proc/meminfo"); - int len = is.read(mBuffer); - is.close(); - final int BUFLEN = mBuffer.length; - for (int i=0; i<len && (memFree == 0 || memCached == 0); i++) { - if (matchText(mBuffer, i, "MemFree")) { - i += 7; - memFree = extractMemValue(mBuffer, i); - } else if (matchText(mBuffer, i, "Cached")) { - i += 6; - memCached = extractMemValue(mBuffer, i); - } - while (i < BUFLEN && mBuffer[i] != '\n') { - i++; - } - } - return memFree + memCached; - } catch (java.io.FileNotFoundException e) { - } catch (java.io.IOException e) { - } - return 0; - } - - - void refreshUi(boolean dataChanged) { - if (dataChanged) { - ServiceListAdapter adapter = (ServiceListAdapter)(mListView.getAdapter()); - adapter.refreshItems(); - adapter.notifyDataSetChanged(); - } - - // This is the amount of available memory until we start killing - // background services. - long availMem = readAvailMem() - SECONDARY_SERVER_MEM; - if (availMem < 0) { - availMem = 0; - } - - synchronized (mState.mLock) { - if (mLastNumBackgroundProcesses != mState.mNumBackgroundProcesses - || mLastBackgroundProcessMemory != mState.mBackgroundProcessMemory - || mLastAvailMemory != availMem) { - mLastNumBackgroundProcesses = mState.mNumBackgroundProcesses; - mLastBackgroundProcessMemory = mState.mBackgroundProcessMemory; - mLastAvailMemory = availMem; - String sizeStr = Formatter.formatShortFileSize(getContext(), - mLastAvailMemory + mLastBackgroundProcessMemory); - mBackgroundProcessText.setText(getResources().getString( - R.string.service_background_processes, sizeStr)); - } - if (mLastNumForegroundProcesses != mState.mNumForegroundProcesses - || mLastForegroundProcessMemory != mState.mForegroundProcessMemory) { - mLastNumForegroundProcesses = mState.mNumForegroundProcesses; - mLastForegroundProcessMemory = mState.mForegroundProcessMemory; - String sizeStr = Formatter.formatShortFileSize(getContext(), - mLastForegroundProcessMemory); - mForegroundProcessText.setText(getResources().getString( - R.string.service_foreground_processes, sizeStr)); - } - mLastNumServiceProcesses = mState.mNumServiceProcesses; - mLastServiceProcessMemory = mState.mServiceProcessMemory; - - float totalMem = availMem + mLastBackgroundProcessMemory - + mLastForegroundProcessMemory + mLastServiceProcessMemory; - mColorBar.setRatios(mLastForegroundProcessMemory/totalMem, - mLastServiceProcessMemory/totalMem, - (availMem+mLastBackgroundProcessMemory)/totalMem); - } - } - - public void onItemClick(AdapterView<?> parent, View v, int position, long id) { - ListView l = (ListView)parent; - RunningState.BaseItem bi = (RunningState.BaseItem)l.getAdapter().getItem(position); - mCurSelected = bi; - } - - public void onMovedToScrapHeap(View view) { - mActiveItems.remove(view); - } - - public RunningProcessesViewOld(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void doCreate(Bundle savedInstanceState, Object nonConfigurationInstace) { - mAm = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE); - mState = (RunningState)nonConfigurationInstace; - if (mState == null) { - mState = new RunningState(); - } - mProcessBgColor = 0xff505050; - LayoutInflater inflater = (LayoutInflater)getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.running_processes_view, this); - mListView = (ListView)findViewById(android.R.id.list); - View emptyView = findViewById(com.android.internal.R.id.empty); - if (emptyView != null) { - mListView.setEmptyView(emptyView); - } - mListView.setOnItemClickListener(this); - mListView.setDivider(null); - mListView.setAdapter(new ServiceListAdapter(mState)); - mColorBar = (LinearColorBar)findViewById(R.id.color_bar); - mBackgroundProcessText = (TextView)findViewById(R.id.backgroundText); - mForegroundProcessText = (TextView)findViewById(R.id.foregroundText); - - // Magic! Implementation detail! Don't count on this! - SECONDARY_SERVER_MEM = - Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE; - } - - public void doPause() { - mHandler.removeMessages(MSG_UPDATE_TIMES); - if (mBackgroundThread != null) { - mBackgroundThread.quit(); - mBackgroundThread = null; - mBackgroundHandler = null; - } - } - - public void doResume() { - refreshUi(mState.update(getContext(), mAm)); - mBackgroundThread = new HandlerThread("RunningServices"); - mBackgroundThread.start(); - mBackgroundHandler = new BackgroundHandler(mBackgroundThread.getLooper()); - mHandler.removeMessages(MSG_UPDATE_TIMES); - Message msg = mHandler.obtainMessage(MSG_UPDATE_TIMES); - mHandler.sendMessageDelayed(msg, TIME_UPDATE_DELAY); - mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS); - msg = mBackgroundHandler.obtainMessage(MSG_UPDATE_CONTENTS); - mBackgroundHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY); - } - - public Object doRetainNonConfigurationInstance() { - return mState; - } -} diff --git a/src/com/android/settings/applications/RunningServices.java b/src/com/android/settings/applications/RunningServices.java deleted file mode 100644 index 703e8c7..0000000 --- a/src/com/android/settings/applications/RunningServices.java +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (C) 2006 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.applications; - -import com.android.settings.R; - -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.ListActivity; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentSender; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.text.format.DateUtils; -import android.text.format.Formatter; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.TextView; - -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - -public class RunningServices extends ListActivity - implements AbsListView.RecyclerListener, - DialogInterface.OnClickListener { - static final String TAG = "RunningServices"; - - /** Maximum number of services to retrieve */ - static final int MAX_SERVICES = 100; - - static final int MSG_UPDATE_TIMES = 1; - static final int MSG_UPDATE_CONTENTS = 2; - static final int MSG_REFRESH_UI = 3; - - static final long TIME_UPDATE_DELAY = 1000; - static final long CONTENTS_UPDATE_DELAY = 2000; - - // Memory pages are 4K. - static final long PAGE_SIZE = 4*1024; - - long SECONDARY_SERVER_MEM; - - final HashMap<View, ActiveItem> mActiveItems = new HashMap<View, ActiveItem>(); - - ActivityManager mAm; - - RunningState mState; - - StringBuilder mBuilder = new StringBuilder(128); - - RunningState.BaseItem mCurSelected; - - int mProcessBgColor; - - LinearColorBar mColorBar; - TextView mBackgroundProcessText; - TextView mForegroundProcessText; - - int mLastNumBackgroundProcesses = -1; - int mLastNumForegroundProcesses = -1; - int mLastNumServiceProcesses = -1; - long mLastBackgroundProcessMemory = -1; - long mLastForegroundProcessMemory = -1; - long mLastServiceProcessMemory = -1; - long mLastAvailMemory = -1; - - Dialog mCurDialog; - - byte[] mBuffer = new byte[1024]; - - class ActiveItem { - View mRootView; - RunningState.BaseItem mItem; - ActivityManager.RunningServiceInfo mService; - ViewHolder mHolder; - long mFirstRunTime; - - void updateTime(Context context) { - if (mItem.mIsProcess) { - String size = mItem.mSizeStr != null ? mItem.mSizeStr : ""; - if (!size.equals(mItem.mCurSizeStr)) { - mItem.mCurSizeStr = size; - mHolder.size.setText(size); - } - } else { - if (mItem.mActiveSince >= 0) { - mHolder.size.setText(DateUtils.formatElapsedTime(mBuilder, - (SystemClock.uptimeMillis()-mFirstRunTime)/1000)); - } else { - mHolder.size.setText(context.getResources().getText( - R.string.service_restarting)); - } - } - } - } - - static class ViewHolder { - ImageView separator; - ImageView icon; - TextView name; - TextView description; - TextView size; - } - - static class TimeTicker extends TextView { - public TimeTicker(Context context, AttributeSet attrs) { - super(context, attrs); - } - } - - class ServiceListAdapter extends BaseAdapter { - final RunningState mState; - final LayoutInflater mInflater; - ArrayList<RunningState.BaseItem> mItems; - - ServiceListAdapter(RunningState state) { - mState = state; - mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); - refreshItems(); - } - - void refreshItems() { - ArrayList<RunningState.BaseItem> newItems = mState.getCurrentItems(); - if (mItems != newItems) { - mItems = newItems; - } - if (mItems == null) { - mItems = new ArrayList<RunningState.BaseItem>(); - } - } - - public boolean hasStableIds() { - return true; - } - - public int getCount() { - return mItems.size(); - } - - public Object getItem(int position) { - return mItems.get(position); - } - - public long getItemId(int position) { - return mItems.get(position).hashCode(); - } - - public boolean areAllItemsEnabled() { - return false; - } - - public boolean isEnabled(int position) { - return !mItems.get(position).mIsProcess; - } - - public View getView(int position, View convertView, ViewGroup parent) { - View v; - if (convertView == null) { - v = newView(parent); - } else { - v = convertView; - } - bindView(v, position); - return v; - } - - public View newView(ViewGroup parent) { - View v = mInflater.inflate(R.layout.running_services_item, parent, false); - ViewHolder h = new ViewHolder(); - h.separator = (ImageView)v.findViewById(R.id.separator); - h.icon = (ImageView)v.findViewById(R.id.icon); - h.name = (TextView)v.findViewById(R.id.name); - h.description = (TextView)v.findViewById(R.id.description); - h.size = (TextView)v.findViewById(R.id.size); - v.setTag(h); - return v; - } - - public void bindView(View view, int position) { - synchronized (mState.mLock) { - ViewHolder vh = (ViewHolder) view.getTag(); - if (position >= mItems.size()) { - // List must have changed since we last reported its - // size... ignore here, we will be doing a data changed - // to refresh the entire list. - return; - } - RunningState.BaseItem item = mItems.get(position); - vh.name.setText(item.mDisplayLabel); - vh.separator.setVisibility(item.mNeedDivider - ? View.VISIBLE : View.INVISIBLE); - ActiveItem ai = new ActiveItem(); - ai.mRootView = view; - ai.mItem = item; - ai.mHolder = vh; - ai.mFirstRunTime = item.mActiveSince; - vh.description.setText(item.mDescription); - if (item.mIsProcess) { - view.setBackgroundColor(mProcessBgColor); - vh.icon.setImageDrawable(null); - vh.icon.setVisibility(View.GONE); - vh.description.setText(item.mDescription); - item.mCurSizeStr = null; - } else { - view.setBackgroundDrawable(null); - vh.icon.setImageDrawable(item.mPackageInfo.loadIcon(getPackageManager())); - vh.icon.setVisibility(View.VISIBLE); - vh.description.setText(item.mDescription); - ai.mFirstRunTime = item.mActiveSince; - } - ai.updateTime(RunningServices.this); - mActiveItems.put(view, ai); - } - } - } - - 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); - } - } - } - - HandlerThread mBackgroundThread; - final class BackgroundHandler extends Handler { - public BackgroundHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_CONTENTS: - Message cmd = mHandler.obtainMessage(MSG_REFRESH_UI); - cmd.arg1 = mState.update(RunningServices.this, mAm) ? 1 : 0; - mHandler.sendMessage(cmd); - removeMessages(MSG_UPDATE_CONTENTS); - msg = obtainMessage(MSG_UPDATE_CONTENTS); - sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY); - break; - } - } - }; - - BackgroundHandler mBackgroundHandler; - - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_TIMES: - Iterator<ActiveItem> it = mActiveItems.values().iterator(); - while (it.hasNext()) { - ActiveItem ai = it.next(); - if (ai.mRootView.getWindowToken() == null) { - // Clean out any dead views, just in case. - it.remove(); - continue; - } - ai.updateTime(RunningServices.this); - } - removeMessages(MSG_UPDATE_TIMES); - msg = obtainMessage(MSG_UPDATE_TIMES); - sendMessageDelayed(msg, TIME_UPDATE_DELAY); - break; - case MSG_REFRESH_UI: - refreshUi(msg.arg1 != 0); - break; - } - } - }; - - private boolean matchText(byte[] buffer, int index, String text) { - int N = text.length(); - if ((index+N) >= buffer.length) { - return false; - } - for (int i=0; i<N; i++) { - if (buffer[index+i] != text.charAt(i)) { - return false; - } - } - return true; - } - - private long extractMemValue(byte[] buffer, int index) { - while (index < buffer.length && buffer[index] != '\n') { - if (buffer[index] >= '0' && buffer[index] <= '9') { - int start = index; - index++; - while (index < buffer.length && buffer[index] >= '0' - && buffer[index] <= '9') { - index++; - } - String str = new String(buffer, 0, start, index-start); - return ((long)Integer.parseInt(str)) * 1024; - } - index++; - } - return 0; - } - - private long readAvailMem() { - try { - long memFree = 0; - long memCached = 0; - FileInputStream is = new FileInputStream("/proc/meminfo"); - int len = is.read(mBuffer); - is.close(); - final int BUFLEN = mBuffer.length; - for (int i=0; i<len && (memFree == 0 || memCached == 0); i++) { - if (matchText(mBuffer, i, "MemFree")) { - i += 7; - memFree = extractMemValue(mBuffer, i); - } else if (matchText(mBuffer, i, "Cached")) { - i += 6; - memCached = extractMemValue(mBuffer, i); - } - while (i < BUFLEN && mBuffer[i] != '\n') { - i++; - } - } - return memFree + memCached; - } catch (java.io.FileNotFoundException e) { - } catch (java.io.IOException e) { - } - return 0; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mAm = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); - mState = (RunningState)getLastNonConfigurationInstance(); - if (mState == null) { - mState = new RunningState(); - } - mProcessBgColor = 0xff505050; - setContentView(R.layout.running_services); - getListView().setDivider(null); - getListView().setAdapter(new ServiceListAdapter(mState)); - mColorBar = (LinearColorBar)findViewById(R.id.color_bar); - mBackgroundProcessText = (TextView)findViewById(R.id.backgroundText); - mForegroundProcessText = (TextView)findViewById(R.id.foregroundText); - - // Magic! Implementation detail! Don't count on this! - SECONDARY_SERVER_MEM = - Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE; - } - - void refreshUi(boolean dataChanged) { - if (dataChanged) { - ServiceListAdapter adapter = (ServiceListAdapter)(getListView().getAdapter()); - adapter.refreshItems(); - adapter.notifyDataSetChanged(); - } - - // This is the amount of available memory until we start killing - // background services. - long availMem = readAvailMem() - SECONDARY_SERVER_MEM; - if (availMem < 0) { - availMem = 0; - } - - synchronized (mState.mLock) { - if (mLastNumBackgroundProcesses != mState.mNumBackgroundProcesses - || mLastBackgroundProcessMemory != mState.mBackgroundProcessMemory - || mLastAvailMemory != availMem) { - mLastNumBackgroundProcesses = mState.mNumBackgroundProcesses; - mLastBackgroundProcessMemory = mState.mBackgroundProcessMemory; - mLastAvailMemory = availMem; - String availStr = availMem != 0 - ? Formatter.formatShortFileSize(this, availMem) : "0"; - String sizeStr = Formatter.formatShortFileSize(this, mLastBackgroundProcessMemory); - mBackgroundProcessText.setText(getResources().getString( - R.string.service_background_processes, - mLastNumBackgroundProcesses, availStr, sizeStr)); - } - if (mLastNumForegroundProcesses != mState.mNumForegroundProcesses - || mLastForegroundProcessMemory != mState.mForegroundProcessMemory) { - mLastNumForegroundProcesses = mState.mNumForegroundProcesses; - mLastForegroundProcessMemory = mState.mForegroundProcessMemory; - String sizeStr = Formatter.formatShortFileSize(this, mLastForegroundProcessMemory); - mForegroundProcessText.setText(getResources().getString( - R.string.service_foreground_processes, mLastNumForegroundProcesses, sizeStr)); - } - mLastNumServiceProcesses = mState.mNumServiceProcesses; - mLastServiceProcessMemory = mState.mServiceProcessMemory; - - float totalMem = availMem + mLastBackgroundProcessMemory - + mLastForegroundProcessMemory + mLastServiceProcessMemory; - mColorBar.setRatios(mLastForegroundProcessMemory/totalMem, - mLastServiceProcessMemory/totalMem, - (availMem+mLastBackgroundProcessMemory)/totalMem); - } - } - - @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - RunningState.BaseItem bi = (RunningState.BaseItem)l.getAdapter().getItem(position); - if (!bi.mIsProcess) { - RunningState.ServiceItem si = (RunningState.ServiceItem)bi; - if (si.mRunningService.clientLabel != 0) { - mCurSelected = null; - PendingIntent pi = mAm.getRunningServiceControlPanel( - si.mRunningService.service); - if (pi != null) { - try { - this.startIntentSender(pi.getIntentSender(), null, - Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, - Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, 0); - } catch (IntentSender.SendIntentException e) { - Log.w(TAG, e); - } catch (IllegalArgumentException e) { - Log.w(TAG, e); - } catch (ActivityNotFoundException e) { - Log.w(TAG, e); - } - } - } else { - mCurSelected = bi; - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.confirm_stop_service); - String msg = getResources().getString( - R.string.confirm_stop_service_msg, - si.mPackageInfo.loadLabel(getPackageManager())); - builder.setMessage(msg); - builder.setPositiveButton(R.string.confirm_stop_stop, this); - builder.setNegativeButton(R.string.confirm_stop_cancel, null); - builder.setCancelable(true); - mCurDialog = builder.show(); - } - } else { - mCurSelected = null; - } - } - - public void onClick(DialogInterface dialog, int which) { - if (mCurSelected != null) { - stopService(new Intent().setComponent( - ((RunningState.ServiceItem)mCurSelected).mRunningService.service)); - if (mBackgroundHandler != null) { - mBackgroundHandler.sendEmptyMessage(MSG_UPDATE_CONTENTS); - } - } - } - - @Override - protected void onPause() { - super.onPause(); - mHandler.removeMessages(MSG_UPDATE_TIMES); - if (mBackgroundThread != null) { - mBackgroundThread.quit(); - mBackgroundThread = null; - mBackgroundHandler = null; - } - } - - @Override - protected void onResume() { - super.onResume(); - refreshUi(mState.update(this, mAm)); - mBackgroundThread = new HandlerThread("RunningServices"); - mBackgroundThread.start(); - mBackgroundHandler = new BackgroundHandler(mBackgroundThread.getLooper()); - mHandler.removeMessages(MSG_UPDATE_TIMES); - Message msg = mHandler.obtainMessage(MSG_UPDATE_TIMES); - mHandler.sendMessageDelayed(msg, TIME_UPDATE_DELAY); - mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS); - msg = mBackgroundHandler.obtainMessage(MSG_UPDATE_CONTENTS); - mBackgroundHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY); - } - - @Override - public Object onRetainNonConfigurationInstance() { - return mState; - } - - public void onMovedToScrapHeap(View view) { - mActiveItems.remove(view); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (mCurDialog != null) { - mCurDialog.dismiss(); - } - } -} diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java index 11b40be..2b51421 100644 --- a/src/com/android/settings/applications/RunningState.java +++ b/src/com/android/settings/applications/RunningState.java @@ -418,7 +418,7 @@ public class RunningState { boolean changed = false; List<ActivityManager.RunningServiceInfo> services - = am.getRunningServices(RunningServices.MAX_SERVICES); + = am.getRunningServices(RunningProcessesView.MAX_SERVICES); final int NS = services != null ? services.size() : 0; for (int i=0; i<NS; i++) { ActivityManager.RunningServiceInfo si = services.get(i); @@ -671,7 +671,7 @@ public class RunningState { numForegroundProcesses++; mAllProcessItems.add(proc); } else { - Log.i(RunningServices.TAG, "Unknown non-service process: " + Log.i("RunningState", "Unknown non-service process: " + proc.mProcessName + " #" + proc.mPid); } } else { diff --git a/src/com/android/settings/battery_history/BatteryHistory.java b/src/com/android/settings/battery_history/BatteryHistory.java deleted file mode 100644 index 06f38ae..0000000 --- a/src/com/android/settings/battery_history/BatteryHistory.java +++ /dev/null @@ -1,916 +0,0 @@ -/* - * Copyright (C) 2006 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.battery_history; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Formatter; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import com.android.internal.app.IBatteryStats; -import com.android.settings.R; - -import android.app.Activity; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.BatteryStats; -import android.os.Bundle; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.BatteryStats.Timer; -import android.os.BatteryStats.Uid; -import android.util.Log; -import android.util.LogPrinter; -import android.util.SparseArray; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.AdapterView.OnItemSelectedListener; - -public class BatteryHistory extends Activity implements OnClickListener, OnItemSelectedListener { - private static final String TAG = "BatteryHistory"; - - private static final int SECONDS_PER_MINUTE = 60; - private static final int SECONDS_PER_HOUR = 60 * 60; - private static final int SECONDS_PER_DAY = 24 * 60 * 60; - - // Must be in sync with the values in res/values/array.xml (id battery_history_type_spinner) - private static final int CPU_USAGE = 0; - private static final int NETWORK_USAGE = 1; - private static final int GPS_USAGE = 2; - private static final int SENSOR_USAGE = 3; - private static final int WAKELOCK_USAGE = 4; - private static final int MISC_USAGE = 5; - - // Must be in sync with the values in res/values/array.xml (id battery_history_which_spinner) - private static final int UNPLUGGED = 0; - private static final int CURRENT = 1; - private static final int TOTAL = 2; - - private BatteryStats mStats; - private int mWhich = BatteryStats.STATS_UNPLUGGED; - private int mType = MISC_USAGE; - - private GraphableButton[] mButtons; - IBatteryStats mBatteryInfo; - - private List<CpuUsage> mCpuUsage = new ArrayList<CpuUsage>(); - private List<NetworkUsage> mNetworkUsage = new ArrayList<NetworkUsage>(); - private List<SensorUsage> mSensorUsage = new ArrayList<SensorUsage>(); - private List<SensorUsage> mGpsUsage = new ArrayList<SensorUsage>(); - private List<WakelockUsage> mWakelockUsage = new ArrayList<WakelockUsage>(); - private List<MiscUsage> mMiscUsage = new ArrayList<MiscUsage>(); - - private boolean mHaveCpuUsage, mHaveNetworkUsage, mHaveSensorUsage, - mHaveWakelockUsage, mHaveMiscUsage; - - private LinearLayout mGraphLayout; - private LinearLayout mTextLayout; - private TextView mMessageText; - private TextView mDetailsText; - private Button mDetailsBackButton; - private Spinner mTypeSpinner; - private Spinner mWhichSpinner; - - private boolean mDetailsShown = false; - - private static String getLabel(String packageName, PackageManager pm) { - try { - ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - CharSequence label = ai.loadLabel(pm); - if (label != null) { - return label.toString(); - } - } catch (NameNotFoundException e) { - return packageName; - } - - return ""; - } - - void formatTime(double millis, StringBuilder sb) { - int seconds = (int) Math.floor(millis / 1000); - - int days = 0, hours = 0, minutes = 0; - if (seconds > SECONDS_PER_DAY) { - days = seconds / SECONDS_PER_DAY; - seconds -= days * SECONDS_PER_DAY; - } - if (seconds > SECONDS_PER_HOUR) { - hours = seconds / SECONDS_PER_HOUR; - seconds -= hours * SECONDS_PER_HOUR; - } - if (seconds > SECONDS_PER_MINUTE) { - minutes = seconds / SECONDS_PER_MINUTE; - seconds -= minutes * SECONDS_PER_MINUTE; - } - if (days > 0) { - sb.append(getString(R.string.battery_history_days, days, hours, minutes, seconds)); - } else if (hours > 0) { - sb.append(getString(R.string.battery_history_hours, hours, minutes, seconds)); - } else if (minutes > 0) { - sb.append(getString(R.string.battery_history_minutes, minutes, seconds)); - } else { - sb.append(getString(R.string.battery_history_seconds, seconds)); - } - } - - abstract class Graphable implements Comparable<Graphable> { - protected String mName; - protected String mNamePackage; - protected boolean mUniqueName; - protected String[] mPackages; - protected String[] mPackageNames; - - public abstract String getLabel(); - public abstract double getSortValue(); - public abstract double[] getValues(); - public abstract void getInfo(StringBuilder info); - - public double getMaxValue() { - return -Double.MAX_VALUE; - } - - public int compareTo(Graphable o) { - double t = getSortValue(); - double ot = o.getSortValue(); - if (t < ot) { - // Largest first - return 1; - } else if (t > ot) { - return -1; - } else { - return 0; - } - } - - // Side effects: sets mName and mUniqueName - void getNameForUid(int uid) { - PackageManager pm = getPackageManager(); - mPackages = pm.getPackagesForUid(uid); - if (mPackages == null) { - mName = Integer.toString(uid); - mNamePackage = null; - return; - } - - mPackageNames = new String[mPackages.length]; - System.arraycopy(mPackages, 0, mPackageNames, 0, mPackages.length); - - // Convert package names to user-facing labels where possible - for (int i = 0; i < mPackageNames.length; i++) { - mPackageNames[i] = BatteryHistory.getLabel(mPackageNames[i], pm); - } - - if (mPackageNames.length == 1) { - mNamePackage = mPackages[0]; - mName = mPackageNames[0]; - mUniqueName = true; - } else { - mName = getString(R.string.battery_history_uid, uid); // Default name - // Look for an official name for this UID. - for (String name : mPackages) { - try { - PackageInfo pi = pm.getPackageInfo(name, 0); - if (pi.sharedUserLabel != 0) { - CharSequence nm = pm.getText(name, - pi.sharedUserLabel, pi.applicationInfo); - if (nm != null) { - mName = nm.toString(); - break; - } - } - } catch (PackageManager.NameNotFoundException e) { - } - } - } - } - } - - class CpuUsage extends Graphable { - String mProcess; - double[] mUsage; - double mTotalRuntime; - long mStarts; - - public CpuUsage(int uid, String process, long userTime, long systemTime, - long starts, long totalRuntime) { - getNameForUid(uid); - mProcess = process; - PackageManager pm = BatteryHistory.this.getPackageManager(); - mName = BatteryHistory.getLabel(process, pm); - mUsage = new double[2]; - - mUsage[0] = userTime; - mUsage[1] = userTime + systemTime; - mTotalRuntime = totalRuntime; - mStarts = starts; - } - - public String getLabel() { - return mName; - } - - public double getSortValue() { - return mUsage[1]; - } - - public double[] getValues() { - return mUsage; - } - - public double getMaxValue() { - return mTotalRuntime; - } - - public void getInfo(StringBuilder info) { - info.append(getString(R.string.battery_history_cpu_usage, mProcess)); - info.append("\n\n"); - info.append(getString(R.string.battery_history_user_time)); - formatTime(mUsage[0] * 10, info); - info.append('\n'); - info.append(getString(R.string.battery_history_system_time)); - formatTime((mUsage[1] - mUsage[0]) * 10, info); - info.append('\n'); - info.append(getString(R.string.battery_history_total_time)); - formatTime((mUsage[1]) * 10, info); - info.append('\n'); - info.append(getString(R.string.battery_history_starts, mStarts)); - } - } - - class NetworkUsage extends Graphable { - double[] mUsage; - - public NetworkUsage(int uid, long received, long sent) { - getNameForUid(uid); - - mUsage = new double[2]; - mUsage[0] = received; - mUsage[1] = received + sent; - } - - public String getLabel() { - return mName; - } - - public double getSortValue() { - return mUsage[1]; - } - - public double[] getValues() { - return mUsage; - } - - public void getInfo(StringBuilder info) { - info.append(getString(R.string.battery_history_network_usage, mName)); - info.append("\n\n"); - info.append(getString(R.string.battery_history_bytes_received, (long) mUsage[0])); - info.append('\n'); - info.append(getString(R.string.battery_history_bytes_sent, - (long) mUsage[1] - (long) mUsage[0])); - info.append('\n'); - info.append(getString(R.string.battery_history_bytes_total, (long) mUsage[1])); - - if (!mUniqueName) { - info.append("\n\n"); - info.append(getString(R.string.battery_history_packages_sharing_this_uid)); - info.append('\n'); - - PackageManager pm = BatteryHistory.this.getPackageManager(); - List<String> names = new ArrayList<String>(); - for (String name : mPackageNames) { - names.add(BatteryHistory.getLabel(name, pm)); - } - Collections.sort(names); - for (String name : names) { - info.append(" "); - info.append(name); - info.append('\n'); - } - } - } - } - - class SensorUsage extends Graphable { - double[] mUsage; - double mTotalRealtime; - int mCount; - - public SensorUsage(int uid, long time, int count, long totalRealtime) { - getNameForUid(uid); - - mUsage = new double[1]; - mUsage[0] = time; - mTotalRealtime = totalRealtime; - - mCount = count; - } - - public String getLabel() { - return mName; - } - - public double getSortValue() { - return mUsage[0]; - } - - public double[] getValues() { - return mUsage; - } - - public double getMaxValue() { - return mTotalRealtime; - } - - public void getInfo(StringBuilder info) { - info.append(getString(R.string.battery_history_sensor)); - info.append(mName); - info.append("\n\n"); - info.append(getString(R.string.battery_history_total_time)); - formatTime(mUsage[0], info); - info.append("\n\n"); - } - } - - - class WakelockUsage extends Graphable { - double[] mUsage; - double mTotalRealtime; - int mCount; - - public WakelockUsage(int uid, long time, int count, long totalRealtime) { - getNameForUid(uid); - - mUsage = new double[1]; - mUsage[0] = time; - mTotalRealtime = totalRealtime; - - mCount = count; - } - - public String getLabel() { - return mName; - } - - public double getSortValue() { - return mUsage[0]; - } - - public double[] getValues() { - return mUsage; - } - - public double getMaxValue() { - return mTotalRealtime; - } - - public void getInfo(StringBuilder info) { - info.append(getString(R.string.battery_history_wakelock)); - info.append(mName); - info.append("\n\n"); - info.append(getString(R.string.battery_history_total_time)); - formatTime(mUsage[0], info); - info.append("\n\n"); - } - } - - class MiscUsage extends Graphable { - int mInfoLabelRes; - String mInfoLabel; - double[] mUsage; - double mTotalRealtime; - - public MiscUsage(String name, int infoLabelRes, long value, - long totalRealtime) { - mName = name; - - mInfoLabelRes = infoLabelRes; - - mUsage = new double[2]; - mUsage[0] = value; - mTotalRealtime = totalRealtime; - } - - public MiscUsage(String name, String infoLabel, long value, - long totalRealtime) { - mName = name; - - mInfoLabel = infoLabel; - - mUsage = new double[2]; - mUsage[0] = value; - mTotalRealtime = totalRealtime; - } - - public String getLabel() { - return mName; - } - - public double getSortValue() { - return mUsage[1]; - } - - public double[] getValues() { - return mUsage; - } - - public double getMaxValue() { - return mTotalRealtime; - } - - public void getInfo(StringBuilder info) { - info.append(mInfoLabel != null ? mInfoLabel : getString(mInfoLabelRes)); - info.append(' '); - formatTime(mUsage[0], info); - info.append(" ("); - info.append((mUsage[0]*100)/mTotalRealtime); - info.append("%)"); - } - } - - private List<? extends Graphable> getGraphRecords() { - switch (mType) { - case CPU_USAGE: return mCpuUsage; - case NETWORK_USAGE : return mNetworkUsage; - case SENSOR_USAGE: return mSensorUsage; - case GPS_USAGE: return mGpsUsage; - case WAKELOCK_USAGE: return mWakelockUsage; - case MISC_USAGE: return mMiscUsage; - default: - return (List<? extends Graphable>) null; // TODO - } - } - - private void displayGraph() { - Log.i(TAG, "displayGraph"); - - collectStatistics(); - - // Hide the UI and selectively enable it below - mMessageText.setVisibility(View.GONE); - for (int i = 0; i < mButtons.length; i++) { - mButtons[i].setVisibility(View.INVISIBLE); - } - - double maxValue = -Double.MAX_VALUE; - - List<? extends Graphable> records = getGraphRecords(); - for (Graphable g : records) { - double[] values = g.getValues(); - maxValue = Math.max(maxValue, values[values.length - 1]); - maxValue = Math.max(maxValue, g.getMaxValue()); - } - - int[] colors = new int[2]; - colors[0] = 0xff0000ff; - colors[1] = 0xffff0000; - - for (int i = 0; i < mButtons.length; i++) { - mButtons[i].setVisibility(View.INVISIBLE); - } - - int numRecords = Math.min(records.size(), mButtons.length); - if (numRecords == 0) { - mMessageText.setVisibility(View.VISIBLE); - mMessageText.setText(R.string.battery_history_no_data); - } else { - for (int i = 0; i < numRecords; i++) { - Graphable r = records.get(i); - - mButtons[i].setText(r.getLabel()); - mButtons[i].setValues(r.getValues(), maxValue); - mButtons[i].setVisibility(View.VISIBLE); - } - } - } - - private void hideDetails() { - mTextLayout.setVisibility(View.GONE); - mGraphLayout.setVisibility(View.VISIBLE); - mDetailsShown = false; - } - - private void showDetails(int id) { - mGraphLayout.setVisibility(View.GONE); - mTextLayout.setVisibility(View.VISIBLE); - - StringBuilder info = new StringBuilder(); - List<? extends Graphable> records = getGraphRecords(); - if (id < records.size()) { - Graphable record = records.get(id); - record.getInfo(info); - } else { - info.append(getString(R.string.battery_history_details_for, id)); - } - mDetailsText.setText(info.toString()); - mDetailsShown = true; - } - - private void processCpuUsage() { - mCpuUsage.clear(); - - long uSecTime = SystemClock.uptimeMillis() * 1000; - final long uSecNow = mStats.computeBatteryUptime(uSecTime, mWhich) / 1000; - - SparseArray<? extends Uid> uidStats = mStats.getUidStats(); - final int NU = uidStats.size(); - for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - - Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); - if (processStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent - : processStats.entrySet()) { - - Uid.Proc ps = ent.getValue(); - long userTime = ps.getUserTime(mWhich); - long systemTime = ps.getSystemTime(mWhich); - long starts = ps.getStarts(mWhich); - - if (userTime != 0 || systemTime != 0) { - mCpuUsage.add(new CpuUsage(u.getUid(), ent.getKey(), - userTime, systemTime, starts, uSecNow)); - } - } - } - } - Collections.sort(mCpuUsage); - } - - private void processNetworkUsage() { - mNetworkUsage.clear(); - - SparseArray<? extends Uid> uidStats = mStats.getUidStats(); - final int NU = uidStats.size(); - for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - - long received = u.getTcpBytesReceived(mWhich); - long sent = u.getTcpBytesSent(mWhich); - if (received + sent > 0) { - mNetworkUsage.add(new NetworkUsage(u.getUid(), received, sent)); - } - } - Collections.sort(mNetworkUsage); - } - - private void processSensorUsage() { - mGpsUsage.clear(); - mSensorUsage.clear(); - - long uSecTime = SystemClock.elapsedRealtime() * 1000; - final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000; - - SparseArray<? extends Uid> uidStats = mStats.getUidStats(); - final int NU = uidStats.size(); - for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - int uid = u.getUid(); - - Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); - long timeGps = 0; - int countGps = 0; - long timeOther = 0; - int countOther = 0; - if (sensorStats.size() > 0) { - for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent - : sensorStats.entrySet()) { - - Uid.Sensor se = ent.getValue(); - int handle = se.getHandle(); - Timer timer = se.getSensorTime(); - if (timer != null) { - // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(uSecNow, mWhich) + 500) / 1000; - int count = timer.getCountLocked(mWhich); - if (handle == BatteryStats.Uid.Sensor.GPS) { - timeGps += totalTime; - countGps += count; - } else { - timeOther += totalTime; - countOther += count; - } - } - } - } - - if (timeGps > 0) { - mGpsUsage.add(new SensorUsage(uid, timeGps, countGps, uSecNow)); - } - if (timeOther > 0) { - mSensorUsage.add(new SensorUsage(uid, timeOther, countOther, uSecNow)); - } - } - - Collections.sort(mGpsUsage); - Collections.sort(mSensorUsage); - } - - private void processWakelockUsage() { - mWakelockUsage.clear(); - - long uSecTime = SystemClock.elapsedRealtime() * 1000; - final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000; - - SparseArray<? extends Uid> uidStats = mStats.getUidStats(); - final int NU = uidStats.size(); - for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - int uid = u.getUid(); - - Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats(); - long time = 0; - int count = 0; - if (wakelockStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent - : wakelockStats.entrySet()) { - - Uid.Wakelock wl = ent.getValue(); - Timer timer = wl.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL); - if (timer != null) { - // Convert from microseconds to milliseconds with rounding - time += (timer.getTotalTimeLocked(uSecNow, mWhich) + 500) / 1000; - count += timer.getCountLocked(mWhich); - } - } - } - - if (time > 0) { - mWakelockUsage.add(new WakelockUsage(uid, time, count, uSecNow)); - } - } - - Collections.sort(mWakelockUsage); - } - - private final StringBuilder mFormatBuilder = new StringBuilder(8); - private final Formatter mFormatter = new Formatter(mFormatBuilder); - - private final String formatRatio(long num, long den) { - if (den == 0L) { - return "---%"; - } - float perc = ((float)num) / ((float)den) * 100; - mFormatBuilder.setLength(0); - mFormatter.format("%.1f%%", perc); - return mFormatBuilder.toString(); - } - - private void processMiscUsage() { - mMiscUsage.clear(); - - long rawRealtime = SystemClock.elapsedRealtime() * 1000; - final long batteryRealtime = mStats.getBatteryRealtime(rawRealtime); - final long whichRealtime = mStats.computeBatteryRealtime(rawRealtime, mWhich) / 1000; - - long time = mStats.computeBatteryUptime(SystemClock.uptimeMillis() * 1000, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage(getString( - R.string.battery_history_awake_label) - + " (" + formatRatio(time, whichRealtime) + ")", - R.string.battery_history_awake, - time, whichRealtime)); - } - - time = mStats.getScreenOnTime(batteryRealtime, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage(getString( - R.string.battery_history_screen_on_label) - + " (" + formatRatio(time, whichRealtime) + ")", - R.string.battery_history_screen_on, - time, whichRealtime)); - } - - time = mStats.getPhoneOnTime(batteryRealtime, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage(getString( - R.string.battery_history_phone_on_label) - + " (" + formatRatio(time, whichRealtime) + ")", - R.string.battery_history_phone_on, - time, whichRealtime)); - } - - time = mStats.getWifiOnTime(batteryRealtime, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage("Wifi On (" - + formatRatio(time, whichRealtime) + ")", - "Time spent with Wifi on:", - time, whichRealtime)); - } - - time = mStats.getWifiRunningTime(batteryRealtime, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage("Wifi Running (" - + formatRatio(time, whichRealtime) + ")", - "Time spent with Wifi running:", - time, whichRealtime)); - } - - time = mStats.getBluetoothOnTime(batteryRealtime, mWhich) / 1000; - if (time > 0) { - mMiscUsage.add(new MiscUsage("Bluetooth On (" - + formatRatio(time, whichRealtime) + ")", - "Time spent with Bluetooth on:", - time, whichRealtime)); - } - - Collections.sort(mMiscUsage); - } - - private void collectStatistics() { - if (mType == CPU_USAGE) { - if (!mHaveCpuUsage) { - mHaveCpuUsage = true; - processCpuUsage(); - } - } - if (mType == NETWORK_USAGE) { - if (!mHaveNetworkUsage) { - mHaveNetworkUsage = true; - processNetworkUsage(); - } - } - if (mType == GPS_USAGE || mType == SENSOR_USAGE) { - if (!mHaveSensorUsage) { - mHaveSensorUsage = true; - processSensorUsage(); - } - } - if (mType == WAKELOCK_USAGE) { - if (!mHaveWakelockUsage) { - mHaveWakelockUsage = true; - processWakelockUsage(); - } - } - if (mType == MISC_USAGE) { - if (!mHaveMiscUsage) { - mHaveMiscUsage = true; - processMiscUsage(); - } - } - } - - private void load() { - try { - byte[] data = mBatteryInfo.getStatistics(); - Parcel parcel = Parcel.obtain(); - //Log.i(TAG, "Got data: " + data.length + " bytes"); - parcel.unmarshall(data, 0, data.length); - parcel.setDataPosition(0); - mStats = com.android.internal.os.BatteryStatsImpl.CREATOR - .createFromParcel(parcel); - //Log.i(TAG, "RECEIVED BATTERY INFO:"); - //mStats.dumpLocked(new LogPrinter(Log.INFO, TAG)); - - mHaveCpuUsage = mHaveNetworkUsage = mHaveSensorUsage - = mHaveWakelockUsage = mHaveMiscUsage = false; - } catch (RemoteException e) { - Log.e(TAG, "RemoteException:", e); - } - } - - public void onClick(View v) { - if (v == mDetailsBackButton) { - hideDetails(); - return; - } - - int id = ((Integer) v.getTag()).intValue(); - showDetails(id); - } - - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK && mDetailsShown) { - hideDetails(); - return true; - } - return super.onKeyDown(keyCode, event); - } - - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - int oldWhich = mWhich; - - if (parent.equals(mTypeSpinner)) { - mType = position; - } else if (parent.equals(mWhichSpinner)) { - switch (position) { - case UNPLUGGED: - mWhich = BatteryStats.STATS_UNPLUGGED; - break; - case CURRENT: - mWhich = BatteryStats.STATS_CURRENT; - break; - case TOTAL: - mWhich = BatteryStats.STATS_TOTAL; - break; - } - } - - if (oldWhich != mWhich) { - mHaveCpuUsage = mHaveNetworkUsage = mHaveSensorUsage - = mHaveWakelockUsage = mHaveMiscUsage = false; - } - - displayGraph(); - } - - public void onNothingSelected(AdapterView<?> parent) { - // Do nothing - } - - @Override - public Object onRetainNonConfigurationInstance() { - BatteryStats stats = mStats; - mStats = null; - return stats; - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (mStats != null) { - outState.putParcelable("stats", mStats); - } - outState.putInt("type", mType); - outState.putInt("which", mWhich); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - Log.i(TAG, "onCreate"); - - setContentView(R.layout.battery_history); - - mStats = (BatteryStats)getLastNonConfigurationInstance(); - if (icicle != null) { - if (mStats == null) { - mStats = (BatteryStats)icicle.getParcelable("stats"); - } - mType = icicle.getInt("type"); - mWhich = icicle.getInt("which"); - } - - mGraphLayout = (LinearLayout) findViewById(R.id.graphLayout); - mTextLayout = (LinearLayout) findViewById(R.id.textLayout); - mDetailsText = (TextView) findViewById(R.id.detailsText); - mMessageText = (TextView) findViewById(R.id.messageText); - - mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner); - mTypeSpinner.setSelection(mType); - mTypeSpinner.setOnItemSelectedListener(this); - - mWhichSpinner = (Spinner) findViewById(R.id.whichSpinner); - mWhichSpinner.setOnItemSelectedListener(this); - mWhichSpinner.setEnabled(true); - - mButtons = new GraphableButton[8]; - mButtons[0] = (GraphableButton) findViewById(R.id.button0); - mButtons[1] = (GraphableButton) findViewById(R.id.button1); - mButtons[2] = (GraphableButton) findViewById(R.id.button2); - mButtons[3] = (GraphableButton) findViewById(R.id.button3); - mButtons[4] = (GraphableButton) findViewById(R.id.button4); - mButtons[5] = (GraphableButton) findViewById(R.id.button5); - mButtons[6] = (GraphableButton) findViewById(R.id.button6); - mButtons[7] = (GraphableButton) findViewById(R.id.button7); - - for (int i = 0; i < mButtons.length; i++) { - mButtons[i].setTag(i); - mButtons[i].setOnClickListener(this); - } - - mBatteryInfo = IBatteryStats.Stub.asInterface( - ServiceManager.getService("batteryinfo")); - - if (mStats == null) { - load(); - } - displayGraph(); - } -} diff --git a/src/com/android/settings/battery_history/GraphableButton.java b/src/com/android/settings/battery_history/GraphableButton.java deleted file mode 100644 index fb90a0d..0000000 --- a/src/com/android/settings/battery_history/GraphableButton.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.android.settings.battery_history; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.Button; - -public class GraphableButton extends Button { - private static final String TAG = "GraphableButton"; - - static Paint[] sPaint = new Paint[2]; - static { - sPaint[0] = new Paint(); - sPaint[0].setStyle(Paint.Style.FILL); - sPaint[0].setColor(0xFF0080FF); - - sPaint[1] = new Paint(); - sPaint[1].setStyle(Paint.Style.FILL); - sPaint[1].setColor(0xFFFF6060); - } - - double[] mValues; - - public GraphableButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setValues(double[] values, double maxValue) { - mValues = values.clone(); - for (int i = 0; i < values.length; i++) { - mValues[i] /= maxValue; - } - } - - @Override - public void onDraw(Canvas canvas) { - Log.i(TAG, "onDraw: w = " + getWidth() + ", h = " + getHeight()); - - int xmin = getPaddingLeft(); - int xmax = getWidth() - getPaddingRight(); - int ymin = getPaddingTop(); - int ymax = getHeight() - getPaddingBottom(); - - int startx = xmin; - for (int i = 0; i < mValues.length; i++) { - int endx = xmin + (int) (mValues[i] * (xmax - xmin)); - canvas.drawRect(startx, ymin, endx, ymax, sPaint[i]); - startx = endx; - } - super.onDraw(canvas); - } -} diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java new file mode 100644 index 0000000..95a9fb2 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010 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 com.android.settings.R; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.os.BatteryStats; +import android.os.SystemClock; +import android.os.BatteryStats.BatteryHistoryRecord; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.view.View; + +public class BatteryHistoryChart extends View { + private static final int SANS = 1; + private static final int SERIF = 2; + private static final int MONOSPACE = 3; + + final Paint mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + int mFontSize; + + BatteryStats mStats; + long mStatsPeriod; + String mDurationString; + + int mTextAscent; + int mTextDescent; + int mDurationStringWidth; + + int mNumHist; + long mHistStart; + long mHistEnd; + int mBatLow; + int mBatHigh; + + public BatteryHistoryChart(Context context, AttributeSet attrs) { + super(context, attrs); + + mBatteryPaint.setARGB(255, 255, 128, 128); + + mTextPaint.density = getResources().getDisplayMetrics().density; + mTextPaint.setCompatibilityScaling( + getResources().getCompatibilityInfo().applicationScale); + + TypedArray a = + context.obtainStyledAttributes( + attrs, R.styleable.BatteryHistoryChart, 0, 0); + + ColorStateList textColor = null; + int textSize = 15; + int typefaceIndex = -1; + int styleIndex = -1; + + TypedArray appearance = null; + int ap = a.getResourceId(R.styleable.BatteryHistoryChart_android_textAppearance, -1); + if (ap != -1) { + appearance = context.obtainStyledAttributes(ap, + com.android.internal.R.styleable. + TextAppearance); + } + if (appearance != null) { + int n = appearance.getIndexCount(); + for (int i = 0; i < n; i++) { + int attr = appearance.getIndex(i); + + switch (attr) { + case com.android.internal.R.styleable.TextAppearance_textColor: + textColor = appearance.getColorStateList(attr); + break; + + case com.android.internal.R.styleable.TextAppearance_textSize: + textSize = appearance.getDimensionPixelSize(attr, textSize); + break; + + case com.android.internal.R.styleable.TextAppearance_typeface: + typefaceIndex = appearance.getInt(attr, -1); + break; + + case com.android.internal.R.styleable.TextAppearance_textStyle: + styleIndex = appearance.getInt(attr, -1); + break; + } + } + + appearance.recycle(); + } + + int shadowcolor = 0; + float dx=0, dy=0, r=0; + + int n = a.getIndexCount(); + for (int i = 0; i < n; i++) { + int attr = a.getIndex(i); + + switch (attr) { + case R.styleable.BatteryHistoryChart_android_shadowColor: + shadowcolor = a.getInt(attr, 0); + break; + + case R.styleable.BatteryHistoryChart_android_shadowDx: + dx = a.getFloat(attr, 0); + break; + + case R.styleable.BatteryHistoryChart_android_shadowDy: + dy = a.getFloat(attr, 0); + break; + + case R.styleable.BatteryHistoryChart_android_shadowRadius: + r = a.getFloat(attr, 0); + break; + + case R.styleable.BatteryHistoryChart_android_textColor: + textColor = a.getColorStateList(attr); + break; + + case R.styleable.BatteryHistoryChart_android_textSize: + textSize = a.getDimensionPixelSize(attr, textSize); + break; + + case R.styleable.BatteryHistoryChart_android_typeface: + typefaceIndex = a.getInt(attr, typefaceIndex); + break; + + case R.styleable.BatteryHistoryChart_android_textStyle: + styleIndex = a.getInt(attr, styleIndex); + break; + } + } + + mTextPaint.setColor(textColor.getDefaultColor()); + mTextPaint.setTextSize(textSize); + + Typeface tf = null; + switch (typefaceIndex) { + case SANS: + tf = Typeface.SANS_SERIF; + break; + + case SERIF: + tf = Typeface.SERIF; + break; + + case MONOSPACE: + tf = Typeface.MONOSPACE; + break; + } + + setTypeface(tf, styleIndex); + + if (shadowcolor != 0) { + mTextPaint.setShadowLayer(r, dx, dy, shadowcolor); + } + } + + public void setTypeface(Typeface tf, int style) { + if (style > 0) { + if (tf == null) { + tf = Typeface.defaultFromStyle(style); + } else { + tf = Typeface.create(tf, style); + } + + mTextPaint.setTypeface(tf); + // now compute what (if any) algorithmic styling is needed + int typefaceStyle = tf != null ? tf.getStyle() : 0; + int need = style & ~typefaceStyle; + mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0); + mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0); + } else { + mTextPaint.setFakeBoldText(false); + mTextPaint.setTextSkewX(0); + mTextPaint.setTypeface(tf); + } + } + + void setStats(BatteryStats stats) { + mStats = stats; + + long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, + BatteryStats.STATS_UNPLUGGED); + mStatsPeriod = uSecTime; + String durationString = Utils.formatElapsedTime(getContext(), mStatsPeriod / 1000); + mDurationString = getContext().getString(R.string.battery_stats_on_battery, + durationString); + + BatteryStats.BatteryHistoryRecord rec = stats.getHistory(); + if (rec != null) { + mHistStart = rec.time; + mBatLow = mBatHigh = rec.batteryLevel; + } + int pos = 0; + int lastUnplugged = 0; + mBatLow = 0; + mBatHigh = 100; + while (rec != null) { + pos++; + if ((rec.states&BatteryHistoryRecord.STATE_BATTERY_PLUGGED_FLAG) == 0) { + lastUnplugged = pos; + mHistEnd = rec.time; + } + rec = rec.next; + } + mNumHist = lastUnplugged; + + if (mHistEnd <= mHistStart) mHistEnd = mHistStart+1; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + mDurationStringWidth = (int)mTextPaint.measureText(mDurationString); + mTextAscent = (int)mTextPaint.ascent(); + mTextDescent = (int)mTextPaint.descent(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + final int width = getWidth(); + final int height = getHeight(); + + final long timeStart = mHistStart; + final long timeChange = mHistEnd-mHistStart; + + final int batLow = mBatLow; + final int batChange = mBatHigh-mBatLow; + + BatteryStats.BatteryHistoryRecord rec = mStats.getHistory(); + int lastX=-1, lastY=-1; + int pos = 0; + final int N = mNumHist; + while (rec != null && pos < N) { + int x = (int)(((rec.time-timeStart)*width)/timeChange); + int y = height-1 - ((rec.batteryLevel-batLow)*height)/batChange; + if (lastX >= 0) { + canvas.drawLine(lastX, lastY, x, y, mBatteryPaint); + } + lastX = x; + lastY = y; + rec = rec.next; + pos++; + } + + canvas.drawText(mDurationString, (width/2) - (mDurationStringWidth/2), + (height/2) - ((mTextDescent-mTextAscent)/2) - mTextAscent, mTextPaint); + } +} diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java new file mode 100644 index 0000000..4579db7 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 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.content.Context; +import android.graphics.drawable.Drawable; +import android.os.BatteryStats; +import android.preference.Preference; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.settings.R; + +/** + * Custom preference for displaying power consumption as a bar and an icon on the left for the + * subsystem/app type. + * + */ +public class BatteryHistoryPreference extends Preference { + + private BatteryStats mStats; + + public BatteryHistoryPreference(Context context, BatteryStats stats) { + super(context); + setLayoutResource(R.layout.preference_batteryhistory); + mStats = stats; + } + + BatteryStats getStats() { + return mStats; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + BatteryHistoryChart chart = (BatteryHistoryChart)view.findViewById( + R.id.battery_history_chart); + chart.setStats(mStats); + } +} diff --git a/src/com/android/settings/fuelgauge/BatterySipper.java b/src/com/android/settings/fuelgauge/BatterySipper.java new file mode 100644 index 0000000..8125146 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatterySipper.java @@ -0,0 +1,196 @@ +/* + * 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 com.android.settings.R; +import com.android.settings.fuelgauge.PowerUsageDetail.DrainType; + +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.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.BatteryStats.Uid; + +import java.util.ArrayList; +import java.util.HashMap; + +class BatterySipper implements Comparable<BatterySipper> { + final Context mContext; + final HashMap<String,UidToDetail> mUidCache = 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 cpuFgTime; + double percent; + double noCoveragePercent; + String defaultPackageName; + + static class UidToDetail { + String name; + String packageName; + Drawable icon; + } + + BatterySipper(Context context, ArrayList<BatterySipper> requestQueue, + Handler handler, String label, DrainType drainType, + int iconId, Uid uid, double[] values) { + mContext = context; + mRequestQueue = requestQueue; + mHandler = handler; + this.values = values; + name = label; + this.drainType = drainType; + if (iconId > 0) { + icon = mContext.getResources().getDrawable(iconId); + } + if (values != null) value = values[0]; + if ((label == null || iconId == 0) && uid != null) { + getQuickNameIconForUid(uid); + } + uidObj = uid; + } + + double getSortValue() { + return value; + } + + double[] getValues() { + return values; + } + + Drawable getIcon() { + return icon; + } + + public int compareTo(BatterySipper other) { + // Return the flipped value because we want the items in descending order + return (int) (other.getSortValue() - getSortValue()); + } + + void getQuickNameIconForUid(Uid uidObj) { + final int uid = uidObj.getUid(); + final String uidString = Integer.toString(uid); + if (mUidCache.containsKey(uidString)) { + UidToDetail utd = mUidCache.get(uidString); + defaultPackageName = utd.packageName; + name = utd.name; + icon = utd.icon; + return; + } + PackageManager pm = mContext.getPackageManager(); + final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); + 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); + } else if ("mediaserver".equals(name)) { + name = mContext.getResources().getString(R.string.process_mediaserver_label); + } + iconId = R.drawable.ic_power_system; + icon = mContext.getResources().getDrawable(iconId); + return; + } else { + //name = packages[0]; + } + synchronized (mRequestQueue) { + mRequestQueue.add(this); + } + } + + /** + * Sets name and icon + * @param uid Uid of the application + */ + void getNameIcon() { + PackageManager pm = mContext.getPackageManager(); + final int uid = uidObj.getUid(); + final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); + String[] packages = pm.getPackagesForUid(uid); + if (packages == null) { + name = Integer.toString(uid); + return; + } + + String[] packageLabels = new String[packages.length]; + System.arraycopy(packages, 0, packageLabels, 0, packages.length); + + int preferredIndex = -1; + // Convert package names to user-facing labels where possible + for (int i = 0; i < packageLabels.length; i++) { + // Check if package matches preferred package + if (packageLabels[i].equals(name)) preferredIndex = i; + try { + ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0); + CharSequence label = ai.loadLabel(pm); + if (label != null) { + packageLabels[i] = label.toString(); + } + if (ai.icon != 0) { + defaultPackageName = packages[i]; + icon = ai.loadIcon(pm); + break; + } + } catch (NameNotFoundException e) { + } + } + if (icon == null) icon = defaultActivityIcon; + + if (packageLabels.length == 1) { + name = packageLabels[0]; + } else { + // Look for an official name for this UID. + for (String pkgName : packages) { + try { + final PackageInfo pi = pm.getPackageInfo(pkgName, 0); + if (pi.sharedUserLabel != 0) { + final CharSequence nm = pm.getText(pkgName, + pi.sharedUserLabel, pi.applicationInfo); + if (nm != null) { + name = nm.toString(); + if (pi.applicationInfo.icon != 0) { + defaultPackageName = pkgName; + icon = pi.applicationInfo.loadIcon(pm); + } + break; + } + } + } catch (PackageManager.NameNotFoundException e) { + } + } + } + final String uidString = Integer.toString(uidObj.getUid()); + UidToDetail utd = new UidToDetail(); + utd.name = name; + utd.icon = icon; + utd.packageName = defaultPackageName; + mUidCache.put(uidString, utd); + mHandler.sendMessage(mHandler.obtainMessage(PowerUsageSummary.MSG_UPDATE_NAME_ICON, this)); + } +}
\ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java index 68f294c..ad8c25b 100644 --- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java +++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java @@ -17,9 +17,6 @@ package com.android.settings.fuelgauge; import android.content.Context; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.preference.Preference; import android.view.View; @@ -27,7 +24,6 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.settings.R; -import com.android.settings.fuelgauge.PowerUsageSummary.BatterySipper; /** * Custom preference for displaying power consumption as a bar and an icon on the left for the diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 5678160..a6c8a05 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -18,10 +18,6 @@ package com.android.settings.fuelgauge; 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.hardware.SensorManager; import android.os.BatteryStats; @@ -53,7 +49,6 @@ import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -86,19 +81,11 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { private double mTotalPower; private PowerProfile mPowerProfile; - private HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>(); - /** Queue for fetching name and icon for an application */ private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>(); private Thread mRequestThread; private boolean mAbort; - static class UidToDetail { - String name; - String packageName; - Drawable icon; - } - @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -267,6 +254,10 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { mAppListGroup.setOrderingAsAdded(false); + BatteryHistoryPreference hist = new BatteryHistoryPreference(this, mStats); + hist.setOrder(-1); + mAppListGroup.addPreference(hist); + Collections.sort(mUsageList); for (BatterySipper sipper : mUsageList) { if (sipper.getSortValue() < MIN_POWER_THRESHOLD) continue; @@ -283,7 +274,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { pref.setKey(Integer.toString(sipper.uidObj.getUid())); } mAppListGroup.addPreference(pref); - if (mAppListGroup.getPreferenceCount() > MAX_ITEMS_TO_LIST) break; + if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break; } if (DEBUG) setTitle("Battery total uAh = " + ((mTotalPower * 1000) / 3600)); synchronized (mRequestQueue) { @@ -408,7 +399,8 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { // Add the app to the list if it is consuming power if (power != 0) { - BatterySipper app = new BatterySipper(packageWithHighestDrain, DrainType.APP, 0, u, + BatterySipper app = new BatterySipper(this, mRequestQueue, mHandler, + packageWithHighestDrain, DrainType.APP, 0, u, new double[] {power}); app.cpuTime = cpuTime; app.gpsTime = gpsTime; @@ -549,7 +541,8 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { double power) { if (power > mMaxPower) mMaxPower = power; mTotalPower += power; - BatterySipper bs = new BatterySipper(label, drainType, iconId, null, new double[] {power}); + BatterySipper bs = new BatterySipper(this, mRequestQueue, mHandler, + label, drainType, iconId, null, new double[] {power}); bs.usageTime = time; bs.iconId = iconId; mUsageList.add(bs); @@ -569,156 +562,6 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { } } - class BatterySipper implements Comparable<BatterySipper> { - 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 cpuFgTime; - double percent; - double noCoveragePercent; - String defaultPackageName; - - BatterySipper(String label, DrainType drainType, int iconId, Uid uid, double[] values) { - this.values = values; - name = label; - this.drainType = drainType; - if (iconId > 0) { - icon = getResources().getDrawable(iconId); - } - if (values != null) value = values[0]; - if ((label == null || iconId == 0) && uid != null) { - getQuickNameIconForUid(uid); - } - uidObj = uid; - } - - double getSortValue() { - return value; - } - - double[] getValues() { - return values; - } - - Drawable getIcon() { - return icon; - } - - public int compareTo(BatterySipper other) { - // Return the flipped value because we want the items in descending order - return (int) (other.getSortValue() - getSortValue()); - } - - void getQuickNameIconForUid(Uid uidObj) { - final int uid = uidObj.getUid(); - final String uidString = Integer.toString(uid); - if (mUidCache.containsKey(uidString)) { - UidToDetail utd = mUidCache.get(uidString); - defaultPackageName = utd.packageName; - name = utd.name; - icon = utd.icon; - return; - } - PackageManager pm = getPackageManager(); - final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); - String[] packages = pm.getPackagesForUid(uid); - icon = pm.getDefaultActivityIcon(); - if (packages == null) { - //name = Integer.toString(uid); - if (uid == 0) { - name = getResources().getString(R.string.process_kernel_label); - } else if ("mediaserver".equals(name)) { - name = getResources().getString(R.string.process_mediaserver_label); - } - iconId = R.drawable.ic_power_system; - icon = getResources().getDrawable(iconId); - return; - } else { - //name = packages[0]; - } - synchronized (mRequestQueue) { - mRequestQueue.add(this); - } - } - - /** - * Sets name and icon - * @param uid Uid of the application - */ - void getNameIcon() { - PackageManager pm = getPackageManager(); - final int uid = uidObj.getUid(); - final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); - String[] packages = pm.getPackagesForUid(uid); - if (packages == null) { - name = Integer.toString(uid); - return; - } - - String[] packageLabels = new String[packages.length]; - System.arraycopy(packages, 0, packageLabels, 0, packages.length); - - int preferredIndex = -1; - // Convert package names to user-facing labels where possible - for (int i = 0; i < packageLabels.length; i++) { - // Check if package matches preferred package - if (packageLabels[i].equals(name)) preferredIndex = i; - try { - ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0); - CharSequence label = ai.loadLabel(pm); - if (label != null) { - packageLabels[i] = label.toString(); - } - if (ai.icon != 0) { - defaultPackageName = packages[i]; - icon = ai.loadIcon(pm); - break; - } - } catch (NameNotFoundException e) { - } - } - if (icon == null) icon = defaultActivityIcon; - - if (packageLabels.length == 1) { - name = packageLabels[0]; - } else { - // Look for an official name for this UID. - for (String pkgName : packages) { - try { - final PackageInfo pi = pm.getPackageInfo(pkgName, 0); - if (pi.sharedUserLabel != 0) { - final CharSequence nm = pm.getText(pkgName, - pi.sharedUserLabel, pi.applicationInfo); - if (nm != null) { - name = nm.toString(); - if (pi.applicationInfo.icon != 0) { - defaultPackageName = pkgName; - icon = pi.applicationInfo.loadIcon(pm); - } - break; - } - } - } catch (PackageManager.NameNotFoundException e) { - } - } - } - final String uidString = Integer.toString(uidObj.getUid()); - UidToDetail utd = new UidToDetail(); - utd.name = name; - utd.icon = icon; - utd.packageName = defaultPackageName; - mUidCache.put(uidString, utd); - mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this)); - } - } - public void run() { while (true) { BatterySipper bs; @@ -733,7 +576,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { } } - private static final int MSG_UPDATE_NAME_ICON = 1; + static final int MSG_UPDATE_NAME_ICON = 1; Handler mHandler = new Handler() { |