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

Commit a1e4d8d6 authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "Don't use mockito for UiAutomation" into main

parents db33fc17 706c5691
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ import java.util.concurrent.TimeoutException;
 * interacting with another application whose behavior depends on that setting.
 * </p>
 */
@android.ravenwood.annotation.RavenwoodKeepPartialClass
@android.ravenwood.annotation.RavenwoodRedirectionClass("UiAutomation_ravenwood")
public final class UiAutomation {

    private static final String LOG_TAG = UiAutomation.class.getSimpleName();
@@ -284,6 +286,7 @@ public final class UiAutomation {
     *
     * @hide
     */
    @android.ravenwood.annotation.RavenwoodKeep
    public UiAutomation(Context context, IUiAutomationConnection connection) {
        this(getDisplayId(context), context.getMainLooper(), connection);
    }
@@ -307,6 +310,7 @@ public final class UiAutomation {
        Log.w(LOG_TAG, "Created with deprecatead constructor, assumes DEFAULT_DISPLAY");
    }

    @android.ravenwood.annotation.RavenwoodKeep
    private UiAutomation(int displayId, Looper looper, IUiAutomationConnection connection) {
        Preconditions.checkArgument(looper != null, "Looper cannot be null!");
        Preconditions.checkArgument(connection != null, "Connection cannot be null!");
@@ -586,6 +590,7 @@ public final class UiAutomation {
     * @see #adoptShellPermissionIdentity(String...)
     * @see #dropShellPermissionIdentity()
     */
    @android.ravenwood.annotation.RavenwoodRedirect
    public void adoptShellPermissionIdentity() {
        try {
            // Calling out without a lock held.
@@ -611,6 +616,7 @@ public final class UiAutomation {
     * @see #adoptShellPermissionIdentity()
     * @see #dropShellPermissionIdentity()
     */
    @android.ravenwood.annotation.RavenwoodRedirect
    public void adoptShellPermissionIdentity(@Nullable String... permissions) {
        try {
            // Calling out without a lock held.
@@ -627,6 +633,7 @@ public final class UiAutomation {
     *
     * @see #adoptShellPermissionIdentity()
     */
    @android.ravenwood.annotation.RavenwoodRedirect
    public void dropShellPermissionIdentity() {
        try {
            // Calling out without a lock held.
@@ -645,6 +652,7 @@ public final class UiAutomation {
     */
    @TestApi
    @NonNull
    @android.ravenwood.annotation.RavenwoodRedirect
    public Set<String> getAdoptedShellPermissions() {
        try {
            final List<String> permissions = mUiAutomationConnection.getAdoptedShellPermissions();
@@ -1884,6 +1892,7 @@ public final class UiAutomation {
     * <p><b>NOTE: </b> must be a static method because it's called from a constructor to call
     * another one.
     */
    @android.ravenwood.annotation.RavenwoodReplace(reason = "Always use DEFAULT_DISPLAY")
    private static int getDisplayId(Context context) {
        Preconditions.checkArgument(context != null, "Context cannot be null!");

@@ -1917,6 +1926,10 @@ public final class UiAutomation {
        return userDisplayId;
    }

    private static int getDisplayId$ravenwood(Context context) {
        return DEFAULT_DISPLAY;
    }

    private static int getMainDisplayIdAssignedToUser(Context context, UserManager userManager) {
        if (!userManager.isUserVisible()) {
            // Should also not happen, but ...
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.app;

import android.annotation.Nullable;

import java.util.Collections;
import java.util.Set;

public class UiAutomation_ravenwood {
    private static Set<String> sAdoptedPermissions = Collections.emptySet();

    public static void reset() {
        sAdoptedPermissions = Collections.emptySet();
    }

    public static void adoptShellPermissionIdentity(UiAutomation self) {
        sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS;
    }

    public static void adoptShellPermissionIdentity(UiAutomation self,
            @Nullable String... permissions) {
        if (permissions == null) {
            sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS;
        } else {
            sAdoptedPermissions = Set.of(permissions);
        }
    }

    public static void dropShellPermissionIdentity(UiAutomation self) {
        sAdoptedPermissions = Collections.emptySet();
    }

    public static Set<String> getAdoptedShellPermissions(UiAutomation self) {
        return sAdoptedPermissions;
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -186,7 +186,6 @@ java_library {
        "ravenwood-helper-framework-runtime",
        "ravenwood-helper-libcore-runtime",
        "hoststubgen-helper-runtime.ravenwood",
        "mockito-ravenwood-prebuilt",
    ],
    visibility: [":__subpackages__"],
    jarjar_rules: ":ravenwood-services-jarjar-rules",
+6 −43
Original line number Diff line number Diff line
@@ -30,17 +30,16 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.withDefault;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread_ravenwood;
import android.app.AppCompatCallbacks;
import android.app.IUiAutomationConnection;
import android.app.Instrumentation;
import android.app.ResourcesManager;
import android.app.UiAutomation;
import android.app.UiAutomation_ravenwood;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
@@ -83,14 +82,12 @@ import org.junit.runner.Description;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@@ -198,7 +195,6 @@ public class RavenwoodRuntimeEnvironmentController {

    /** Map from path -> resources. */
    private static final HashMap<File, Resources> sCachedResources = new HashMap<>();
    private static Set<String> sAdoptedPermissions = Collections.emptySet();

    private static final Object sInitializationLock = new Object();

@@ -416,6 +412,8 @@ public class RavenwoodRuntimeEnvironmentController {
        var systemServerContext =
                new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader);

        var uiAutomation = new UiAutomation(sInstContext, new IUiAutomationConnection.Default());

        var instArgs = Bundle.EMPTY;
        RavenwoodUtils.runOnMainThreadSync(() -> {
            var instClassName = withDefault(sInstrumentationClass, DEFAULT_INSTRUMENTATION_CLASS);
@@ -432,7 +430,7 @@ public class RavenwoodRuntimeEnvironmentController {
                }
            }

            initInstrumentation();
            sInstrumentation.basicInit(sInstContext, sTargetContext, uiAutomation);
            sInstrumentation.onCreate(instArgs);
        });
        InstrumentationRegistry.registerInstance(sInstrumentation, instArgs);
@@ -473,19 +471,12 @@ public class RavenwoodRuntimeEnvironmentController {
        }
    }

    private static void initInstrumentation() {
        // We need to recreate the mocks for each test class, because sometimes tests
        // will call Mockito.framework().clearInlineMocks() after execution.
        sInstrumentation.basicInit(sInstContext, sTargetContext, createMockUiAutomation());
    }

    /**
     * Partially reset and initialize before each test class invocation
     */
    public static void initForRunner() {
        initInstrumentation();

        // Reset some global state
        UiAutomation_ravenwood.reset();
        Process_ravenwood.reset();
        DeviceConfig_host.reset();
        Binder.restoreCallingIdentity(sCallingIdentity);
@@ -731,34 +722,6 @@ public class RavenwoodRuntimeEnvironmentController {
                () -> Class.forName("org.mockito.Matchers"));
    }

    static <T> T makeDefaultThrowMock(Class<T> clazz) {
        return mock(clazz, inv -> { throw new RavenwoodUnsupportedApiException(); });
    }

    // TODO: use the real UiAutomation class instead of a mock
    private static UiAutomation createMockUiAutomation() {
        sAdoptedPermissions = Collections.emptySet();
        var mock = makeDefaultThrowMock(UiAutomation.class);
        doAnswer(inv -> {
            sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS;
            return null;
        }).when(mock).adoptShellPermissionIdentity();
        doAnswer(inv -> {
            if (inv.getArgument(0) == null) {
                sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS;
            } else {
                sAdoptedPermissions = (Set) Set.of(inv.getArguments());
            }
            return null;
        }).when(mock).adoptShellPermissionIdentity(any());
        doAnswer(inv -> {
            sAdoptedPermissions = Collections.emptySet();
            return null;
        }).when(mock).dropShellPermissionIdentity();
        doAnswer(inv -> sAdoptedPermissions).when(mock).getAdoptedShellPermissions();
        return mock;
    }

    private static void dumpCommandLineArgs() {
        Log.i(TAG, "JVM arguments:");

+1 −0
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ android.app.ComponentOptions
android.app.Instrumentation
android.app.LocaleConfig
android.app.ResourcesManager
android.app.UiAutomation
android.app.WindowConfiguration

android.metrics.LogMaker