Multi-user - wallpaper service
- Allow each user to have their own wallpaper (live or static).
- Migrate old wallpaper on upgrade.
- Update SystemBackupAgent to backup/restore from primary user's
new wallpaper directory.
Reduce dependency on Binder.getOrigCallingUser() by passing the
userId for bindService.
Change-Id: I19c8c3296d3d2efa7f28f951d4b84407489e2166
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index dfea728..5a36466 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -670,8 +670,9 @@
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
+ int userId = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
- int res = bindService(app, token, service, resolvedType, conn, fl);
+ int res = bindService(app, token, service, resolvedType, conn, fl, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -2288,7 +2289,7 @@
}
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
- int flags) throws RemoteException {
+ int flags, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -2298,6 +2299,7 @@
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
+ data.writeInt(userId);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 37900b6..ebf692a 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1125,6 +1125,12 @@
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
+ return bindService(service, conn, flags, UserId.getUserId(Process.myUid()));
+ }
+
+ /** @hide */
+ @Override
+ public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
@@ -1143,7 +1149,7 @@
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
- sd, flags);
+ sd, flags, userId);
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a62f724..7deb615 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -166,7 +166,7 @@
int id, Notification notification, boolean keepNotification) throws RemoteException;
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
- IServiceConnection connection, int flags) throws RemoteException;
+ IServiceConnection connection, int flags, int userId) throws RemoteException;
public boolean unbindService(IServiceConnection connection) throws RemoteException;
public void publishService(IBinder token,
Intent intent, IBinder service) throws RemoteException;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c1e28b0..f6d2612 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -30,6 +30,7 @@
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 170171e..a74a268 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -38,15 +38,23 @@
private static final boolean DEBUG = false;
// This path must match what the WallpaperManagerService uses
- private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
+ // TODO: Will need to change if backing up non-primary user's wallpaper
+ public static final String WALLPAPER_IMAGE = "/data/system/users/0/wallpaper";
+ public static final String WALLPAPER_INFO = "/data/system/users/0/wallpaper_info.xml";
+ // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
+ public static final String WALLPAPER_IMAGE_KEY =
+ "/data/data/com.android.settings/files/wallpaper";
+ public static final String WALLPAPER_INFO_KEY = "/data/system/wallpaper_info.xml";
// Stage file - should be adjacent to the WALLPAPER_IMAGE location. The wallpapers
// will be saved to this file from the restore stream, then renamed to the proper
// location if it's deemed suitable.
- private static final String STAGE_FILE = "/data/data/com.android.settings/files/wallpaper-tmp";
+ // TODO: Will need to change if backing up non-primary user's wallpaper
+ private static final String STAGE_FILE = "/data/system/users/0/wallpaper-tmp";
Context mContext;
String[] mFiles;
+ String[] mKeys;
double mDesiredMinWidth;
double mDesiredMinHeight;
@@ -57,11 +65,12 @@
* @param context
* @param files
*/
- public WallpaperBackupHelper(Context context, String... files) {
+ public WallpaperBackupHelper(Context context, String[] files, String[] keys) {
super(context);
mContext = context;
mFiles = files;
+ mKeys = keys;
WallpaperManager wpm;
wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
@@ -89,7 +98,7 @@
*/
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
- performBackup_checked(oldState, data, newState, mFiles, mFiles);
+ performBackup_checked(oldState, data, newState, mFiles, mKeys);
}
/**
@@ -99,8 +108,8 @@
*/
public void restoreEntity(BackupDataInputStream data) {
final String key = data.getKey();
- if (isKeyInList(key, mFiles)) {
- if (key.equals(WALLPAPER_IMAGE)) {
+ if (isKeyInList(key, mKeys)) {
+ if (key.equals(WALLPAPER_IMAGE_KEY)) {
// restore the file to the stage for inspection
File f = new File(STAGE_FILE);
if (writeFile(f, data)) {
@@ -135,9 +144,9 @@
f.delete();
}
}
- } else {
- // Some other normal file; just decode it to its destination
- File f = new File(key);
+ } else if (key.equals(WALLPAPER_INFO_KEY)) {
+ // XML file containing wallpaper info
+ File f = new File(WALLPAPER_INFO);
writeFile(f, data);
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3d4e354..6d4cdae 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1307,6 +1307,15 @@
int flags);
/**
+ * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userId
+ * argument for use by system server and other multi-user aware code.
+ * @hide
+ */
+ public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* Disconnect from an application service. You will no longer receive
* calls as the service is restarted, and the service is now allowed to
* stop at any time.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 3928aaf..cd8d87f 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -370,6 +370,12 @@
return mBase.bindService(service, conn, flags);
}
+ /** @hide */
+ @Override
+ public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
+ return mBase.bindService(service, conn, flags, userId);
+ }
+
@Override
public void unbindService(ServiceConnection conn) {
mBase.unbindService(conn);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2023f82..8029bd5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3380,7 +3380,8 @@
public static final ServiceInfo generateServiceInfo(Service s, int flags, int userId) {
if (s == null) return null;
- if (!copyNeeded(flags, s.owner, s.metaData) && userId == 0) {
+ if (!copyNeeded(flags, s.owner, s.metaData)
+ && userId == UserId.getUserId(s.info.applicationInfo.uid)) {
return s.info;
}
// Make shallow copies so we can store the metadata safely
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
index 286b674..0da67d63 100644
--- a/core/java/android/os/UserId.java
+++ b/core/java/android/os/UserId.java
@@ -73,6 +73,10 @@
}
}
+ public static final int getCallingUserId() {
+ return getUserId(Binder.getCallingUid());
+ }
+
/**
* Returns the uid that is composed from the userId and the appId.
* @hide
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index f4b5dca..abe0104 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -52,7 +52,6 @@
if (keyUTF == NULL) {
return -1;
}
-
err = writer->WriteEntityHeader(String8(keyUTF), dataSize);
env->ReleaseStringUTFChars(key, keyUTF);