Merge commit '9073dc69b110cbd0d4bebd128ed6cc2b24a16695' * commit '9073dc69b110cbd0d4bebd128ed6cc2b24a16695': Expand apps' control over the settings restore process
This commit is contained in:
@@ -4695,6 +4695,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="killAfterRestore"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843416"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="label"
|
||||
type="int"
|
||||
transient="false"
|
||||
@@ -6477,6 +6488,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="restoreNeedsApplication"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843417"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="right"
|
||||
type="int"
|
||||
transient="false"
|
||||
|
||||
@@ -1118,6 +1118,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
mi.writeToParcel(reply, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
case KILL_APPLICATION_PROCESS_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
String processName = data.readString();
|
||||
int uid = data.readInt();
|
||||
killApplicationProcess(processName, uid);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
@@ -2448,6 +2457,18 @@ class ActivityManagerProxy implements IActivityManager
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
}
|
||||
|
||||
|
||||
public void killApplicationProcess(String processName, int uid) throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||
data.writeString(processName);
|
||||
data.writeInt(uid);
|
||||
mRemote.transact(KILL_APPLICATION_PROCESS_TRANSACTION, data, reply, 0);
|
||||
reply.readException();
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
}
|
||||
|
||||
private IBinder mRemote;
|
||||
}
|
||||
|
||||
@@ -1463,6 +1463,10 @@ public final class ActivityThread {
|
||||
queueOrSendMessage(H.EXIT_APPLICATION, null);
|
||||
}
|
||||
|
||||
public final void scheduleSuicide() {
|
||||
queueOrSendMessage(H.SUICIDE, null);
|
||||
}
|
||||
|
||||
public void requestThumbnail(IBinder token) {
|
||||
queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
|
||||
}
|
||||
@@ -1752,7 +1756,8 @@ public final class ActivityThread {
|
||||
public static final int RELAUNCH_ACTIVITY = 126;
|
||||
public static final int PROFILER_CONTROL = 127;
|
||||
public static final int CREATE_BACKUP_AGENT = 128;
|
||||
public static final int DESTROY_BACKUP_AGENT = 129;
|
||||
public static final int DESTROY_BACKUP_AGENT = 129;
|
||||
public static final int SUICIDE = 130;
|
||||
String codeToString(int code) {
|
||||
if (localLOGV) {
|
||||
switch (code) {
|
||||
@@ -1786,6 +1791,7 @@ public final class ActivityThread {
|
||||
case PROFILER_CONTROL: return "PROFILER_CONTROL";
|
||||
case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
|
||||
case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
|
||||
case SUICIDE: return "SUICIDE";
|
||||
}
|
||||
}
|
||||
return "(unknown)";
|
||||
@@ -1894,6 +1900,11 @@ public final class ActivityThread {
|
||||
case DESTROY_BACKUP_AGENT:
|
||||
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
|
||||
break;
|
||||
case SUICIDE:
|
||||
{
|
||||
Process.killProcess(Process.myPid());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +258,13 @@ public abstract class ApplicationThreadNative extends Binder
|
||||
return true;
|
||||
}
|
||||
|
||||
case SCHEDULE_SUICIDE_TRANSACTION:
|
||||
{
|
||||
data.enforceInterface(IApplicationThread.descriptor);
|
||||
scheduleSuicide();
|
||||
return true;
|
||||
}
|
||||
|
||||
case REQUEST_THUMBNAIL_TRANSACTION:
|
||||
{
|
||||
data.enforceInterface(IApplicationThread.descriptor);
|
||||
@@ -652,7 +659,15 @@ class ApplicationThreadProxy implements IApplicationThread {
|
||||
IBinder.FLAG_ONEWAY);
|
||||
data.recycle();
|
||||
}
|
||||
|
||||
|
||||
public final void scheduleSuicide() throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
data.writeInterfaceToken(IApplicationThread.descriptor);
|
||||
mRemote.transact(SCHEDULE_SUICIDE_TRANSACTION, data, null,
|
||||
IBinder.FLAG_ONEWAY);
|
||||
data.recycle();
|
||||
}
|
||||
|
||||
public final void requestThumbnail(IBinder token)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
|
||||
@@ -158,6 +158,7 @@ public interface IActivityManager extends IInterface {
|
||||
throws RemoteException;
|
||||
public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
|
||||
public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException;
|
||||
public void killApplicationProcess(String processName, int uid) throws RemoteException;
|
||||
|
||||
public boolean startInstrumentation(ComponentName className, String profileFile,
|
||||
int flags, Bundle arguments, IInstrumentationWatcher watcher)
|
||||
@@ -433,4 +434,5 @@ public interface IActivityManager extends IInterface {
|
||||
int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
|
||||
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
|
||||
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
|
||||
int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ public interface IApplicationThread extends IInterface {
|
||||
IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
|
||||
Configuration config, Map<String, IBinder> services) throws RemoteException;
|
||||
void scheduleExit() throws RemoteException;
|
||||
void scheduleSuicide() throws RemoteException;
|
||||
void requestThumbnail(IBinder token) throws RemoteException;
|
||||
void scheduleConfigurationChanged(Configuration config) throws RemoteException;
|
||||
void updateTimeZone() throws RemoteException;
|
||||
@@ -133,4 +134,5 @@ public interface IApplicationThread extends IInterface {
|
||||
int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
|
||||
int SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
|
||||
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
|
||||
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
|
||||
}
|
||||
|
||||
@@ -184,7 +184,29 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int FLAG_ALLOW_BACKUP = 1<<14;
|
||||
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: this is false if the application has set
|
||||
* its android:killAfterRestore to false, true otherwise.
|
||||
*
|
||||
* <p>If android:allowBackup is set to false or no android:backupAgent
|
||||
* is specified, this flag will be ignored.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int FLAG_KILL_AFTER_RESTORE = 1<<15;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: this is true if the application has set
|
||||
* its android:restoreNeedsApplication to true, false otherwise.
|
||||
*
|
||||
* <p>If android:allowBackup is set to false or no android:backupAgent
|
||||
* is specified, this flag will be ignored.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int FLAG_RESTORE_NEEDS_APPLICATION = 1<<16;
|
||||
|
||||
/**
|
||||
* Flags associated with the application. Any combination of
|
||||
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
|
||||
@@ -193,7 +215,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
* {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
|
||||
* {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS}.
|
||||
* {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}.
|
||||
*/
|
||||
public int flags = 0;
|
||||
|
||||
|
||||
@@ -1296,12 +1296,26 @@ public class PackageParser {
|
||||
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
|
||||
if (allowBackup) {
|
||||
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
|
||||
|
||||
// backupAgent, killAfterRestore, and restoreNeedsApplication are only relevant
|
||||
// if backup is possible for the given application.
|
||||
String backupAgent = sa.getNonResourceString(
|
||||
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent);
|
||||
if (backupAgent != null) {
|
||||
ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
|
||||
Log.v(TAG, "android:backupAgent = " + ai.backupAgentName
|
||||
+ " from " + pkgName + "+" + backupAgent);
|
||||
|
||||
if (sa.getBoolean(
|
||||
com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
|
||||
true)) {
|
||||
ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
|
||||
}
|
||||
if (sa.getBoolean(
|
||||
com.android.internal.R.styleable.AndroidManifestApplication_restoreNeedsApplication,
|
||||
false)) {
|
||||
ai.flags |= ApplicationInfo.FLAG_RESTORE_NEEDS_APPLICATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1113,6 +1113,7 @@
|
||||
android:label="@string/android_system_label"
|
||||
android:allowClearUserData="false"
|
||||
android:backupAgent="com.android.server.SystemBackupAgent"
|
||||
android:killAfterRestore="false"
|
||||
android:icon="@drawable/ic_launcher_android">
|
||||
<activity android:name="com.android.internal.app.ChooserActivity"
|
||||
android:theme="@style/Theme.Dialog.Alert"
|
||||
|
||||
@@ -580,6 +580,15 @@
|
||||
<!-- This is not the attribute you are looking for. -->
|
||||
<attr name="allowBackup" format="boolean" />
|
||||
|
||||
<!-- Whether the application in question should be terminated after its
|
||||
settings have been restored. The default is to do so. -->
|
||||
<attr name="killAfterRestore" format="boolean" />
|
||||
|
||||
<!-- Whether the application needs to have its own Application subclass
|
||||
active during restore. The default is to run restore with a minimal
|
||||
Application class to avoid interference with application logic. -->
|
||||
<attr name="restoreNeedsApplication" format="boolean" />
|
||||
|
||||
<!-- The <code>manifest</code> tag is the root of an
|
||||
<code>AndroidManifest.xml</code> file,
|
||||
describing the contents of an Android package (.apk) file. One
|
||||
@@ -656,6 +665,8 @@
|
||||
<attr name="testOnly" />
|
||||
<attr name="backupAgent" />
|
||||
<attr name="allowBackup" />
|
||||
<attr name="killAfterRestore" />
|
||||
<attr name="restoreNeedsApplication" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>permission</code> tag declares a security permission that can be
|
||||
|
||||
@@ -1155,10 +1155,11 @@
|
||||
<public type="attr" name="wallpaperActivityOpenExitAnimation" />
|
||||
<public type="attr" name="wallpaperActivityCloseEnterAnimation" />
|
||||
<public type="attr" name="wallpaperActivityCloseExitAnimation" />
|
||||
<public type="attr" name="supportsUploading" />
|
||||
<public type="attr" name="killAfterRestore" />
|
||||
<public type="attr" name="restoreNeedsApplication" />
|
||||
|
||||
<public type="style" name="Theme.Wallpaper" />
|
||||
<public type="style" name="Theme.Wallpaper.NoTitleBar" />
|
||||
<public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
|
||||
|
||||
<public type="attr" name="supportsUploading" />
|
||||
</resources>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
android:label="@string/app_label"
|
||||
android:process="system"
|
||||
android:backupAgent="SettingsBackupAgent"
|
||||
android:killAfterRestore="false"
|
||||
android:icon="@drawable/ic_launcher_settings">
|
||||
|
||||
<provider android:name="SettingsProvider" android:authorities="settings"
|
||||
|
||||
@@ -557,7 +557,12 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
Log.v(TAG, "Adding " + targetPkgs.size() + " backup participants:");
|
||||
for (PackageInfo p : targetPkgs) {
|
||||
Log.v(TAG, " " + p + " agent=" + p.applicationInfo.backupAgentName
|
||||
+ " uid=" + p.applicationInfo.uid);
|
||||
+ " uid=" + p.applicationInfo.uid
|
||||
+ " killAfterRestore="
|
||||
+ (((p.applicationInfo.flags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0) ? "true" : "false")
|
||||
+ " restoreNeedsApplication="
|
||||
+ (((p.applicationInfo.flags & ApplicationInfo.FLAG_RESTORE_NEEDS_APPLICATION) != 0) ? "true" : "false")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1244,11 +1249,21 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
+ "] is compatible with installed version ["
|
||||
+ packageInfo.versionCode + "]");
|
||||
|
||||
// Now perform the actual restore
|
||||
// Now perform the actual restore: first clear the app's data
|
||||
// if appropriate
|
||||
clearApplicationDataSynchronous(packageName);
|
||||
|
||||
// Then set up and bind the agent (with a restricted Application object
|
||||
// unless the application says otherwise)
|
||||
boolean useRealApp = (packageInfo.applicationInfo.flags
|
||||
& ApplicationInfo.FLAG_RESTORE_NEEDS_APPLICATION) != 0;
|
||||
if (DEBUG && useRealApp) {
|
||||
Log.v(TAG, "agent requires real Application subclass for restore");
|
||||
}
|
||||
IBackupAgent agent = bindToAgentSynchronous(
|
||||
packageInfo.applicationInfo,
|
||||
IApplicationThread.BACKUP_MODE_RESTORE);
|
||||
(useRealApp ? IApplicationThread.BACKUP_MODE_INCREMENTAL
|
||||
: IApplicationThread.BACKUP_MODE_RESTORE));
|
||||
if (agent == null) {
|
||||
Log.w(TAG, "Can't find backup agent for " + packageName);
|
||||
EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
|
||||
@@ -1256,12 +1271,26 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
continue;
|
||||
}
|
||||
|
||||
// And then finally run the restore on this agent
|
||||
try {
|
||||
processOneRestore(packageInfo, metaInfo.versionCode, agent);
|
||||
++count;
|
||||
} finally {
|
||||
// unbind even on timeout or failure, just in case
|
||||
// unbind and tidy up even on timeout or failure, just in case
|
||||
mActivityManager.unbindBackupAgent(packageInfo.applicationInfo);
|
||||
|
||||
// The agent was probably running with a stub Application object,
|
||||
// which isn't a valid run mode for the main app logic. Shut
|
||||
// down the app so that next time it's launched, it gets the
|
||||
// usual full initialization.
|
||||
if ((packageInfo.applicationInfo.flags
|
||||
& ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0) {
|
||||
if (DEBUG) Log.d(TAG, "Restore complete, killing host process of "
|
||||
+ packageInfo.applicationInfo.processName);
|
||||
mActivityManager.killApplicationProcess(
|
||||
packageInfo.applicationInfo.processName,
|
||||
packageInfo.applicationInfo.uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4914,7 +4914,34 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
|
||||
thread.getMemoryInfo(mi);
|
||||
}
|
||||
|
||||
|
||||
public void killApplicationProcess(String processName, int uid) {
|
||||
if (processName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int callerUid = Binder.getCallingUid();
|
||||
// Only the system server can kill an application
|
||||
if (callerUid == Process.SYSTEM_UID) {
|
||||
synchronized (this) {
|
||||
ProcessRecord app = getProcessRecordLocked(processName, uid);
|
||||
if (app != null) {
|
||||
try {
|
||||
app.thread.scheduleSuicide();
|
||||
} catch (RemoteException e) {
|
||||
// If the other end already died, then our work here is done.
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Process/uid not found attempting kill of "
|
||||
+ processName + " / " + uid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SecurityException(callerUid + " cannot kill app process: " +
|
||||
processName);
|
||||
}
|
||||
}
|
||||
|
||||
private void restartPackageLocked(final String packageName, int uid) {
|
||||
uninstallPackageLocked(packageName, uid, false);
|
||||
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
|
||||
|
||||
Reference in New Issue
Block a user