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

Commit 3f265b79 authored by Joshua Trask's avatar Joshua Trask Committed by Android (Google) Code Review
Browse files

Merge "Decompose ChooserActivityTest for reuse."

parents 0f44e20e 33501f38
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -138,3 +138,39 @@ java_genrule {
        "done && " +
        "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
}

// In addition to running as part of FrameworksCoreTests, we run (a subclass of)
// ChooserActivityTest against the unbundled ChooserActivity implementation in
// //packages/modules/IntentResolver/. The following library provides the
// minimum dependencies required to build that test in the unbundled package.
android_library {
    name: "ChooserActivityTestsLib",
    visibility: ["//packages/modules/IntentResolver/java/tests:__pkg__"],

    srcs: [
        "src/com/android/internal/app/ChooserActivityLoggerFake.java",
        "src/com/android/internal/app/ChooserActivityOverrideData.java",
        "src/com/android/internal/app/ChooserActivityTest.java",
        "src/com/android/internal/app/ChooserWrapperActivity.java",
        "src/com/android/internal/app/IChooserWrapper.java",
        "src/com/android/internal/app/MatcherUtils.java",
        "src/com/android/internal/app/ResolverDataProvider.java",
    ],

    static_libs: [
        "androidx.test.espresso.core",
        "androidx.test.ext.junit",
        "androidx.test.runner",
        "androidx.test.rules",
        "mockito-target-minus-junit4",
        "truth-prebuilt",
    ],

    libs: [
        "android.test.runner",
        "android.test.base",
        "android.test.mock",
        "framework",
        "framework-res",
    ],
}
 No newline at end of file
+115 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 com.android.internal.app;

import static org.mockito.Mockito.mock;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.UserHandle;

import com.android.internal.app.chooser.TargetInfo;
import com.android.internal.logging.MetricsLogger;

import java.util.List;
import java.util.function.Function;

/**
 * Singleton providing overrides to be applied by any {@code IChooserWrapper} used in testing.
 * We cannot directly mock the activity created since instrumentation creates it, so instead we use
 * this singleton to modify behavior.
 */
public class ChooserActivityOverrideData {
    private static ChooserActivityOverrideData sInstance = null;

    public static ChooserActivityOverrideData getInstance() {
        if (sInstance == null) {
            sInstance = new ChooserActivityOverrideData();
        }
        return sInstance;
    }

    @SuppressWarnings("Since15")
    public Function<PackageManager, PackageManager> createPackageManager;
    public Function<TargetInfo, Boolean> onSafelyStartCallback;
    public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
    public ResolverListController resolverListController;
    public ResolverListController workResolverListController;
    public Boolean isVoiceInteraction;
    public boolean isImageType;
    public Cursor resolverCursor;
    public boolean resolverForceException;
    public Bitmap previewThumbnail;
    public MetricsLogger metricsLogger;
    public ChooserActivityLogger chooserActivityLogger;
    public int alternateProfileSetting;
    public Resources resources;
    public UserHandle workProfileUserHandle;
    public boolean hasCrossProfileIntents;
    public boolean isQuietModeEnabled;
    public boolean isWorkProfileUserRunning;
    public boolean isWorkProfileUserUnlocked;
    public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;
    public PackageManager packageManager;

    public void reset() {
        onSafelyStartCallback = null;
        onQueryDirectShareTargets = null;
        isVoiceInteraction = null;
        createPackageManager = null;
        previewThumbnail = null;
        isImageType = false;
        resolverCursor = null;
        resolverForceException = false;
        resolverListController = mock(ResolverListController.class);
        workResolverListController = mock(ResolverListController.class);
        metricsLogger = mock(MetricsLogger.class);
        chooserActivityLogger = new ChooserActivityLoggerFake();
        alternateProfileSetting = 0;
        resources = null;
        workProfileUserHandle = null;
        hasCrossProfileIntents = true;
        isQuietModeEnabled = false;
        isWorkProfileUserRunning = true;
        isWorkProfileUserUnlocked = true;
        packageManager = null;
        multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
            @Override
            public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
                    int targetUserId) {
                return hasCrossProfileIntents;
            }

            @Override
            public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
                return isQuietModeEnabled;
            }

            @Override
            public void requestQuietModeEnabled(boolean enabled,
                    UserHandle workProfileUserHandle) {
                isQuietModeEnabled = enabled;
            }
        };
    }

    private ChooserActivityOverrideData() {}
}
+667 −314

File changed.

Preview size limit exceeded, changes collapsed.

+24 −85
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.internal.app;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.annotation.Nullable;
@@ -41,13 +40,15 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import java.util.List;
import java.util.function.Function;

public class ChooserWrapperActivity extends ChooserActivity {
    /*
     * Simple wrapper around chooser activity to be able to initiate it under test
/**
 * Simple wrapper around chooser activity to be able to initiate it under test with overrides
 * specified in the {@code ChooserActivityOverrideData} singleton. This should be copy-and-pasted
 * verbatim to test other {@code ChooserActivity} subclasses (updating only the `extends` to match
 * the concrete activity under test).
 */
    static final OverrideData sOverrides = new OverrideData();
public class ChooserWrapperActivity extends ChooserActivity implements IChooserWrapper {
    static final ChooserActivityOverrideData sOverrides = ChooserActivityOverrideData.getInstance();
    private UsageStatsManager mUsm;

