summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/UserHandle.java55
-rw-r--r--core/tests/coretests/src/android/os/UserHandleTest.java120
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
3 files changed, 165 insertions, 14 deletions
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 6a4fef2b67e8..4c04f7860cf6 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -27,6 +27,8 @@ import java.io.PrintWriter;
* Representation of a user on the device.
*/
public final class UserHandle implements Parcelable {
+ // NOTE: keep logic in sync with system/core/libcutils/multiuser.c
+
/**
* @hide Range of uids allocated for a user.
*/
@@ -88,6 +90,19 @@ public final class UserHandle implements Parcelable {
*/
public static final boolean MU_ENABLED = true;
+ /** @hide */
+ public static final int ERR_GID = -1;
+ /** @hide */
+ public static final int AID_ROOT = android.os.Process.ROOT_UID;
+ /** @hide */
+ public static final int AID_APP_START = android.os.Process.FIRST_APPLICATION_UID;
+ /** @hide */
+ public static final int AID_APP_END = android.os.Process.LAST_APPLICATION_UID;
+ /** @hide */
+ public static final int AID_SHARED_GID_START = android.os.Process.FIRST_SHARED_APPLICATION_GID;
+ /** @hide */
+ public static final int AID_CACHE_GID_START = android.os.Process.FIRST_APPLICATION_CACHE_GID;
+
final int mHandle;
/**
@@ -192,13 +207,20 @@ public final class UserHandle implements Parcelable {
return getUid(userId, Process.SHARED_USER_GID);
}
- /**
- * Returns the shared app gid for a given uid or appId.
- * @hide
- */
- public static int getSharedAppGid(int id) {
- return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE)
- - Process.FIRST_APPLICATION_UID;
+ /** @hide */
+ public static int getSharedAppGid(int uid) {
+ return getSharedAppGid(getUserId(uid), getAppId(uid));
+ }
+
+ /** @hide */
+ public static int getSharedAppGid(int userId, int appId) {
+ if (appId >= AID_APP_START && appId <= AID_APP_END) {
+ return (appId - AID_APP_START) + AID_SHARED_GID_START;
+ } else if (appId >= AID_ROOT && appId <= AID_APP_START) {
+ return appId;
+ } else {
+ return -1;
+ }
}
/**
@@ -214,13 +236,18 @@ public final class UserHandle implements Parcelable {
return appId;
}
- /**
- * Returns the cache GID for a given UID or appId.
- * @hide
- */
- public static int getCacheAppGid(int id) {
- return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE)
- - Process.FIRST_APPLICATION_UID;
+ /** @hide */
+ public static int getCacheAppGid(int uid) {
+ return getCacheAppGid(getUserId(uid), getAppId(uid));
+ }
+
+ /** @hide */
+ public static int getCacheAppGid(int userId, int appId) {
+ if (appId >= AID_APP_START && appId <= AID_APP_END) {
+ return getUid(userId, (appId - AID_APP_START) + AID_CACHE_GID_START);
+ } else {
+ return -1;
+ }
}
/**
diff --git a/core/tests/coretests/src/android/os/UserHandleTest.java b/core/tests/coretests/src/android/os/UserHandleTest.java
new file mode 100644
index 000000000000..af559fddd48a
--- /dev/null
+++ b/core/tests/coretests/src/android/os/UserHandleTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static android.os.UserHandle.ERR_GID;
+import static android.os.UserHandle.getAppId;
+import static android.os.UserHandle.getCacheAppGid;
+import static android.os.UserHandle.getSharedAppGid;
+import static android.os.UserHandle.getUid;
+import static android.os.UserHandle.getUserId;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class UserHandleTest {
+ // NOTE: keep logic in sync with system/core/libcutils/tests/multiuser_test.cpp
+
+ @Test
+ public void testMerge() throws Exception {
+ EXPECT_EQ(0, multiuser_get_uid(0, 0));
+ EXPECT_EQ(1000, multiuser_get_uid(0, 1000));
+ EXPECT_EQ(10000, multiuser_get_uid(0, 10000));
+ EXPECT_EQ(50000, multiuser_get_uid(0, 50000));
+ EXPECT_EQ(1000000, multiuser_get_uid(10, 0));
+ EXPECT_EQ(1001000, multiuser_get_uid(10, 1000));
+ EXPECT_EQ(1010000, multiuser_get_uid(10, 10000));
+ EXPECT_EQ(1050000, multiuser_get_uid(10, 50000));
+ }
+
+ @Test
+ public void testSplitUser() throws Exception {
+ EXPECT_EQ(0, multiuser_get_user_id(0));
+ EXPECT_EQ(0, multiuser_get_user_id(1000));
+ EXPECT_EQ(0, multiuser_get_user_id(10000));
+ EXPECT_EQ(0, multiuser_get_user_id(50000));
+ EXPECT_EQ(10, multiuser_get_user_id(1000000));
+ EXPECT_EQ(10, multiuser_get_user_id(1001000));
+ EXPECT_EQ(10, multiuser_get_user_id(1010000));
+ EXPECT_EQ(10, multiuser_get_user_id(1050000));
+ }
+
+ @Test
+ public void testSplitApp() throws Exception {
+ EXPECT_EQ(0, multiuser_get_app_id(0));
+ EXPECT_EQ(1000, multiuser_get_app_id(1000));
+ EXPECT_EQ(10000, multiuser_get_app_id(10000));
+ EXPECT_EQ(50000, multiuser_get_app_id(50000));
+ EXPECT_EQ(0, multiuser_get_app_id(1000000));
+ EXPECT_EQ(1000, multiuser_get_app_id(1001000));
+ EXPECT_EQ(10000, multiuser_get_app_id(1010000));
+ EXPECT_EQ(50000, multiuser_get_app_id(1050000));
+ }
+
+ @Test
+ public void testCache() throws Exception {
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 0));
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 1000));
+ EXPECT_EQ(20000, multiuser_get_cache_gid(0, 10000));
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 50000));
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 0));
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 1000));
+ EXPECT_EQ(1020000, multiuser_get_cache_gid(10, 10000));
+ EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 50000));
+ }
+
+ @Test
+ public void testShared() throws Exception {
+ EXPECT_EQ(0, multiuser_get_shared_gid(0, 0));
+ EXPECT_EQ(1000, multiuser_get_shared_gid(0, 1000));
+ EXPECT_EQ(50000, multiuser_get_shared_gid(0, 10000));
+ EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(0, 50000));
+ EXPECT_EQ(0, multiuser_get_shared_gid(10, 0));
+ EXPECT_EQ(1000, multiuser_get_shared_gid(10, 1000));
+ EXPECT_EQ(50000, multiuser_get_shared_gid(10, 10000));
+ EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(10, 50000));
+ }
+
+ private static void EXPECT_EQ(int expected, int actual) {
+ assertEquals(expected, actual);
+ }
+
+ private static int multiuser_get_uid(int userId, int appId) {
+ return getUid(userId, appId);
+ }
+
+ private static int multiuser_get_cache_gid(int userId, int appId) {
+ return getCacheAppGid(userId, appId);
+ }
+
+ private static int multiuser_get_shared_gid(int userId, int appId) {
+ return getSharedAppGid(userId, appId);
+ }
+
+ private static int multiuser_get_user_id(int uid) {
+ return getUserId(uid);
+ }
+
+ private static int multiuser_get_app_id(int uid) {
+ return getAppId(uid);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 90b8e29b122d..70c08c929fe3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3808,6 +3808,10 @@ public class ActivityManagerService extends IActivityManager.Stub
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+
+ // Replace any invalid GIDs
+ if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
+ if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
}
checkTime(startTime, "startProcess: building args");
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {