Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77a34500 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Better, consistent definition of AID_SHARED_GID.

AID_SHARED_GID is a GID shared by a specific app across all users on
the same device.  Bring the UserHandle and multiuser.c implementations
into agreement, and copy/paste the unit tests that verify that both
behave identically.

Since we might now return "-1" when a GID is invalid, have
ActivityManager handle these cases by quickly swapping in the
always-valid getUserGid().

Test: bit FrameworksCoreTests:android.os.UserHandleTest
Bug: 34151068, 64548938
Change-Id: I0463aba923ae5ce1942666359a394ae6cdb7c1f8
parent c173c93c
Loading
Loading
Loading
Loading
+41 −14
Original line number Diff line number Diff line
@@ -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;
        }
    }

    /**
+120 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -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) {