diff options
19 files changed, 48 insertions, 559 deletions
@@ -19,33 +19,12 @@ package { default_visibility: [":__subpackages__"], } -filegroup { - name: "ReleaseSources", - srcs: [ - "java/src-release/**/*.kt", - ], -} - -filegroup { - name: "DebugSources", - srcs: [ - "java/src-debug/**/*.kt", - ], -} - java_defaults { name: "Java_Defaults", srcs: [ "java/src/**/*.java", "java/src/**/*.kt", - ":ReleaseSources", ], - product_variables: { - debuggable: { - srcs: [":DebugSources"], - exclude_srcs: [":ReleaseSources"], - } - }, resource_dirs: [ "java/res", ], @@ -78,7 +57,6 @@ android_library { "kotlinx-coroutines-android", "//external/kotlinc:kotlin-annotations", "guava", - "SystemUIFlagsLib", ], } diff --git a/java/src-debug/com/android/intentresolver/flags/DebugFeatureFlagRepository.kt b/java/src-debug/com/android/intentresolver/flags/DebugFeatureFlagRepository.kt deleted file mode 100644 index 5067c0ee..00000000 --- a/java/src-debug/com/android/intentresolver/flags/DebugFeatureFlagRepository.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import android.util.SparseBooleanArray -import androidx.annotation.GuardedBy -import com.android.systemui.flags.BooleanFlag -import com.android.systemui.flags.FlagManager -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.UnreleasedFlag -import javax.annotation.concurrent.ThreadSafe - -@ThreadSafe -internal class DebugFeatureFlagRepository( - private val flagManager: FlagManager, - private val deviceConfig: DeviceConfigProxy, -) : FeatureFlagRepository { - @GuardedBy("self") - private val cache = hashMapOf<String, Boolean>() - - override fun isEnabled(flag: UnreleasedFlag): Boolean = isFlagEnabled(flag) - - override fun isEnabled(flag: ReleasedFlag): Boolean = isFlagEnabled(flag) - - private fun isFlagEnabled(flag: BooleanFlag): Boolean { - synchronized(cache) { - cache[flag.name]?.let { return it } - } - val flagValue = readFlagValue(flag) - return synchronized(cache) { - // the first read saved in the cache wins - cache.getOrPut(flag.name) { flagValue } - } - } - - private fun readFlagValue(flag: BooleanFlag): Boolean { - val localOverride = runCatching { - flagManager.isEnabled(flag.name) - }.getOrDefault(null) - val remoteOverride = deviceConfig.isEnabled(flag) - - // Only check for teamfood if the default is false - // and there is no server override. - if (remoteOverride == null - && !flag.default - && localOverride == null - && !flag.isTeamfoodFlag - && flag.teamfood - ) { - return flagManager.isTeamfoodEnabled - } - return localOverride ?: remoteOverride ?: flag.default - } - - companion object { - /** keep in sync with [com.android.systemui.flags.Flags] */ - private const val TEAMFOOD_FLAG_NAME = "teamfood" - - private val BooleanFlag.isTeamfoodFlag: Boolean - get() = name == TEAMFOOD_FLAG_NAME - - private val FlagManager.isTeamfoodEnabled: Boolean - get() = runCatching { - isEnabled(TEAMFOOD_FLAG_NAME) ?: false - }.getOrDefault(false) - } -} diff --git a/java/src-debug/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt b/java/src-debug/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt deleted file mode 100644 index 4ddb0447..00000000 --- a/java/src-debug/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import android.content.Context -import android.os.Handler -import android.os.Looper -import com.android.systemui.flags.FlagManager - -class FeatureFlagRepositoryFactory { - fun create(context: Context): FeatureFlagRepository = - DebugFeatureFlagRepository( - FlagManager(context, Handler(Looper.getMainLooper())), - DeviceConfigProxy(), - ) -} diff --git a/java/src-release/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt b/java/src-release/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt deleted file mode 100644 index 6bf7579e..00000000 --- a/java/src-release/com/android/intentresolver/flags/FeatureFlagRepositoryFactory.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import android.content.Context - -class FeatureFlagRepositoryFactory { - fun create(context: Context): FeatureFlagRepository = - ReleaseFeatureFlagRepository(DeviceConfigProxy()) -} diff --git a/java/src-release/com/android/intentresolver/flags/ReleaseFeatureFlagRepository.kt b/java/src-release/com/android/intentresolver/flags/ReleaseFeatureFlagRepository.kt deleted file mode 100644 index f9fa2c6a..00000000 --- a/java/src-release/com/android/intentresolver/flags/ReleaseFeatureFlagRepository.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.UnreleasedFlag -import javax.annotation.concurrent.ThreadSafe - -@ThreadSafe -internal class ReleaseFeatureFlagRepository( - private val deviceConfig: DeviceConfigProxy, -) : FeatureFlagRepository { - override fun isEnabled(flag: UnreleasedFlag): Boolean = flag.default - - override fun isEnabled(flag: ReleasedFlag): Boolean = - deviceConfig.isEnabled(flag) ?: flag.default -} diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 1e670a21..0101c046 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -23,9 +23,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE; import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL; import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; - import static androidx.lifecycle.LifecycleKt.getCoroutineScope; - import static com.android.internal.util.LatencyTracker.ACTION_LOAD_SHARE_SHEET; import android.annotation.IntDef; @@ -85,8 +83,6 @@ import com.android.intentresolver.contentpreview.BasePreviewViewModel; import com.android.intentresolver.contentpreview.ChooserContentPreviewUi; import com.android.intentresolver.contentpreview.HeadlineGeneratorImpl; import com.android.intentresolver.contentpreview.PreviewViewModel; -import com.android.intentresolver.flags.FeatureFlagRepository; -import com.android.intentresolver.flags.FeatureFlagRepositoryFactory; import com.android.intentresolver.grid.ChooserGridAdapter; import com.android.intentresolver.icons.DefaultTargetDataLoader; import com.android.intentresolver.icons.TargetDataLoader; @@ -119,6 +115,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; +import javax.inject.Inject; + /** * The Chooser Activity handles intent resolution specifically for sharing intents - * for example, as generated by {@see android.content.Intent#createChooser(Intent, CharSequence)}. @@ -175,6 +173,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements @Retention(RetentionPolicy.SOURCE) public @interface ShareTargetType {} + @Inject public FeatureFlags mFeatureFlags; + private ChooserIntegratedDeviceComponents mIntegratedDeviceComponents; /* TODO: this is `nullable` because we have to defer the assignment til onCreate(). We make the @@ -188,7 +188,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements private ChooserRefinementManager mRefinementManager; - private FeatureFlagRepository mFeatureFlagRepository; private ChooserContentPreviewUi mChooserContentPreviewUi; private boolean mShouldDisplayLandscape; @@ -242,15 +241,11 @@ public class ChooserActivity extends Hilt_ChooserActivity implements getEventLog().logSharesheetTriggered(); - mFeatureFlagRepository = createFeatureFlagRepository(); - mIntegratedDeviceComponents = getIntegratedDeviceComponents(); - try { mChooserRequest = new ChooserRequestParameters( getIntent(), getReferrerPackageName(), - getReferrer(), - mFeatureFlagRepository); + getReferrer()); } catch (IllegalArgumentException e) { Log.e(TAG, "Caller provided invalid Chooser request parameters", e); finish(); @@ -265,7 +260,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements createProfileRecords( new AppPredictorFactory( - getApplicationContext(), + this, // TODO: Review w/team, possible side effects? mChooserRequest.getSharedText(), mChooserRequest.getTargetIntentFilter()), mChooserRequest.getTargetIntentFilter()); @@ -283,7 +278,10 @@ public class ChooserActivity extends Hilt_ChooserActivity implements new DefaultTargetDataLoader(this, getLifecycle(), false), /* safeForwardingMode= */ true); - mFeatureFlagRepository = createFeatureFlagRepository(); + if (mFeatureFlags.exampleNewSharingMethod()) { + // Sample flag usage + } + mIntegratedDeviceComponents = getIntegratedDeviceComponents(); mRefinementManager = new ViewModelProvider(this).get(ChooserRefinementManager.class); @@ -371,10 +369,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements return R.style.Theme_DeviceDefault_Chooser; } - protected FeatureFlagRepository createFeatureFlagRepository() { - return new FeatureFlagRepositoryFactory().create(getApplicationContext()); - } - private void createProfileRecords( AppPredictorFactory factory, IntentFilter targetIntentFilter) { UserHandle mainUserHandle = getPersonalProfileUserHandle(); @@ -395,7 +389,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements ShortcutLoader shortcutLoader = ActivityManager.isLowRamDeviceStatic() ? null : createShortcutLoader( - getApplicationContext(), + this, // TODO: Review w/team, possible side effects? appPredictor, userHandle, targetIntentFilter, diff --git a/java/src/com/android/intentresolver/ChooserRequestParameters.java b/java/src/com/android/intentresolver/ChooserRequestParameters.java index 5157986b..b05d51b2 100644 --- a/java/src/com/android/intentresolver/ChooserRequestParameters.java +++ b/java/src/com/android/intentresolver/ChooserRequestParameters.java @@ -32,7 +32,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; -import com.android.intentresolver.flags.FeatureFlagRepository; import com.android.intentresolver.util.UriFilters; import com.google.common.collect.ImmutableList; @@ -104,8 +103,7 @@ public class ChooserRequestParameters { public ChooserRequestParameters( final Intent clientIntent, String referrerPackageName, - final Uri referrer, - FeatureFlagRepository featureFlags) { + final Uri referrer) { final Intent requestedTarget = parseTargetIntentExtra( clientIntent.getParcelableExtra(Intent.EXTRA_INTENT)); mTarget = intentWithModifiedLaunchFlags(requestedTarget); diff --git a/java/src/com/android/intentresolver/flags/DeviceConfigProxy.kt b/java/src/com/android/intentresolver/flags/DeviceConfigProxy.kt deleted file mode 100644 index d1494fe7..00000000 --- a/java/src/com/android/intentresolver/flags/DeviceConfigProxy.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import android.provider.DeviceConfig -import com.android.systemui.flags.ParcelableFlag - -internal class DeviceConfigProxy { - fun isEnabled(flag: ParcelableFlag<Boolean>): Boolean? { - return runCatching { - val hasProperty = DeviceConfig.getProperty(flag.namespace, flag.name) != null - if (hasProperty) { - DeviceConfig.getBoolean(flag.namespace, flag.name, flag.default) - } else { - null - } - }.getOrDefault(null) - } -} diff --git a/java/src/com/android/intentresolver/flags/FeatureFlagRepository.kt b/java/src/com/android/intentresolver/flags/FeatureFlagRepository.kt deleted file mode 100644 index 5b5d769c..00000000 --- a/java/src/com/android/intentresolver/flags/FeatureFlagRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.UnreleasedFlag - -interface FeatureFlagRepository { - fun isEnabled(flag: UnreleasedFlag): Boolean - fun isEnabled(flag: ReleasedFlag): Boolean -} diff --git a/java/src/com/android/intentresolver/flags/Flags.kt b/java/src/com/android/intentresolver/flags/Flags.kt deleted file mode 100644 index 2c20d341..00000000 --- a/java/src/com/android/intentresolver/flags/Flags.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2022 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.intentresolver.flags - -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.UnreleasedFlag - -// Flag id, name and namespace should be kept in sync with [com.android.systemui.flags.Flags] to -// make the flags available in the flag flipper app (see go/sysui-flags). -// All flags added should be included in UnbundledChooserActivityTest.ALL_FLAGS. -object Flags { - private fun releasedFlag(name: String) = ReleasedFlag(name, "systemui") - - private fun unreleasedFlag(name: String, teamfood: Boolean = false) = - UnreleasedFlag(name, "systemui", teamfood) -} diff --git a/java/src/com/android/intentresolver/inject/FeatureFlagsModule.kt b/java/src/com/android/intentresolver/inject/FeatureFlagsModule.kt new file mode 100644 index 00000000..05cf2104 --- /dev/null +++ b/java/src/com/android/intentresolver/inject/FeatureFlagsModule.kt @@ -0,0 +1,15 @@ +package com.android.intentresolver.inject + +import com.android.intentresolver.FeatureFlags +import com.android.intentresolver.FeatureFlagsImpl +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@Module +@InstallIn(SingletonComponent::class) +object FeatureFlagsModule { + + @Provides fun featureFlags(): FeatureFlags = FeatureFlagsImpl() +} diff --git a/java/src/com/android/intentresolver/inject/Qualifiers.kt b/java/src/com/android/intentresolver/inject/Qualifiers.kt index 2bfb1ff9..fca1e896 100644 --- a/java/src/com/android/intentresolver/inject/Qualifiers.kt +++ b/java/src/com/android/intentresolver/inject/Qualifiers.kt @@ -20,6 +20,11 @@ import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ActivityOwned +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class ApplicationOwned + @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class Background @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class Default diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java index 84f5124c..5b938aa1 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java +++ b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java @@ -29,7 +29,6 @@ import android.os.UserHandle; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.contentpreview.ImageLoader; -import com.android.intentresolver.flags.FeatureFlagRepository; import com.android.intentresolver.logging.EventLog; import com.android.intentresolver.shortcuts.ShortcutLoader; @@ -77,7 +76,6 @@ public class ChooserActivityOverrideData { public WorkProfileAvailabilityManager mWorkProfileAvailability; public CrossProfileIntentsChecker mCrossProfileIntentsChecker; public PackageManager packageManager; - public FeatureFlagRepository featureFlagRepository; public void reset() { onSafelyStartInternalCallback = null; @@ -127,7 +125,6 @@ public class ChooserActivityOverrideData { mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class); when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt())) .thenAnswer(invocation -> hasCrossProfileIntents); - featureFlagRepository = null; } private ChooserActivityOverrideData() {} diff --git a/java/tests/src/com/android/intentresolver/ChooserRequestParametersTest.kt b/java/tests/src/com/android/intentresolver/ChooserRequestParametersTest.kt index 331d1c21..90f6cf93 100644 --- a/java/tests/src/com/android/intentresolver/ChooserRequestParametersTest.kt +++ b/java/tests/src/com/android/intentresolver/ChooserRequestParametersTest.kt @@ -29,7 +29,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ChooserRequestParametersTest { - val flags = TestFeatureFlagRepository(mapOf()) @Test fun testChooserActions() { @@ -41,7 +40,7 @@ class ChooserRequestParametersTest { putExtra(Intent.EXTRA_INTENT, intent) putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions) } - val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY, flags) + val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY) assertThat(request.chooserActions).containsExactlyElementsIn(actions).inOrder() } @@ -50,7 +49,7 @@ class ChooserRequestParametersTest { val intent = Intent(Intent.ACTION_SEND) val chooserIntent = Intent(Intent.ACTION_CHOOSER).apply { putExtra(Intent.EXTRA_INTENT, intent) } - val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY, flags) + val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY) assertThat(request.chooserActions).isEmpty() } @@ -64,7 +63,7 @@ class ChooserRequestParametersTest { putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, chooserActions) } - val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY, flags) + val request = ChooserRequestParameters(chooserIntent, "", Uri.EMPTY) val expectedActions = chooserActions.sliceArray(0 until 5) assertThat(request.chooserActions).containsExactlyElementsIn(expectedActions).inOrder() diff --git a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java index 8c2a15f1..578b9557 100644 --- a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java +++ b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java @@ -37,7 +37,6 @@ import androidx.lifecycle.ViewModelProvider; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.TargetInfo; -import com.android.intentresolver.flags.FeatureFlagRepository; import com.android.intentresolver.grid.ChooserGridAdapter; import com.android.intentresolver.icons.TargetDataLoader; import com.android.intentresolver.logging.EventLog; @@ -282,12 +281,4 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW return super.createShortcutLoader( context, appPredictor, userHandle, targetIntentFilter, callback); } - - @Override - protected FeatureFlagRepository createFeatureFlagRepository() { - if (sOverrides.featureFlagRepository != null) { - return sOverrides.featureFlagRepository; - } - return super.createFeatureFlagRepository(); - } } diff --git a/java/tests/src/com/android/intentresolver/FeatureFlagRule.kt b/java/tests/src/com/android/intentresolver/FeatureFlagRule.kt deleted file mode 100644 index 3fa01bcc..00000000 --- a/java/tests/src/com/android/intentresolver/FeatureFlagRule.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2023 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.intentresolver - -import com.android.systemui.flags.BooleanFlag -import org.junit.rules.TestRule -import org.junit.runner.Description -import org.junit.runners.model.Statement - -/** - * Ignores tests annotated with [RequireFeatureFlags] which flag requirements does not - * meet in the active flag set. - * @param flags active flag set - */ -internal class FeatureFlagRule(flags: Map<BooleanFlag, Boolean>) : TestRule { - private val flags = flags.entries.fold(HashMap<String, Boolean>()) { map, (key, value) -> - map.apply { - put(key.name, value) - } - } - private val skippingStatement = object : Statement() { - override fun evaluate() = Unit - } - - override fun apply(base: Statement, description: Description): Statement { - val annotation = description.annotations.firstOrNull { - it is RequireFeatureFlags - } as? RequireFeatureFlags - ?: return base - - if (annotation.flags.size != annotation.values.size) { - error("${description.className}#${description.methodName}: inconsistent number of" + - " flags and values in $annotation") - } - for (i in annotation.flags.indices) { - val flag = annotation.flags[i] - val value = annotation.values[i] - if (flags.getOrDefault(flag, !value) != value) return skippingStatement - } - return base - } -} diff --git a/java/tests/src/com/android/intentresolver/RequireFeatureFlags.kt b/java/tests/src/com/android/intentresolver/RequireFeatureFlags.kt deleted file mode 100644 index 1ddf7462..00000000 --- a/java/tests/src/com/android/intentresolver/RequireFeatureFlags.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2023 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.intentresolver - -/** - * Specifies expected feature flag values for a test. - */ -@Target(AnnotationTarget.FUNCTION) -annotation class RequireFeatureFlags(val flags: Array<String>, val values: BooleanArray) diff --git a/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt b/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt deleted file mode 100644 index b9047712..00000000 --- a/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2023 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.intentresolver - -import com.android.intentresolver.flags.FeatureFlagRepository -import com.android.systemui.flags.BooleanFlag -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.UnreleasedFlag - -class TestFeatureFlagRepository( - private val overrides: Map<BooleanFlag, Boolean> -) : FeatureFlagRepository { - override fun isEnabled(flag: UnreleasedFlag): Boolean = getValue(flag) - override fun isEnabled(flag: ReleasedFlag): Boolean = getValue(flag) - - private fun getValue(flag: BooleanFlag) = overrides.getOrDefault(flag, flag.default) -} diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index aca78604..59357843 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -17,7 +17,6 @@ package com.android.intentresolver; import static android.app.Activity.RESULT_OK; - import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.longClick; @@ -29,7 +28,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; - import static com.android.intentresolver.ChooserActivity.TARGET_TYPE_CHOOSER_TARGET; import static com.android.intentresolver.ChooserActivity.TARGET_TYPE_DEFAULT; import static com.android.intentresolver.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE; @@ -37,11 +35,8 @@ import static com.android.intentresolver.ChooserActivity.TARGET_TYPE_SHORTCUTS_F import static com.android.intentresolver.ChooserListAdapter.CALLER_TARGET_SCORE_BOOST; import static com.android.intentresolver.ChooserListAdapter.SHORTCUT_TARGET_SCORE_BOOST; import static com.android.intentresolver.MatcherUtils.first; - import static com.google.common.truth.Truth.assertThat; - import static junit.framework.Assert.assertNull; - import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -105,7 +100,6 @@ import android.view.View; import android.view.WindowManager; import android.widget.TextView; -import androidx.annotation.CallSuper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.GridLayoutManager; @@ -122,7 +116,6 @@ import com.android.intentresolver.logging.EventLog; import com.android.intentresolver.shortcuts.ShortcutLoader; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.flags.BooleanFlag; import org.hamcrest.Description; import org.hamcrest.Matcher; @@ -131,8 +124,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.ArgumentCaptor; @@ -155,27 +146,14 @@ import java.util.function.Consumer; import java.util.function.Function; /** - * Instrumentation tests for the IntentResolver module's Sharesheet (ChooserActivity). - * TODO: remove methods that supported running these tests against arbitrary ChooserActivity - * subclasses. Those were left over from an earlier version where IntentResolver's ChooserActivity - * inherited from the framework version at com.android.internal.app.ChooserActivity, and this test - * file inherited from the framework's version as well. Once the migration to the IntentResolver - * package is complete, that aspect of the test design can revert to match the style of the - * framework tests prior to ag/16482932. - * TODO: this can simply be renamed to "ChooserActivityTest" if that's ever unambiguous (i.e., if - * there's no risk of confusion with the framework tests that currently share the same name). + * Instrumentation tests for ChooserActivity. + * <p> + * Legacy test suite migrated from framework CoreTests. + * <p> */ @RunWith(Parameterized.class) public class UnbundledChooserActivityTest { - /* -------- - * Subclasses should copy the following section verbatim (or alternatively could specify some - * additional @Parameterized.Parameters, as long as the correct parameters are used to - * initialize the ChooserActivityTest). The subclasses should also be @RunWith the - * `Parameterized` runner. - * -------- - */ - private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry .getInstrumentation().getTargetContext().getUser(); private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm; @@ -186,56 +164,18 @@ public class UnbundledChooserActivityTest { return mock; }; - private static final List<BooleanFlag> ALL_FLAGS = - Arrays.asList(); - - private static final Map<BooleanFlag, Boolean> ALL_FLAGS_OFF = - createAllFlagsOverride(false); - private static final Map<BooleanFlag, Boolean> ALL_FLAGS_ON = - createAllFlagsOverride(true); - @Parameterized.Parameters public static Collection packageManagers() { - if (ALL_FLAGS.isEmpty()) { - // No flags to toggle between, so just two configurations. - return Arrays.asList(new Object[][] { - // Default PackageManager and all flags off - { DEFAULT_PM, ALL_FLAGS_OFF}, - // No App Prediction Service and all flags off - { NO_APP_PREDICTION_SERVICE_PM, ALL_FLAGS_OFF }, - }); - } return Arrays.asList(new Object[][] { - // Default PackageManager and all flags off - { DEFAULT_PM, ALL_FLAGS_OFF}, - // Default PackageManager and all flags on - { DEFAULT_PM, ALL_FLAGS_ON}, - // No App Prediction Service and all flags off - { NO_APP_PREDICTION_SERVICE_PM, ALL_FLAGS_OFF }, - // No App Prediction Service and all flags on - { NO_APP_PREDICTION_SERVICE_PM, ALL_FLAGS_ON } + // Default PackageManager + { DEFAULT_PM }, + // No App Prediction Service + { NO_APP_PREDICTION_SERVICE_PM} }); } - private static Map<BooleanFlag, Boolean> createAllFlagsOverride(boolean value) { - HashMap<BooleanFlag, Boolean> overrides = new HashMap<>(ALL_FLAGS.size()); - for (BooleanFlag flag : ALL_FLAGS) { - overrides.put(flag, value); - } - return overrides; - } - - /* -------- - * Subclasses can override the following methods to customize test behavior. - * -------- - */ - - /** - * Perform any necessary per-test initialization steps (subclasses may add additional steps - * before and/or after calling up to the superclass implementation). - */ - @CallSuper - protected void setup() { + @Before + public void setUp() { // TODO: use the other form of `adoptShellPermissionIdentity()` where we explicitly list the // permissions we require (which we'll read from the manifest at runtime). InstrumentationRegistry @@ -244,67 +184,11 @@ public class UnbundledChooserActivityTest { .adoptShellPermissionIdentity(); cleanOverrideData(); - ChooserActivityOverrideData.getInstance().featureFlagRepository = - new TestFeatureFlagRepository(mFlags); - } - - /** - * Given an intent that was constructed in a test, perform any additional configuration to - * specify the appropriate concrete ChooserActivity subclass. The activity launched by this - * intent must descend from android.intentresolver.ChooserActivity (for our ActivityTestRule), and - * must also implement the android.intentresolver.IChooserWrapper interface (since test code will - * assume the ability to make unsafe downcasts). - */ - protected Intent getConcreteIntentForLaunch(Intent clientIntent) { - clientIntent.setClass( - InstrumentationRegistry.getInstrumentation().getTargetContext(), - com.android.intentresolver.ChooserWrapperActivity.class); - return clientIntent; - } - - /** - * Whether {@code #testIsAppPredictionServiceAvailable} should verify the behavior after - * changing the availability conditions at runtime. In the unbundled chooser, the availability - * is cached at start and will never be re-evaluated. - * TODO: remove when we no longer want to test the system's on-the-fly evaluation. - */ - protected boolean shouldTestTogglingAppPredictionServiceAvailabilityAtRuntime() { - return false; } - /* -------- - * The code in this section is unorthodox and can be simplified/reverted when we no longer need - * to support the parallel chooser implementations. - * -------- - */ - @Rule - public final TestRule mRule; - - // Shared test code references the activity under test as ChooserActivity, the common ancestor - // of any (inheritance-based) chooser implementation. For testing purposes, that activity will - // usually be cast to IChooserWrapper to expose instrumentation. - private ActivityTestRule<ChooserActivity> mActivityRule = - new ActivityTestRule<>(ChooserActivity.class, false, false) { - @Override - public ChooserActivity launchActivity(Intent clientIntent) { - return super.launchActivity(getConcreteIntentForLaunch(clientIntent)); - } - }; - - @Before - public final void doPolymorphicSetup() { - // The base class needs a @Before-annotated setup for when it runs against the system - // chooser, while subclasses need to be able to specify their own setup behavior. Notably - // the unbundled chooser, running in user-space, needs to take additional steps before it - // can run #cleanOverrideData() (which writes to DeviceConfig). - setup(); - } - - /* -------- - * Subclasses can ignore the remaining code and inherit the full suite of tests. - * -------- - */ + public ActivityTestRule<ChooserWrapperActivity> mActivityRule = + new ActivityTestRule<>(ChooserWrapperActivity.class, false, false); private static final String TEST_MIME_TYPE = "application/TestType"; @@ -313,18 +197,10 @@ public class UnbundledChooserActivityTest { private static final int CONTENT_PREVIEW_TEXT = 3; private final Function<PackageManager, PackageManager> mPackageManagerOverride; - private final Map<BooleanFlag, Boolean> mFlags; - public UnbundledChooserActivityTest( - Function<PackageManager, PackageManager> packageManagerOverride, - Map<BooleanFlag, Boolean> flags) { + Function<PackageManager, PackageManager> packageManagerOverride) { mPackageManagerOverride = packageManagerOverride; - mFlags = flags; - - mRule = RuleChain - .outerRule(new FeatureFlagRule(flags)) - .around(mActivityRule); } private void setDeviceConfigProperty( |