summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java3
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/ApplicationPackageManager.java15
-rw-r--r--core/java/android/app/ContextImpl.java25
-rw-r--r--core/java/android/app/IActivityManager.java6
-rw-r--r--core/java/android/app/LoadedApk.java10
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/content/pm/PackageManager.java54
-rw-r--r--core/java/android/content/pm/PackageParser.java52
-rw-r--r--core/java/android/os/Binder.java31
-rw-r--r--core/java/android/os/UserId.java90
12 files changed, 230 insertions, 90 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9661b9e..d98d87b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,6 +30,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.Parcel;
@@ -975,7 +976,7 @@ public class ActivityManager {
public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
try {
return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
- observer);
+ observer, Binder.getOrigCallingUser());
} catch (RemoteException e) {
return false;
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 7994d7c..d80902d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -91,7 +91,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
try {
getDefault().broadcastIntent(
null, intent, null, null, Activity.RESULT_OK, null, null,
- null /*permission*/, false, true);
+ null /*permission*/, false, true, Binder.getOrigCallingUser());
} catch (RemoteException ex) {
}
}
@@ -306,9 +306,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String perm = data.readString();
boolean serialized = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
+ int userId = data.readInt();
int res = broadcastIntent(app, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, perm,
- serialized, sticky);
+ serialized, sticky, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -320,7 +321,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IBinder b = data.readStrongBinder();
IApplicationThread app = b != null ? ApplicationThreadNative.asInterface(b) : null;
Intent intent = Intent.CREATOR.createFromParcel(data);
- unbroadcastIntent(app, intent);
+ int userId = data.readInt();
+ unbroadcastIntent(app, intent, userId);
reply.writeNoException();
return true;
}
@@ -900,7 +902,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String packageName = data.readString();
IPackageDataObserver observer = IPackageDataObserver.Stub.asInterface(
data.readStrongBinder());
- boolean res = clearApplicationUserData(packageName, observer);
+ int userId = data.readInt();
+ boolean res = clearApplicationUserData(packageName, observer, userId);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -1819,7 +1822,7 @@ class ActivityManagerProxy implements IActivityManager
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized,
- boolean sticky) throws RemoteException
+ boolean sticky, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -1834,6 +1837,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(requiredPermission);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
+ data.writeInt(userId);
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
@@ -1841,13 +1845,15 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
return res;
}
- public void unbroadcastIntent(IApplicationThread caller, Intent intent) throws RemoteException
+ public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId)
+ throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
+ data.writeInt(userId);
mRemote.transact(UNBROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -2651,12 +2657,13 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
public boolean clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) throws RemoteException {
+ final IPackageDataObserver observer, final int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(packageName);
data.writeStrongBinder(observer.asBinder());
+ data.writeInt(userId);
mRemote.transact(CLEAR_APP_DATA_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3c5f53a..e4cfc99 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -47,6 +47,7 @@ import android.net.Proxy;
import android.net.ProxyProperties;
import android.opengl.GLUtils;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -60,6 +61,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
+import android.os.UserId;
import android.util.AndroidRuntimeException;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -132,6 +134,7 @@ public final class ActivityThread {
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = true;
private static final boolean DEBUG_CONFIGURATION = false;
+ private static final boolean DEBUG_SERVICE = true;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
@@ -635,6 +638,9 @@ public final class ActivityThread {
s.intent = intent;
s.rebind = rebind;
+ if (DEBUG_SERVICE)
+ Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
queueOrSendMessage(H.BIND_SERVICE, s);
}
@@ -1592,7 +1598,8 @@ public final class ActivityThread {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
- ? ai.uid != mBoundApplication.appInfo.uid : true);
+ ? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
+ : true);
if ((flags&(Context.CONTEXT_INCLUDE_CODE
|Context.CONTEXT_IGNORE_SECURITY))
== Context.CONTEXT_INCLUDE_CODE) {
@@ -2294,6 +2301,8 @@ public final class ActivityThread {
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
+ if (DEBUG_SERVICE)
+ Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 180a442..fee2beb 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1177,13 +1177,14 @@ final class ApplicationPackageManager extends PackageManager {
*/
@Override
public List<UserInfo> getUsers() {
- // TODO:
- // Dummy code, always returns just the primary user
- ArrayList<UserInfo> users = new ArrayList<UserInfo>();
- UserInfo primary = new UserInfo(0, "Root!",
- UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
- users.add(primary);
- return users;
+ try {
+ return mPM.getUsers();
+ } catch (RemoteException re) {
+ ArrayList<UserInfo> users = new ArrayList<UserInfo>();
+ UserInfo primary = new UserInfo(0, "Root!", UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+ users.add(primary);
+ return users;
+ }
}
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2bf1fb7..db5113e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,6 +75,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserId;
import android.os.Vibrator;
import android.os.storage.StorageManager;
import android.telephony.TelephonyManager;
@@ -896,7 +897,8 @@ class ContextImpl extends Context {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, false, false);
+ Activity.RESULT_OK, null, null, null, false, false,
+ Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -908,7 +910,8 @@ class ContextImpl extends Context {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, false, false);
+ Activity.RESULT_OK, null, null, receiverPermission, false, false,
+ Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -921,7 +924,8 @@ class ContextImpl extends Context {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, true, false);
+ Activity.RESULT_OK, null, null, receiverPermission, true, false,
+ Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -954,7 +958,7 @@ class ContextImpl extends Context {
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
- true, false);
+ true, false, Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -966,7 +970,8 @@ class ContextImpl extends Context {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, false, true);
+ Activity.RESULT_OK, null, null, null, false, true,
+ Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -999,7 +1004,7 @@ class ContextImpl extends Context {
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
- true, true);
+ true, true, Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -1014,7 +1019,7 @@ class ContextImpl extends Context {
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().unbroadcastIntent(
- mMainThread.getApplicationThread(), intent);
+ mMainThread.getApplicationThread(), intent, Binder.getOrigCallingUser());
} catch (RemoteException e) {
}
}
@@ -1215,8 +1220,7 @@ class ContextImpl extends Context {
int pid = Binder.getCallingPid();
if (pid != Process.myPid()) {
- return checkPermission(permission, pid,
- Binder.getCallingUid());
+ return checkPermission(permission, pid, Binder.getCallingUid());
}
return PackageManager.PERMISSION_DENIED;
}
@@ -1384,7 +1388,8 @@ class ContextImpl extends Context {
Uri uri, int modeFlags, String message) {
enforceForUri(
modeFlags, checkCallingUriPermission(uri, modeFlags),
- false, Binder.getCallingUid(), uri, message);
+ false,
+ Binder.getCallingUid(), uri, message);
}
public void enforceCallingOrSelfUriPermission(
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 5222d37..39817ac 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -114,8 +114,8 @@ public interface IActivityManager extends IInterface {
public int broadcastIntent(IApplicationThread caller, Intent intent,
String resolvedType, IIntentReceiver resultTo, int resultCode,
String resultData, Bundle map, String requiredPermission,
- boolean serialized, boolean sticky) throws RemoteException;
- public void unbroadcastIntent(IApplicationThread caller, Intent intent) throws RemoteException;
+ boolean serialized, boolean sticky, int userId) throws RemoteException;
+ public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
/* oneway */
public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException;
public void attachApplication(IApplicationThread app) throws RemoteException;
@@ -209,7 +209,7 @@ public interface IActivityManager extends IInterface {
int flags) throws RemoteException;
public void cancelIntentSender(IIntentSender sender) throws RemoteException;
public boolean clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) throws RemoteException;
+ final IPackageDataObserver observer, int userId) throws RemoteException;
public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
public void setProcessLimit(int max) throws RemoteException;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0c6baeb..fcbcd81 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.StrictMode;
+import android.os.UserId;
import android.util.AndroidRuntimeException;
import android.util.Slog;
import android.view.CompatibilityInfoHolder;
@@ -67,6 +68,8 @@ final class ServiceConnectionLeaked extends AndroidRuntimeException {
*/
public final class LoadedApk {
+ private static final String TAG = "LoadedApk";
+
private final ActivityThread mActivityThread;
private final ApplicationInfo mApplicationInfo;
final String mPackageName;
@@ -113,8 +116,13 @@ public final class LoadedApk {
mApplicationInfo = aInfo;
mPackageName = aInfo.packageName;
mAppDir = aInfo.sourceDir;
- mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
+ final int myUid = Process.myUid();
+ mResDir = aInfo.uid == myUid ? aInfo.sourceDir
: aInfo.publicSourceDir;
+ if (!UserId.isSameUser(aInfo.uid, myUid)) {
+ aInfo.dataDir = PackageManager.getDataDirForUser(UserId.getUserId(myUid),
+ mPackageName);
+ }
mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index decb974..bb35c29 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -364,4 +364,6 @@ interface IPackageManager {
VerifierDeviceIdentity getVerifierDeviceIdentity();
boolean isFirstBoot();
+
+ List<UserInfo> getUsers();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8541748..26a9181 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,6 +28,7 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Environment;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -753,13 +754,6 @@ public abstract class PackageManager {
public static final int VERIFICATION_REJECT = -1;
/**
- * Range of IDs allocated for a user.
- *
- * @hide
- */
- public static final int PER_USER_RANGE = 100000;
-
- /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's
* audio pipeline is low-latency, more suitable for audio applications sensitive to delays or
* lag in sound input or output.
@@ -2615,39 +2609,6 @@ public abstract class PackageManager {
public abstract void updateUserFlags(int id, int flags);
/**
- * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
- * user.
- * @hide
- */
- public static boolean isSameUser(int uid1, int uid2) {
- return getUserId(uid1) == getUserId(uid2);
- }
-
- /**
- * Returns the user id for a given uid.
- * @hide
- */
- public static int getUserId(int uid) {
- return uid / PER_USER_RANGE;
- }
-
- /**
- * Returns the uid that is composed from the userId and the appId.
- * @hide
- */
- public static int getUid(int userId, int appId) {
- return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
- }
-
- /**
- * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
- * @hide
- */
- public static int getAppId(int uid) {
- return uid % PER_USER_RANGE;
- }
-
- /**
* Returns the device identity that verifiers can use to associate their
* scheme to a particular device. This should not be used by anything other
* than a package verifier.
@@ -2656,4 +2617,17 @@ public abstract class PackageManager {
* @hide
*/
public abstract VerifierDeviceIdentity getVerifierDeviceIdentity();
+
+ /**
+ * Returns the data directory for a particular user and package, given the uid of the package.
+ * @param uid uid of the package, including the userId and appId
+ * @param packageName name of the package
+ * @return the user-specific data directory for the package
+ * @hide
+ */
+ public static String getDataDirForUser(int userId, String packageName) {
+ // TODO: This should be shared with Installer's knowledge of user directory
+ return Environment.getDataDirectory().toString() + "/user/" + userId
+ + "/" + packageName;
+ }
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e593d5b..faee873 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -24,18 +24,17 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.PatternMatcher;
+import android.os.UserId;
import android.util.AttributeSet;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
import android.util.TypedValue;
-import com.android.internal.util.XmlUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.File;
@@ -59,6 +58,11 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
/**
* Package archive parsing
*
@@ -209,6 +213,8 @@ public class PackageParser {
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime) {
+ final int userId = Binder.getOrigCallingUser();
+
PackageInfo pi = new PackageInfo();
pi.packageName = p.packageName;
pi.versionCode = p.mVersionCode;
@@ -250,7 +256,8 @@ public class PackageParser {
final Activity activity = p.activities.get(i);
if (activity.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags);
+ pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
+ userId);
}
}
}
@@ -271,7 +278,7 @@ public class PackageParser {
final Activity activity = p.receivers.get(i);
if (activity.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags);
+ pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags, userId);
}
}
}
@@ -292,7 +299,7 @@ public class PackageParser {
final Service service = p.services.get(i);
if (service.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.services[j++] = generateServiceInfo(p.services.get(i), flags);
+ pi.services[j++] = generateServiceInfo(p.services.get(i), flags, userId);
}
}
}
@@ -313,7 +320,7 @@ public class PackageParser {
final Provider provider = p.providers.get(i);
if (provider.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags);
+ pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, userId);
}
}
}
@@ -3241,8 +3248,12 @@ public class PackageParser {
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
+ return generateApplicationInfo(p, flags, UserId.getUserId(Binder.getCallingUid()));
+ }
+
+ public static ApplicationInfo generateApplicationInfo(Package p, int flags, int userId) {
if (p == null) return null;
- if (!copyNeeded(flags, p, null)) {
+ if (!copyNeeded(flags, p, null) && userId == 0) {
// CompatibilityMode is global state. It's safe to modify the instance
// of the package.
if (!sCompatibilityModeEnabled) {
@@ -3258,6 +3269,10 @@ public class PackageParser {
// Make shallow copy so we can store the metadata/libraries safely
ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
+ if (userId != 0) {
+ ai.uid = UserId.getUid(userId, ai.uid);
+ ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
+ }
if ((flags & PackageManager.GET_META_DATA) != 0) {
ai.metaData = p.mAppMetaData;
}
@@ -3325,16 +3340,15 @@ public class PackageParser {
}
}
- public static final ActivityInfo generateActivityInfo(Activity a,
- int flags) {
+ public static final ActivityInfo generateActivityInfo(Activity a, int flags, int userId) {
if (a == null) return null;
- if (!copyNeeded(flags, a.owner, a.metaData)) {
+ if (!copyNeeded(flags, a.owner, a.metaData) && userId == 0) {
return a.info;
}
// Make shallow copies so we can store the metadata safely
ActivityInfo ai = new ActivityInfo(a.info);
ai.metaData = a.metaData;
- ai.applicationInfo = generateApplicationInfo(a.owner, flags);
+ ai.applicationInfo = generateApplicationInfo(a.owner, flags, userId);
return ai;
}
@@ -3359,15 +3373,15 @@ public class PackageParser {
}
}
- public static final ServiceInfo generateServiceInfo(Service s, int flags) {
+ public static final ServiceInfo generateServiceInfo(Service s, int flags, int userId) {
if (s == null) return null;
- if (!copyNeeded(flags, s.owner, s.metaData)) {
+ if (!copyNeeded(flags, s.owner, s.metaData) && userId == 0) {
return s.info;
}
// Make shallow copies so we can store the metadata safely
ServiceInfo si = new ServiceInfo(s.info);
si.metaData = s.metaData;
- si.applicationInfo = generateApplicationInfo(s.owner, flags);
+ si.applicationInfo = generateApplicationInfo(s.owner, flags, userId);
return si;
}
@@ -3400,12 +3414,12 @@ public class PackageParser {
}
}
- public static final ProviderInfo generateProviderInfo(Provider p,
- int flags) {
+ public static final ProviderInfo generateProviderInfo(Provider p, int flags, int userId) {
if (p == null) return null;
if (!copyNeeded(flags, p.owner, p.metaData)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
- || p.info.uriPermissionPatterns == null)) {
+ || p.info.uriPermissionPatterns == null)
+ && userId == 0) {
return p.info;
}
// Make shallow copies so we can store the metadata safely
@@ -3414,7 +3428,7 @@ public class PackageParser {
if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
pi.uriPermissionPatterns = null;
}
- pi.applicationInfo = generateApplicationInfo(p.owner, flags);
+ pi.applicationInfo = generateApplicationInfo(p.owner, flags, userId);
return pi;
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 24569fa..577fc43 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -49,6 +49,7 @@ public class Binder implements IBinder {
private static final boolean FIND_POTENTIAL_LEAKS = false;
private static final String TAG = "Binder";
+ /* mObject is used by native code, do not remove or rename */
private int mObject;
private IInterface mOwner;
private String mDescriptor;
@@ -70,7 +71,35 @@ public class Binder implements IBinder {
* incoming transaction, then its own uid is returned.
*/
public static final native int getCallingUid();
-
+
+ /**
+ * Return the original ID of the user assigned to the process that sent you the current
+ * transaction that is being processed. This uid can be used with higher-level system services
+ * to determine its identity and check permissions. If the current thread is not currently
+ * executing an incoming transaction, then its own uid is returned.
+ * <p/>
+ * This value cannot be reset by calls to {@link #clearCallingIdentity()}.
+ * @hide
+ */
+ public static final int getOrigCallingUid() {
+ if (UserId.MU_ENABLED) {
+ return getOrigCallingUidNative();
+ } else {
+ return getCallingUid();
+ }
+ }
+
+ private static final native int getOrigCallingUidNative();
+
+ /**
+ * Utility function to return the user id of the calling process.
+ * @return userId of the calling process, extracted from the callingUid
+ * @hide
+ */
+ public static final int getOrigCallingUser() {
+ return UserId.getUserId(getOrigCallingUid());
+ }
+
/**
* Reset the identity of the incoming IPC on the current thread. This can
* be useful if, while handling an incoming call, you will be calling
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
new file mode 100644
index 0000000..4124d51
--- /dev/null
+++ b/core/java/android/os/UserId.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * @hide
+ */
+public final class UserId {
+ /**
+ * Range of IDs allocated for a user.
+ *
+ * @hide
+ */
+ public static final int PER_USER_RANGE = 100000;
+
+ public static final int USER_ALL = -1;
+
+ /**
+ * Enable multi-user related side effects. Set this to false if there are problems with single
+ * user usecases.
+ * */
+ public static final boolean MU_ENABLED = true;
+
+ /**
+ * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
+ * user.
+ * @hide
+ */
+ public static final boolean isSameUser(int uid1, int uid2) {
+ return getUserId(uid1) == getUserId(uid2);
+ }
+
+ /**
+ * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
+ * uids.
+ * @param uid1 uid to compare
+ * @param uid2 other uid to compare
+ * @return whether the appId is the same for both uids
+ * @hide
+ */
+ public static final boolean isSameApp(int uid1, int uid2) {
+ return getAppId(uid1) == getAppId(uid2);
+ }
+
+ /**
+ * Returns the user id for a given uid.
+ * @hide
+ */
+ public static final int getUserId(int uid) {
+ if (MU_ENABLED) {
+ return uid / PER_USER_RANGE;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns the uid that is composed from the userId and the appId.
+ * @hide
+ */
+ public static final int getUid(int userId, int appId) {
+ if (MU_ENABLED) {
+ return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
+ } else {
+ return appId;
+ }
+ }
+
+ /**
+ * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
+ * @hide
+ */
+ public static final int getAppId(int uid) {
+ return uid % PER_USER_RANGE;
+ }
+}