    @Override
@@ -72,16 +73,19 @@ public class ChooserWrapperActivity extends ChooserActivity {
                getChooserActivityLogger());
    }

    ChooserListAdapter getAdapter() {
    @Override
    public ChooserListAdapter getAdapter() {
        return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
    }

    ChooserListAdapter getPersonalListAdapter() {
    @Override
    public ChooserListAdapter getPersonalListAdapter() {
        return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0))
                .getListAdapter();
    }

    ChooserListAdapter getWorkListAdapter() {
    @Override
    public ChooserListAdapter getWorkListAdapter() {
        if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
            return null;
        }
@@ -89,7 +93,10 @@ public class ChooserWrapperActivity extends ChooserActivity {
                .getListAdapter();
    }

    boolean getIsSelected() { return mIsSuccessfullySelected; }
    @Override
    public boolean getIsSelected() {
        return mIsSuccessfullySelected;
    }

    @Override
    protected ComponentName getNearbySharingComponent() {
@@ -103,7 +110,8 @@ public class ChooserWrapperActivity extends ChooserActivity {
        return new ChooserWrapperActivity.EmptyTargetInfo();
    }

    UsageStatsManager getUsageStatsManager() {
    @Override
    public UsageStatsManager getUsageStatsManager() {
        if (mUsm == null) {
            mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
        }
@@ -172,7 +180,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
    }

    @Override
    protected ChooserActivityLogger getChooserActivityLogger() {
    public ChooserActivityLogger getChooserActivityLogger() {
        return sOverrides.chooserActivityLogger;
    }

@@ -197,6 +205,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
        return super.isWorkProfile();
    }

    @Override
    public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri,
            CharSequence pLabel, CharSequence pInfo, Intent replacementIntent,
            @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) {
@@ -209,7 +218,8 @@ public class ChooserWrapperActivity extends ChooserActivity {
        return sOverrides.workProfileUserHandle;
    }

    protected UserHandle getCurrentUserHandle() {
    @Override
    public UserHandle getCurrentUserHandle() {
        return mMultiProfilePagerAdapter.getCurrentUserHandle();
    }

@@ -248,75 +258,4 @@ public class ChooserWrapperActivity extends ChooserActivity {
        }
        return sOverrides.isWorkProfileUserUnlocked;
    }

    /**
     * We cannot directly mock the activity created since instrumentation creates it.
     * <p>
     * Instead, we use static instances of this object to modify behavior.
     */
    static class OverrideData {
        @SuppressWarnings("Since15")
        public Function<PackageManager, PackageManager> createPackageManager;
        public Function<TargetInfo, Boolean> onSafelyStartCallback;
        public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
        public ResolverListController resolverListController;
        public ResolverListController workResolverListController;
        public Boolean isVoiceInteraction;
        public boolean isImageType;
        public Cursor resolverCursor;
        public boolean resolverForceException;
        public Bitmap previewThumbnail;
        public MetricsLogger metricsLogger;
        public ChooserActivityLogger chooserActivityLogger;
        public int alternateProfileSetting;
        public Resources resources;
        public UserHandle workProfileUserHandle;
        public boolean hasCrossProfileIntents;
        public boolean isQuietModeEnabled;
        public boolean isWorkProfileUserRunning;
        public boolean isWorkProfileUserUnlocked;
        public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;
        public PackageManager packageManager;

        public void reset() {
            onSafelyStartCallback = null;
            onQueryDirectShareTargets = null;
            isVoiceInteraction = null;
            createPackageManager = null;
            previewThumbnail = null;
            isImageType = false;
            resolverCursor = null;
            resolverForceException = false;
            resolverListController = mock(ResolverListController.class);
            workResolverListController = mock(ResolverListController.class);
            metricsLogger = mock(MetricsLogger.class);
            chooserActivityLogger = new ChooserActivityLoggerFake();
            alternateProfileSetting = 0;
            resources = null;
            workProfileUserHandle = null;
            hasCrossProfileIntents = true;
            isQuietModeEnabled = false;
            isWorkProfileUserRunning = true;
            isWorkProfileUserUnlocked = true;
            packageManager = null;
            multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
                @Override
                public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
                        int targetUserId) {
                    return hasCrossProfileIntents;
                }

                @Override
                public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
                    return isQuietModeEnabled;
                }

                @Override
                public void requestQuietModeEnabled(boolean enabled,
                        UserHandle workProfileUserHandle) {
                    isQuietModeEnabled = enabled;
                }
            };
        }
    }
}
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 com.android.internal.app;

import android.annotation.Nullable;
import android.app.usage.UsageStatsManager;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;

import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
import com.android.internal.app.chooser.DisplayResolveInfo;

/**
 * Test-only extended API capabilities that an instrumented ChooserActivity subclass provides in
 * order to expose the internals for override/inspection. Implementations should apply the overrides
 * specified by the {@code ChooserActivityOverrideData} singleton.
 */
public interface IChooserWrapper {
    ChooserListAdapter getAdapter();
    ChooserListAdapter getPersonalListAdapter();
    ChooserListAdapter getWorkListAdapter();
    boolean getIsSelected();
    UsageStatsManager getUsageStatsManager();
    DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri,
            CharSequence pLabel, CharSequence pInfo, Intent replacementIntent,
            @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter);
    UserHandle getCurrentUserHandle();
    ChooserActivityLogger getChooserActivityLogger();
}