diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml
index 7c8a672608f..13d3b1006d5 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">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Uninstall
Clear data
+
+ Factory reset
You have selected to launch this application by default for some actions.
@@ -1319,12 +1321,22 @@
found in the list of installed applications.
Unable to clear application data.
+
+ Factory reset system app
+
+ Do you want to fallback to factory version of system application?
+
+ Clear data
+
+ Failed clearing data for application
This application can access the following on your phone:
Computing\u2026
Unable to compute package size
You do not have any third-party apps installed.
+
+ version %1$s
diff --git a/src/com/android/settings/InstalledAppDetails.java b/src/com/android/settings/InstalledAppDetails.java
index 692fc8eba45..5a4e672b9d5 100644
--- a/src/com/android/settings/InstalledAppDetails.java
+++ b/src/com/android/settings/InstalledAppDetails.java
@@ -22,13 +22,16 @@ import com.android.settings.R;
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.net.Uri;
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
}
};
- 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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
}
}
-
+
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 prefActList = new ArrayList();
- //intent list cannot be null. so pass empty list
+ // Intent list cannot be null. so pass empty list
List intentList = new ArrayList();
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
}
}
- @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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
if(newTot != oldTot) {
String str = getSizeStr(newTot);
mTotalSize.setText(str);
- mAppSnippetSize.setText(str);
changed = true;
}
if(newPs.codeSize != mSizeInfo.codeSize) {
@@ -421,14 +438,76 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene
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 class InstalledAppDetails extends Activity implements View.OnClickListene
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 class InstalledAppDetails extends Activity implements View.OnClickListene
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
}