Fix issue #3114356: Storage visualization in Manage Apps is confusing
Also fixes issue #3097388: If you launch Manage Applications when SD card app info isn't available, incomplete information gets cached Change-Id: If3377a965653590e5bc1df25e38764a83e96b820
This commit is contained in:
@@ -43,9 +43,11 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="-5dp"
|
android:layout_marginTop="-5dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
android:paddingTop="30dp"
|
android:paddingTop="30dp"
|
||||||
android:paddingLeft="2dp"
|
android:paddingLeft="4dp"
|
||||||
android:paddingRight="2dp"
|
android:paddingRight="4dp"
|
||||||
android:paddingBottom="1dp">
|
android:paddingBottom="1dp">
|
||||||
<TextView android:id="@+id/usedStorageText"
|
<TextView android:id="@+id/usedStorageText"
|
||||||
android:layout_width="0px"
|
android:layout_width="0px"
|
||||||
@@ -58,8 +60,11 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
|
android:layout_marginTop="-23dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmallInverse"
|
android:textAppearance="?android:attr/textAppearanceSmallInverse"
|
||||||
android:textColor="#000"
|
android:textColor="#ccc"
|
||||||
|
android:shadowColor="#000"
|
||||||
|
android:shadowRadius="5"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@string/internal_storage" />
|
android:text="@string/internal_storage" />
|
||||||
|
@@ -41,9 +41,11 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="-5dp"
|
android:layout_marginTop="-5dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
android:paddingTop="30dp"
|
android:paddingTop="30dp"
|
||||||
android:paddingLeft="2dp"
|
android:paddingLeft="4dp"
|
||||||
android:paddingRight="2dp"
|
android:paddingRight="4dp"
|
||||||
android:paddingBottom="1dp">
|
android:paddingBottom="1dp">
|
||||||
<TextView android:id="@+id/foregroundText"
|
<TextView android:id="@+id/foregroundText"
|
||||||
android:layout_width="0px"
|
android:layout_width="0px"
|
||||||
@@ -58,8 +60,11 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
|
android:layout_marginTop="-23dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmallInverse"
|
android:textAppearance="?android:attr/textAppearanceSmallInverse"
|
||||||
android:textColor="#000"
|
android:textColor="#ccc"
|
||||||
|
android:shadowColor="#000"
|
||||||
|
android:shadowRadius="5"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@string/memory" />
|
android:text="@string/memory" />
|
||||||
|
@@ -21,6 +21,7 @@ import android.os.SystemClock;
|
|||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.text.Normalizer;
|
import java.text.Normalizer;
|
||||||
import java.text.Normalizer.Form;
|
import java.text.Normalizer.Form;
|
||||||
@@ -66,14 +67,17 @@ public class ApplicationsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class AppEntry {
|
public static class AppEntry {
|
||||||
final String label;
|
final File apkFile;
|
||||||
final long id;
|
final long id;
|
||||||
|
String label;
|
||||||
long size;
|
long size;
|
||||||
|
|
||||||
long cacheSize;
|
long cacheSize;
|
||||||
long codeSize;
|
long codeSize;
|
||||||
long dataSize;
|
long dataSize;
|
||||||
|
|
||||||
|
boolean mounted;
|
||||||
|
|
||||||
String getNormalizedLabel() {
|
String getNormalizedLabel() {
|
||||||
if (normalizedLabel != null) {
|
if (normalizedLabel != null) {
|
||||||
return normalizedLabel;
|
return normalizedLabel;
|
||||||
@@ -92,12 +96,47 @@ public class ApplicationsState {
|
|||||||
String normalizedLabel;
|
String normalizedLabel;
|
||||||
|
|
||||||
AppEntry(Context context, ApplicationInfo info, long id) {
|
AppEntry(Context context, ApplicationInfo info, long id) {
|
||||||
CharSequence label = info.loadLabel(context.getPackageManager());
|
apkFile = new File(info.sourceDir);
|
||||||
this.label = label != null ? label.toString() : info.packageName;
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.size = SIZE_UNKNOWN;
|
this.size = SIZE_UNKNOWN;
|
||||||
this.sizeStale = true;
|
this.sizeStale = true;
|
||||||
|
ensureLabel(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensureLabel(Context context) {
|
||||||
|
if (this.label == null || !this.mounted) {
|
||||||
|
if (!this.apkFile.exists()) {
|
||||||
|
this.mounted = false;
|
||||||
|
this.label = info.packageName;
|
||||||
|
} else {
|
||||||
|
this.mounted = true;
|
||||||
|
CharSequence label = info.loadLabel(context.getPackageManager());
|
||||||
|
this.label = label != null ? label.toString() : info.packageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean ensureIconLocked(Context context, PackageManager pm) {
|
||||||
|
if (this.icon == null) {
|
||||||
|
if (this.apkFile.exists()) {
|
||||||
|
this.icon = this.info.loadIcon(pm);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.mounted = false;
|
||||||
|
this.icon = context.getResources().getDrawable(
|
||||||
|
com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon);
|
||||||
|
}
|
||||||
|
} else if (!this.mounted) {
|
||||||
|
// If the app wasn't mounted but is now mounted, reload
|
||||||
|
// its icon.
|
||||||
|
if (this.apkFile.exists()) {
|
||||||
|
this.mounted = true;
|
||||||
|
this.icon = this.info.loadIcon(pm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,9 +256,11 @@ public class ApplicationsState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean avail = Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr);
|
boolean avail = Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr);
|
||||||
for (String pkgName : pkgList) {
|
if (avail) {
|
||||||
if (avail) addPackage(pkgName);
|
for (String pkgName : pkgList) {
|
||||||
else removePackage(pkgName);
|
removePackage(pkgName);
|
||||||
|
addPackage(pkgName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,6 +353,13 @@ public class ApplicationsState {
|
|||||||
for (int i=0; i<mAppEntries.size(); i++) {
|
for (int i=0; i<mAppEntries.size(); i++) {
|
||||||
mAppEntries.get(i).sizeStale = true;
|
mAppEntries.get(i).sizeStale = true;
|
||||||
}
|
}
|
||||||
|
for (int i=0; i<mApplications.size(); i++) {
|
||||||
|
final ApplicationInfo info = mApplications.get(i);
|
||||||
|
final AppEntry entry = mEntriesMap.get(info.packageName);
|
||||||
|
if (entry != null) {
|
||||||
|
entry.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
mCurComputingSizePkg = null;
|
mCurComputingSizePkg = null;
|
||||||
if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
|
if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
|
||||||
mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
|
mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
|
||||||
@@ -391,6 +439,7 @@ public class ApplicationsState {
|
|||||||
if (filter == null || filter.filterApp(info)) {
|
if (filter == null || filter.filterApp(info)) {
|
||||||
synchronized (mEntriesMap) {
|
synchronized (mEntriesMap) {
|
||||||
AppEntry entry = getEntryLocked(info);
|
AppEntry entry = getEntryLocked(info);
|
||||||
|
entry.ensureLabel(mContext);
|
||||||
if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry);
|
if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry);
|
||||||
filteredApps.add(entry);
|
filteredApps.add(entry);
|
||||||
}
|
}
|
||||||
@@ -438,12 +487,10 @@ public class ApplicationsState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (entry) {
|
synchronized (entry) {
|
||||||
if (entry.icon == null) {
|
entry.ensureIconLocked(mContext, mPm);
|
||||||
entry.icon = entry.info.loadIcon(mPm);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestSize(String packageName) {
|
void requestSize(String packageName) {
|
||||||
synchronized (mEntriesMap) {
|
synchronized (mEntriesMap) {
|
||||||
AppEntry entry = mEntriesMap.get(packageName);
|
AppEntry entry = mEntriesMap.get(packageName);
|
||||||
@@ -453,6 +500,16 @@ public class ApplicationsState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long sumCacheSizes() {
|
||||||
|
long sum = 0;
|
||||||
|
synchronized (mEntriesMap) {
|
||||||
|
for (int i=mAppEntries.size()-1; i>=0; i--) {
|
||||||
|
sum += mAppEntries.get(i).cacheSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
int indexOfApplicationInfoLocked(String pkgName) {
|
int indexOfApplicationInfoLocked(String pkgName) {
|
||||||
for (int i=mApplications.size()-1; i>=0; i--) {
|
for (int i=mApplications.size()-1; i>=0; i--) {
|
||||||
if (mApplications.get(i).packageName.equals(pkgName)) {
|
if (mApplications.get(i).packageName.equals(pkgName)) {
|
||||||
@@ -630,16 +687,17 @@ public class ApplicationsState {
|
|||||||
synchronized (mEntriesMap) {
|
synchronized (mEntriesMap) {
|
||||||
for (int i=0; i<mAppEntries.size() && numDone<2; i++) {
|
for (int i=0; i<mAppEntries.size() && numDone<2; i++) {
|
||||||
AppEntry entry = mAppEntries.get(i);
|
AppEntry entry = mAppEntries.get(i);
|
||||||
if (entry.icon == null) {
|
if (entry.icon == null || !entry.mounted) {
|
||||||
if (!mRunning) {
|
|
||||||
mRunning = true;
|
|
||||||
Message m = mMainHandler.obtainMessage(
|
|
||||||
MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
|
|
||||||
mMainHandler.sendMessage(m);
|
|
||||||
}
|
|
||||||
numDone++;
|
|
||||||
synchronized (entry) {
|
synchronized (entry) {
|
||||||
entry.icon = entry.info.loadIcon(mPm);
|
if (entry.ensureIconLocked(mContext, mPm)) {
|
||||||
|
if (!mRunning) {
|
||||||
|
mRunning = true;
|
||||||
|
Message m = mMainHandler.obtainMessage(
|
||||||
|
MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
|
||||||
|
mMainHandler.sendMessage(m);
|
||||||
|
}
|
||||||
|
numDone++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ import android.widget.LinearLayout;
|
|||||||
|
|
||||||
public class LinearColorBar extends LinearLayout {
|
public class LinearColorBar extends LinearLayout {
|
||||||
static final int LEFT_COLOR = 0xffa0a0a0;
|
static final int LEFT_COLOR = 0xffa0a0a0;
|
||||||
static final int MIDDLE_COLOR = 0xff7070ff;
|
static final int MIDDLE_COLOR = 0xffa0a0a0;
|
||||||
static final int RIGHT_COLOR = 0xffa0c0a0;
|
static final int RIGHT_COLOR = 0xffa0c0a0;
|
||||||
|
|
||||||
private float mRedRatio;
|
private float mRedRatio;
|
||||||
@@ -47,6 +47,7 @@ public class LinearColorBar extends LinearLayout {
|
|||||||
? 2 : 1;
|
? 2 : 1;
|
||||||
mEdgeGradientPaint.setStrokeWidth(mLineWidth);
|
mEdgeGradientPaint.setStrokeWidth(mLineWidth);
|
||||||
mEdgeGradientPaint.setAntiAlias(true);
|
mEdgeGradientPaint.setAntiAlias(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRatios(float red, float yellow, float green) {
|
public void setRatios(float red, float yellow, float green) {
|
||||||
@@ -111,22 +112,33 @@ public class LinearColorBar extends LinearLayout {
|
|||||||
mColorPath.reset();
|
mColorPath.reset();
|
||||||
mEdgePath.reset();
|
mEdgePath.reset();
|
||||||
if (indicatorLeft < indicatorRight) {
|
if (indicatorLeft < indicatorRight) {
|
||||||
|
final int midTopY = mRect.top;
|
||||||
|
final int midBottomY = 0;
|
||||||
|
final int xoff = 2;
|
||||||
mColorPath.moveTo(indicatorLeft, mRect.top);
|
mColorPath.moveTo(indicatorLeft, mRect.top);
|
||||||
mColorPath.lineTo(-1, 0);
|
mColorPath.cubicTo(indicatorLeft, midBottomY,
|
||||||
mColorPath.lineTo(width, 0);
|
-xoff, midTopY,
|
||||||
mColorPath.lineTo(indicatorRight, mRect.top);
|
-xoff, 0);
|
||||||
|
mColorPath.lineTo(width+xoff-1, 0);
|
||||||
|
mColorPath.cubicTo(width+xoff-1, midTopY,
|
||||||
|
indicatorRight, midBottomY,
|
||||||
|
indicatorRight, mRect.top);
|
||||||
mColorPath.close();
|
mColorPath.close();
|
||||||
float lineOffset = mLineWidth+.5f;
|
final float lineOffset = mLineWidth+.5f;
|
||||||
mEdgePath.moveTo(indicatorLeft+lineOffset, mRect.top);
|
mEdgePath.moveTo(-xoff+lineOffset, 0);
|
||||||
mEdgePath.lineTo(-1+lineOffset, 0);
|
mEdgePath.cubicTo(-xoff+lineOffset, midTopY,
|
||||||
mEdgePath.moveTo(indicatorRight-lineOffset, mRect.top);
|
indicatorLeft+lineOffset, midBottomY,
|
||||||
mEdgePath.lineTo(width-lineOffset, 0);
|
indicatorLeft+lineOffset, mRect.top);
|
||||||
|
mEdgePath.moveTo(width+xoff-1-lineOffset, 0);
|
||||||
|
mEdgePath.cubicTo(width+xoff-1-lineOffset, midTopY,
|
||||||
|
indicatorRight-lineOffset, midBottomY,
|
||||||
|
indicatorRight-lineOffset, mRect.top);
|
||||||
}
|
}
|
||||||
mLastInterestingLeft = indicatorLeft;
|
mLastInterestingLeft = indicatorLeft;
|
||||||
mLastInterestingRight = indicatorRight;
|
mLastInterestingRight = indicatorRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mColorPath.isEmpty()) {
|
if (!mEdgePath.isEmpty()) {
|
||||||
canvas.drawPath(mEdgePath, mEdgeGradientPaint);
|
canvas.drawPath(mEdgePath, mEdgeGradientPaint);
|
||||||
canvas.drawPath(mColorPath, mColorGradientPaint);
|
canvas.drawPath(mColorPath, mColorGradientPaint);
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ import android.os.StatFs;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -43,6 +44,7 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.AbsListView;
|
import android.widget.AbsListView;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
@@ -57,7 +59,6 @@ import android.widget.AdapterView.OnItemClickListener;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
final class CanBeOnSdCardChecker {
|
final class CanBeOnSdCardChecker {
|
||||||
final IPackageManager mPm;
|
final IPackageManager mPm;
|
||||||
@@ -118,7 +119,7 @@ public class ManageApplications extends TabActivity implements
|
|||||||
|
|
||||||
// constant value that can be used to check return code from sub activity.
|
// constant value that can be used to check return code from sub activity.
|
||||||
private static final int INSTALLED_APP_DETAILS = 1;
|
private static final int INSTALLED_APP_DETAILS = 1;
|
||||||
|
|
||||||
// sort order that can be changed through the menu can be sorted alphabetically
|
// sort order that can be changed through the menu can be sorted alphabetically
|
||||||
// or size(descending)
|
// or size(descending)
|
||||||
private static final int MENU_OPTIONS_BASE = 0;
|
private static final int MENU_OPTIONS_BASE = 0;
|
||||||
@@ -676,6 +677,18 @@ public class ManageApplications extends TabActivity implements
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_SEARCH && event.isTracking()) {
|
||||||
|
if (mCurView != VIEW_RUNNING) {
|
||||||
|
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||||
|
.showSoftInputUnchecked(0, null);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onKeyUp(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||||
long id) {
|
long id) {
|
||||||
@@ -738,8 +751,8 @@ public class ManageApplications extends TabActivity implements
|
|||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
ApplicationsState.AppEntry ae = mApplicationsAdapter.getAppEntry(i);
|
ApplicationsState.AppEntry ae = mApplicationsAdapter.getAppEntry(i);
|
||||||
appStorage += ae.codeSize + ae.dataSize;
|
appStorage += ae.codeSize + ae.dataSize;
|
||||||
freeStorage += ae.cacheSize;
|
|
||||||
}
|
}
|
||||||
|
freeStorage += mApplicationsState.sumCacheSizes();
|
||||||
}
|
}
|
||||||
if (newLabel != null) {
|
if (newLabel != null) {
|
||||||
mStorageChartLabel.setText(newLabel);
|
mStorageChartLabel.setText(newLabel);
|
||||||
@@ -831,6 +844,8 @@ public class ManageApplications extends TabActivity implements
|
|||||||
} else if (TAB_SDCARD.equalsIgnoreCase(tabId)) {
|
} else if (TAB_SDCARD.equalsIgnoreCase(tabId)) {
|
||||||
newOption = FILTER_APPS_SDCARD;
|
newOption = FILTER_APPS_SDCARD;
|
||||||
} else if (TAB_RUNNING.equalsIgnoreCase(tabId)) {
|
} else if (TAB_RUNNING.equalsIgnoreCase(tabId)) {
|
||||||
|
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||||
|
.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
|
||||||
selectView(VIEW_RUNNING);
|
selectView(VIEW_RUNNING);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -285,6 +285,8 @@ public class BatteryHistoryChart extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
mTextPaint.setColor(textColor.getDefaultColor());
|
mTextPaint.setColor(textColor.getDefaultColor());
|
||||||
mTextPaint.setTextSize(textSize);
|
mTextPaint.setTextSize(textSize);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user