Merge "Fix issue #3202866: system server crash"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index b5fddfa..ac0e410 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -217,8 +217,7 @@
// The rest of the 'list' options work with a restore session on the current transport
try {
- String curTransport = mBmgr.getCurrentTransport();
- mRestore = mBmgr.beginRestoreSession(curTransport);
+ mRestore = mBmgr.beginRestoreSession(null, null);
if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR);
return;
@@ -349,8 +348,7 @@
private void doRestorePackage(String pkg) {
try {
- String curTransport = mBmgr.getCurrentTransport();
- mRestore = mBmgr.beginRestoreSession(curTransport);
+ mRestore = mBmgr.beginRestoreSession(pkg, null);
if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR);
return;
@@ -378,8 +376,7 @@
try {
boolean didRestore = false;
- String curTransport = mBmgr.getCurrentTransport();
- mRestore = mBmgr.beginRestoreSession(curTransport);
+ mRestore = mBmgr.beginRestoreSession(null, null);
if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR);
return;
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 52dd707..80656a1 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -138,8 +138,8 @@
if (sService != null) {
RestoreSession session = null;
try {
- String transport = sService.getCurrentTransport();
- IRestoreSession binder = sService.beginRestoreSession(transport);
+ IRestoreSession binder = sService.beginRestoreSession(mContext.getPackageName(),
+ null);
session = new RestoreSession(mContext, binder);
result = session.restorePackage(mContext.getPackageName(), observer);
} catch (RemoteException e) {
@@ -163,8 +163,8 @@
checkServiceBinder();
if (sService != null) {
try {
- String transport = sService.getCurrentTransport();
- IRestoreSession binder = sService.beginRestoreSession(transport);
+ // All packages, current transport
+ IRestoreSession binder = sService.beginRestoreSession(null, null);
session = new RestoreSession(mContext, binder);
} catch (RemoteException e) {
Log.w(TAG, "beginRestoreSession() couldn't connect");
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 23d6351..8af59df 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -144,13 +144,25 @@
String selectBackupTransport(String transport);
/**
- * Begin a restore session with the given transport (which may differ from the
- * currently-active backup transport).
+ * Begin a restore session. Either or both of packageName and transportID
+ * may be null. If packageName is non-null, then only the given package will be
+ * considered for restore. If transportID is null, then the restore will use
+ * the current active transport.
+ * <p>
+ * This method requires the android.permission.BACKUP permission <i>except</i>
+ * when transportID is null and packageName is the name of the caller's own
+ * package. In that case, the restore session returned is suitable for supporting
+ * the BackupManager.requestRestore() functionality via RestoreSession.restorePackage()
+ * without requiring the app to hold any special permission.
*
- * @param transport The name of the transport to use for the restore operation.
+ * @param packageName The name of the single package for which a restore will
+ * be requested. May be null, in which case all packages in the restore
+ * set can be restored.
+ * @param transportID The name of the transport to use for the restore operation.
+ * May be null, in which case the current active transport is used.
* @return An interface to the restore session, or null on error.
*/
- IRestoreSession beginRestoreSession(String transportID);
+ IRestoreSession beginRestoreSession(String packageName, String transportID);
/**
* Notify the backup manager that a BackupAgent has completed the operation
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index aefe8d8..f32ae92 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6206,7 +6206,10 @@
if (applyTransformation) {
setTransformationMethod(null);
}
- setBackgroundDrawable(mEditTextMultilineBackground);
+ // mEditTextMultilineBackground is defined and used only in EditText
+ if (mEditTextMultilineBackground != null) {
+ setBackgroundDrawable(mEditTextMultilineBackground);
+ }
}
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index df03e13..20949a4 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -389,6 +389,10 @@
synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
rsnScriptSetVarV(mContext, id, slot, val);
}
+ native void rsnScriptSetVarObj(int con, int id, int slot, int val);
+ synchronized void nScriptSetVarObj(int id, int slot, int val) {
+ rsnScriptSetVarObj(mContext, id, slot, val);
+ }
native void rsnScriptCBegin(int con);
synchronized void nScriptCBegin() {
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 7d7dd6d..ea616c6 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -88,6 +88,10 @@
mRS.nScriptSetVarI(getID(), index, v ? 1 : 0);
}
+ public void setVar(int index, BaseObj o) {
+ mRS.nScriptSetVarObj(getID(), index, (o == null) ? 0 : o.getID());
+ }
+
public void setVar(int index, FieldPacker v) {
mRS.nScriptSetVarV(getID(), index, v.getData());
}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index dd84848..8888459 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -829,6 +829,13 @@
}
static void
+nScriptSetVarObj(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jint val)
+{
+ LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", con, (void *)script, slot, val);
+ rsScriptSetVarObj(con, (RsScript)script, slot, (RsObjectBase)val);
+}
+
+static void
nScriptSetVarJ(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jlong val)
{
LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", con, (void *)script, slot, val);
@@ -1335,6 +1342,7 @@
{"rsnScriptSetVarF", "(IIIF)V", (void*)nScriptSetVarF },
{"rsnScriptSetVarD", "(IIID)V", (void*)nScriptSetVarD },
{"rsnScriptSetVarV", "(III[B)V", (void*)nScriptSetVarV },
+{"rsnScriptSetVarObj", "(IIII)V", (void*)nScriptSetVarObj },
{"rsnScriptCBegin", "(I)V", (void*)nScriptCBegin },
{"rsnScriptCSetScript", "(I[BII)V", (void*)nScriptCSetScript },
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index ac9abe0..76db14f 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -280,6 +280,12 @@
param int value
}
+ScriptSetVarObj {
+ param RsScript s
+ param uint32_t slot
+ param RsObjectBase value
+ }
+
ScriptSetVarJ {
param RsScript s
param uint32_t slot
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index 4ffdbfd..efdc626 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -67,6 +67,22 @@
}
}
+void Script::setVarObj(uint32_t slot, ObjectBase *val) {
+ ObjectBase **destPtr = ((ObjectBase ***)mEnviroment.mFieldAddress)[slot];
+
+ if (destPtr) {
+ if (val != NULL) {
+ val->incSysRef();
+ }
+ if (*destPtr) {
+ (*destPtr)->decSysRef();
+ }
+ *destPtr = val;
+ } else {
+ LOGV("Calling setVarObj on slot = %i which is null. This is dangerous because the script will not hold a ref count on the object.", slot);
+ }
+}
+
namespace android {
namespace renderscript {
@@ -103,6 +119,12 @@
s->setVar(slot, &value, sizeof(value));
}
+void rsi_ScriptSetVarObj(Context *rsc, RsScript vs, uint32_t slot, RsObjectBase value) {
+ Script *s = static_cast<Script *>(vs);
+ ObjectBase *o = static_cast<ObjectBase *>(value);
+ s->setVarObj(slot, o);
+}
+
void rsi_ScriptSetVarJ(Context *rsc, RsScript vs, uint32_t slot, long long value) {
Script *s = static_cast<Script *>(vs);
s->setVar(slot, &value, sizeof(value));
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 9b6d8a9..bad095b 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -61,6 +61,7 @@
void initSlots();
void setSlot(uint32_t slot, Allocation *a);
void setVar(uint32_t slot, const void *val, uint32_t len);
+ void setVarObj(uint32_t slot, ObjectBase *val);
virtual void runForEach(Context *rsc,
const Allocation * ain,
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 6a86076..bebd013 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -2399,15 +2399,45 @@
}
// Hand off a restore session
- public IRestoreSession beginRestoreSession(String transport) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "beginRestoreSession");
+ public IRestoreSession beginRestoreSession(String packageName, String transport) {
+ if (DEBUG) Slog.v(TAG, "beginRestoreSession: pkg=" + packageName
+ + " transport=" + transport);
+
+ boolean needPermission = true;
+ if (transport == null) {
+ transport = mCurrentTransport;
+
+ if (packageName != null) {
+ PackageInfo app = null;
+ try {
+ app = mPackageManager.getPackageInfo(packageName, 0);
+ } catch (NameNotFoundException nnf) {
+ Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName);
+ throw new IllegalArgumentException("Package " + packageName + " not found");
+ }
+
+ if (app.applicationInfo.uid == Binder.getCallingUid()) {
+ // So: using the current active transport, and the caller has asked
+ // that its own package will be restored. In this narrow use case
+ // we do not require the caller to hold the permission.
+ needPermission = false;
+ }
+ }
+ }
+
+ if (needPermission) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "beginRestoreSession");
+ } else {
+ if (DEBUG) Slog.d(TAG, "restoring self on current transport; no permission needed");
+ }
synchronized(this) {
if (mActiveRestoreSession != null) {
Slog.d(TAG, "Restore session requested but one already active");
return null;
}
- mActiveRestoreSession = new ActiveRestoreSession(transport);
+ mActiveRestoreSession = new ActiveRestoreSession(packageName, transport);
}
return mActiveRestoreSession;
}
@@ -2427,10 +2457,12 @@
class ActiveRestoreSession extends IRestoreSession.Stub {
private static final String TAG = "RestoreSession";
+ private String mPackageName;
private IBackupTransport mRestoreTransport = null;
RestoreSet[] mRestoreSets = null;
- ActiveRestoreSession(String transport) {
+ ActiveRestoreSession(String packageName, String transport) {
+ mPackageName = packageName;
mRestoreTransport = getTransport(transport);
}
@@ -2466,11 +2498,16 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"performRestore");
- if (DEBUG) Slog.d(TAG, "performRestore token=" + Long.toHexString(token)
+ if (DEBUG) Slog.d(TAG, "restoreAll token=" + Long.toHexString(token)
+ " observer=" + observer);
if (mRestoreTransport == null || mRestoreSets == null) {
- Slog.e(TAG, "Ignoring performRestore() with no restore set");
+ Slog.e(TAG, "Ignoring restoreAll() with no restore set");
+ return -1;
+ }
+
+ if (mPackageName != null) {
+ Slog.e(TAG, "Ignoring restoreAll() on single-package session");
return -1;
}
@@ -2495,6 +2532,14 @@
public synchronized int restorePackage(String packageName, IRestoreObserver observer) {
if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer);
+ if (mPackageName != null) {
+ if (! mPackageName.equals(packageName)) {
+ Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName
+ + " on session for package " + mPackageName);
+ return -1;
+ }
+ }
+
PackageInfo app = null;
try {
app = mPackageManager.getPackageInfo(packageName, 0);
@@ -2529,6 +2574,7 @@
// the app has never been backed up from this device -- there's nothing
// to do but return failure.
if (token == 0) {
+ if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
return -1;
}
@@ -2543,9 +2589,6 @@
}
public synchronized void endRestoreSession() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "endRestoreSession");
-
if (DEBUG) Slog.d(TAG, "endRestoreSession");
synchronized (this) {