Merge change 1418 into donut
* changes:
Show locale names in alphabetical order, in their own language.
diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml
index 7c8a672..13d3b10 100644
--- a/res/layout/installed_app_details.xml
+++ b/res/layout/installed_app_details.xml
@@ -28,9 +28,51 @@
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:orientation="vertical">
- <include
- layout="@layout/manage_applications_item"
- android:id="@+id/app_snippet"/>
+
+ <!-- App snippet -->
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_alignParentLeft="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="6dip"
+ android:paddingBottom="6dip"
+ android:paddingRight="6dip"
+ android:paddingLeft="6dip" >
+ <!-- application name -->
+ <TextView android:id="@+id/app_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:layout_marginBottom="2dip" />
+ <!-- application version -->
+ <TextView android:id="@+id/app_version"
+ android:layout_marginTop="-4dip"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+
+ <!-- application icon -->
+ <ImageView android:id="@+id/app_icon"
+ android:layout_width="@android:dimen/app_icon_size"
+ android:layout_height="@android:dimen/app_icon_size"
+ android:layout_alignParentRight="true"
+ android:paddingTop="6dip"
+ android:paddingBottom="6dip"
+ android:paddingRight="6dip"
+ android:scaleType="fitCenter" />
+ </RelativeLayout>
+
<TextView
style="?android:attr/listSeparatorTextViewStyle"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 19d145a..f4a6846 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1274,6 +1274,8 @@
<string name="uninstall_text">Uninstall</string>
<!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for exampel, remove all cached emails for an Email app) -->
<string name="clear_user_data_text">Clear data</string>
+ <!-- Manage applications, restore updated system application to factory version -->
+ <string name="app_factory_reset">Factory reset</string>
<!-- Manage applications, individual application info screen, screen, message text under Launch by default heading. This is present if the app is set as a default for some actions. -->
<string name="auto_launch_enable_text">You have selected to launch this application by default for some actions.</string>
<!-- Manage applications, individual application screen, text under Launch by default heading if the app is NOT a default for actions -->
@@ -1319,12 +1321,22 @@
found in the list of installed applications.</string>
<!-- Manage applications, individual application dialog box message. Shown when there was an error trying to clear the data. -->
<string name="clear_data_failed">Unable to clear application data.</string>
+ <!-- Manage applications, factory reset dialog title for system applications. -->
+ <string name="app_factory_reset_dlg_title">Factory reset system app</string>
+ <!-- Manage applications, factory reset option dialog text for system applications. -->
+ <string name="app_factory_reset_dlg_text">Do you want to fallback to factory version of system application?</string>
+ <!-- Manage applications, title for dialog if clear data fails-->
+ <string name="clear_failed_dlg_title">Clear data</string>
+ <!-- Manage applications, text for dialog if clear data fails-->
+ <string name="clear_failed_dlg_text">Failed clearing data for application</string>
<!-- Manage applications, individual application info screen, text that appears under the "Permissions" heading. This describes the permissions that the application has. -->
<string name="security_settings_desc">This application can access the following on your phone:</string>
<string name="computing_size">Computing\u2026</string>
<string name="invalid_size_value">Unable to compute package size</string>
<!-- String displayed when list is empty -->
<string name="empty_list_msg">You do not have any third-party apps installed.</string>
+ <!-- Manage applications, version string displayed in app snippet -->
+ <string name="version_text">version <xliff:g id="version_num">%1$s</xliff:g></string>
<!-- Language Settings --> <skip />
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings realted to locale and text -->
diff --git a/src/com/android/settings/InstalledAppDetails.java b/src/com/android/settings/InstalledAppDetails.java
index 692fc8e..5a4e672 100644
--- a/src/com/android/settings/InstalledAppDetails.java
+++ b/src/com/android/settings/InstalledAppDetails.java
@@ -22,13 +22,16 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -36,6 +39,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.text.format.Formatter;
import android.util.Config;
import android.util.Log;
@@ -64,9 +68,8 @@
private ApplicationInfo mAppInfo;
private Button mAppButton;
private Button mActivitiesButton;
- private boolean mCanUninstall;
- private boolean localLOGV=Config.LOGV || false;
- private TextView mAppSnippetSize;
+ private boolean localLOGV = false;
+ private TextView mAppVersion;
private TextView mTotalSize;
private TextView mAppSize;
private TextView mDataSize;
@@ -100,10 +103,18 @@
private CharSequence mComputingStr;
private CharSequence mAppButtonText;
+ // Dialog identifiers used in showDialog
+ private static final int DLG_BASE = 0;
+ private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
+ private static final int DLG_FACTORY_RESET = DLG_BASE + 2;
+ private static final int DLG_APP_NOT_FOUND = DLG_BASE + 3;
+ private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 4;
+
// Possible btn states
private enum AppButtonStates {
CLEAR_DATA,
UNINSTALL,
+ FACTORY_RESET,
NONE
}
private AppButtonStates mAppButtonState;
@@ -127,14 +138,6 @@
}
};
- private boolean isUninstallable() {
- if (((mAppInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) &&
- ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0)) {
- return false;
- }
- return true;
- }
-
class ClearUserDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(CLEAR_USER_DATA);
@@ -154,7 +157,7 @@
}
}
-
+
class ClearCacheObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(CLEAR_CACHE);
@@ -170,40 +173,13 @@
return Formatter.formatFileSize(this, size);
}
- private void setAppBtnState() {
- boolean visible = false;
- if(mCanUninstall) {
- //app can clear user data
- if((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
- == ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) {
- mAppButtonText = getText(R.string.clear_user_data_text);
- mAppButtonState = AppButtonStates.CLEAR_DATA;
- visible = true;
- } else {
- //hide button if diableClearUserData is set
- visible = false;
- mAppButtonState = AppButtonStates.NONE;
- }
- } else {
- visible = true;
- mAppButtonState = AppButtonStates.UNINSTALL;
- mAppButtonText = getText(R.string.uninstall_text);
- }
- if(visible) {
- mAppButton.setText(mAppButtonText);
- mAppButton.setVisibility(View.VISIBLE);
- } else {
- mAppButton.setVisibility(View.GONE);
- }
- }
-
/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- //get package manager
+ // Get package manager
mPm = getPackageManager();
- //get application's name from intent
+ // Get application's name from intent
Intent intent = getIntent();
final String packageName = intent.getStringExtra(ManageApplications.APP_PKG_NAME);
mComputingStr = getText(R.string.computing_size);
@@ -217,38 +193,26 @@
PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
Log.e(TAG, "Exception when retrieving package:"+packageName, e);
- displayErrorDialog(R.string.app_not_found_dlg_text, true, true);
+ showDialogInner(DLG_APP_NOT_FOUND);
+ return;
}
- setContentView(R.layout.installed_app_details);
- ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm));
- //set application name TODO version
- CharSequence appName = mAppInfo.loadLabel(mPm);
- if(appName == null) {
- appName = getString(_UNKNOWN_APP);
- }
- ((TextView)findViewById(R.id.app_name)).setText(appName);
- mAppSnippetSize = ((TextView)findViewById(R.id.app_size));
- mAppSnippetSize.setText(totalSizeStr);
+ setContentView(R.layout.installed_app_details);
//TODO download str and download url
- //set values on views
+ // Set default values on sizes
mTotalSize = (TextView)findViewById(R.id.total_size_text);
mTotalSize.setText(totalSizeStr);
mAppSize = (TextView)findViewById(R.id.application_size_text);
mAppSize.setText(appSizeStr);
mDataSize = (TextView)findViewById(R.id.data_size_text);
mDataSize.setText(dataSizeStr);
-
+ // Get AppButton
mAppButton = ((Button)findViewById(R.id.uninstall_button));
- //determine if app is a system app
- mCanUninstall = !isUninstallable();
- if(localLOGV) Log.i(TAG, "Is systemPackage "+mCanUninstall);
- setAppBtnState();
+ // Get ManageSpaceButton
mManageSpaceButton = (Button)findViewById(R.id.manage_space_button);
if(mAppInfo.manageSpaceActivityName != null) {
mManageSpaceButton.setVisibility(View.VISIBLE);
mManageSpaceButton.setOnClickListener(this);
}
-
// Cache section
mCachePanel = findViewById(R.id.cache_panel);
mCacheSize = (TextView) findViewById(R.id.cache_size_text);
@@ -256,17 +220,16 @@
mClearCacheButton = (Button) findViewById(R.id.clear_cache_button);
mForceStopButton = (Button) findViewById(R.id.force_stop_button);
mForceStopButton.setOnClickListener(this);
-
- //clear activities
+ // Get list of preferred activities
mActivitiesButton = (Button)findViewById(R.id.clear_activities_button);
List<ComponentName> prefActList = new ArrayList<ComponentName>();
- //intent list cannot be null. so pass empty list
+ // Intent list cannot be null. so pass empty list
List<IntentFilter> intentList = new ArrayList<IntentFilter>();
mPm.getPreferredActivities(intentList, prefActList, packageName);
if(localLOGV) Log.i(TAG, "Have "+prefActList.size()+" number of activities in prefered list");
TextView autoLaunchView = (TextView)findViewById(R.id.auto_launch);
if(prefActList.size() <= 0) {
- //disable clear activities button
+ // Disable clear activities button
autoLaunchView.setText(R.string.auto_launch_disable_text);
mActivitiesButton.setEnabled(false);
} else {
@@ -274,7 +237,7 @@
mActivitiesButton.setOnClickListener(this);
}
- // security permissions section
+ // Security permissions section
LinearLayout permsView = (LinearLayout) findViewById(R.id.permissions_section);
AppSecurityPermissions asp = new AppSecurityPermissions(this, packageName);
if(asp.getPermissionCount() > 0) {
@@ -288,29 +251,85 @@
}
}
- @Override
- public void onStart() {
- super.onStart();
+ private void refreshAppAttributes(PackageInfo pkgInfo) {
+ setAppLabelAndIcon();
+ // Version number of application
+ setAppVersion(pkgInfo);
+ setAppBtnState();
+ // Refresh size info
if (mAppInfo != null && mAppInfo.packageName != null) {
mPm.getPackageSizeInfo(mAppInfo.packageName, mSizeObserver);
}
}
- private void displayErrorDialog(int msgId, final boolean finish, final boolean changed) {
- //display confirmation dialog
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.app_not_found_dlg_title))
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(msgId))
- .setNeutralButton(getString(R.string.dlg_ok),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- //force to recompute changed value
- setIntentAndFinish(finish, changed);
- }
+ // Utility method to set applicaiton label and icon.
+ private void setAppLabelAndIcon() {
+ ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm));
+ //set application name TODO version
+ CharSequence appName = mAppInfo.loadLabel(mPm);
+ if(appName == null) {
+ appName = getString(_UNKNOWN_APP);
+ }
+ ((TextView)findViewById(R.id.app_name)).setText(appName);
+ }
+
+ // Utility method to set application version
+ private void setAppVersion(PackageInfo pkgInfo) {
+ // Version number of application
+ mAppVersion = ((TextView)findViewById(R.id.app_version));
+ if (pkgInfo != null) {
+ mAppVersion.setVisibility(View.VISIBLE);
+ mAppVersion.setText(getString(R.string.version_text,
+ String.valueOf(pkgInfo.versionCode)));
+ } else {
+ mAppVersion.setVisibility(View.GONE);
+ }
+ }
+
+ // Utility method to set button state
+ private void setAppBtnState() {
+ boolean visible = true;
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ mAppButtonState = AppButtonStates.FACTORY_RESET;
+ mAppButtonText = getText(R.string.app_factory_reset);
+ } else {
+ if ((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) {
+ // Hide button if diableClearUserData is set
+ mAppButtonState = AppButtonStates.NONE;
+ visible = false;
+ } else {
+ mAppButtonState = AppButtonStates.CLEAR_DATA;
+ mAppButtonText = getText(R.string.clear_user_data_text);
}
- )
- .show();
+ }
+ } else {
+ mAppButtonState = AppButtonStates.UNINSTALL;
+ mAppButtonText = getText(R.string.uninstall_text);
+ }
+ if(visible) {
+ mAppButton.setText(mAppButtonText);
+ mAppButton.setVisibility(View.VISIBLE);
+ } else {
+ mAppButton.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ PackageInfo pkgInfo;
+ // Get application info again to refresh changed properties of application
+ try {
+ mAppInfo = mPm.getApplicationInfo(mAppInfo.packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ pkgInfo = mPm.getPackageInfo(mAppInfo.packageName, 0);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Exception when retrieving package:" + mAppInfo.packageName, e);
+ showDialogInner(DLG_APP_NOT_FOUND);
+ return;
+ }
+ refreshAppAttributes(pkgInfo);
}
private void setIntentAndFinish(boolean finish, boolean appChanged) {
@@ -337,7 +356,6 @@
mSizeInfo = newPs;
String str = getSizeStr(newTot);
mTotalSize.setText(str);
- mAppSnippetSize.setText(str);
mAppSize.setText(getSizeStr(newPs.codeSize));
mDataSize.setText(getSizeStr(newPs.dataSize));
mCacheSize.setText(getSizeStr(newPs.cacheSize));
@@ -346,7 +364,6 @@
if(newTot != oldTot) {
String str = getSizeStr(newTot);
mTotalSize.setText(str);
- mAppSnippetSize.setText(str);
changed = true;
}
if(newPs.codeSize != mSizeInfo.codeSize) {
@@ -421,14 +438,76 @@
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
if(!res) {
- //doesnt initiate clear. some error. should not happen but just log error for now
+ // Clearing data failed for some obscure reason. Just log error for now
Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
- displayErrorDialog(R.string.clear_data_failed, false, false);
+ showDialogInner(DLG_CANNOT_CLEAR_DATA);
} else {
mAppButton.setText(R.string.recompute_size);
}
}
+ private void showDialogInner(int id) {
+ //removeDialog(id);
+ showDialog(id);
+ }
+
+ @Override
+ public Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DLG_CLEAR_DATA:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.clear_data_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.clear_data_dlg_text))
+ .setPositiveButton(R.string.dlg_ok, this)
+ .setNegativeButton(R.string.dlg_cancel, this)
+ .create();
+ case DLG_FACTORY_RESET:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.app_factory_reset_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.app_factory_reset_dlg_text))
+ .setPositiveButton(R.string.dlg_ok, this)
+ .setNegativeButton(R.string.dlg_cancel, this)
+ .create();
+ case DLG_APP_NOT_FOUND:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.app_not_found_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.app_not_found_dlg_title))
+ .setNeutralButton(getString(R.string.dlg_ok),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ //force to recompute changed value
+ setIntentAndFinish(true, true);
+ }
+ })
+ .create();
+ case DLG_CANNOT_CLEAR_DATA:
+ return new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.clear_failed_dlg_title))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getString(R.string.clear_failed_dlg_text))
+ .setNeutralButton(R.string.dlg_ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ //force to recompute changed value
+ setIntentAndFinish(false, false);
+ }
+ })
+ .create();
+ }
+ return null;
+ }
+
+ private void uninstallPkg(String packageName) {
+ // Create new intent to launch Uninstaller activity
+ Uri packageURI = Uri.parse("package:"+packageName);
+ Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
+ startActivity(uninstallIntent);
+ setIntentAndFinish(true, true);
+ }
+
/*
* Method implementing functionality of buttons clicked
* @see android.view.View.OnClickListener#onClick(android.view.View)
@@ -436,21 +515,12 @@
public void onClick(View v) {
String packageName = mAppInfo.packageName;
if(v == mAppButton) {
- if(mCanUninstall) {
- //display confirmation dialog
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.clear_data_dlg_title))
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.clear_data_dlg_text))
- .setPositiveButton(R.string.dlg_ok, this)
- .setNegativeButton(R.string.dlg_cancel, this)
- .show();
- } else {
- //create new intent to launch Uninstaller activity
- Uri packageURI = Uri.parse("package:"+packageName);
- Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
- startActivity(uninstallIntent);
- setIntentAndFinish(true, true);
+ if (mAppButtonState == AppButtonStates.CLEAR_DATA) {
+ showDialogInner(DLG_CLEAR_DATA);
+ } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) {
+ showDialogInner(DLG_FACTORY_RESET);
+ } else if (mAppButtonState == AppButtonStates.UNINSTALL) {
+ uninstallPkg(packageName);
}
} else if(v == mActivitiesButton) {
mPm.clearPackagePreferredActivities(packageName);
@@ -474,8 +544,13 @@
public void onClick(DialogInterface dialog, int which) {
if(which == AlertDialog.BUTTON_POSITIVE) {
- //invoke uninstall or clear user data based on sysPackage
- initiateClearUserDataForSysPkg();
+ if (mAppButtonState == AppButtonStates.CLEAR_DATA) {
+ // Invoke uninstall or clear user data based on sysPackage
+ initiateClearUserDataForSysPkg();
+ } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) {
+ // Initiate package installer to delete package
+ uninstallPkg(mAppInfo.packageName);
+ }
} else {
//cancel do nothing just retain existing screen
}