Loading src/com/android/documentsui/util/FlagUtils.kt +31 −28 Original line number Diff line number Diff line Loading @@ -21,12 +21,9 @@ import android.util.Log import com.android.documentsui.flags.Flags import com.android.modules.utils.build.SdkLevel /** * Wrap aconfig generated flags to allow us to override flags in tests. */ class FlagUtils private constructor( private val overrides: MutableMap<String, Boolean> = mutableMapOf() ) { /** Wrap aconfig generated flags to allow us to override flags in tests. */ class FlagUtils private constructor(private val overrides: MutableMap<String, Boolean> = mutableMapOf()) { companion object { private const val TAG = "FlagUtils" @Volatile private var instance: FlagUtils = FlagUtils() Loading Loading @@ -69,27 +66,26 @@ class FlagUtils private constructor( @JvmStatic fun isSearchV2Enabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_USE_SEARCH_V2_READ_ONLY, Flags.useSearchV2ReadOnly() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_USE_SEARCH_V2_READ_ONLY, Flags.useSearchV2ReadOnly()) return flag && isUseMaterial3FlagEnabled() } @JvmStatic fun isDesktopFileHandlingFlagEnabled(): Boolean { return getInstance().overrides.getOrDefault( Flags.FLAG_DESKTOP_FILE_HANDLING_RO, Flags.desktopFileHandlingRo() ) return getInstance() .overrides .getOrDefault(Flags.FLAG_DESKTOP_FILE_HANDLING_RO, Flags.desktopFileHandlingRo()) } @JvmStatic fun isDesktopUxPhase2FlagEnabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_DESKTOP_UX_PHASE_2_RO, Flags.desktopUxPhase2Ro() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_DESKTOP_UX_PHASE_2_RO, Flags.desktopUxPhase2Ro()) return flag && isUseMaterial3FlagEnabled() } Loading @@ -102,10 +98,10 @@ class FlagUtils private constructor( @JvmStatic fun isVisualSignalsFlagEnabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_VISUAL_SIGNALS_RO, Flags.visualSignalsRo() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_VISUAL_SIGNALS_RO, Flags.visualSignalsRo()) return flag && isUseMaterial3FlagEnabled() } Loading @@ -118,17 +114,24 @@ class FlagUtils private constructor( @JvmStatic fun isTrashFlowEnabled(): Boolean { if (!SdkLevel.isAtLeastB()) { // Check if the platform SDK is newer than Android Baklava (SDK 36). // The Trash feature relies on DocumentsContract APIs introduced in the // Android release after Baklava. // This specific Trash feature is NOT backward compatible with platforms // at or below Baklava because the required APIs are missing. // This check ensures the feature is only considered enabled on // supported platform versions, preventing runtime errors if the module // runs on an older base OS. if (!VersionUtils.isGreaterThanB()) { return false } // If API flag is not enabled, then trash flow will be disabled if (!enableDocumentsTrashApi()) { return false } return getInstance().overrides.getOrDefault( Flags.FLAG_ENABLE_TRASH_FLOW_RO, Flags.enableTrashFlowRo() ) return getInstance() .overrides .getOrDefault(Flags.FLAG_ENABLE_TRASH_FLOW_RO, Flags.enableTrashFlowRo()) } @JvmStatic Loading src/com/android/documentsui/util/VersionUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.documentsui.util; import android.os.Build; import com.android.modules.utils.build.SdkLevel; /** Loading @@ -40,4 +42,11 @@ public class VersionUtils { public static boolean isAtLeastS() { return SdkLevel.isAtLeastS(); } /** * Returns whether the device is running on a version newer than Android BAKLAVA. */ public static boolean isGreaterThanB() { return Build.VERSION.SDK_INT > Build.VERSION_CODES.BAKLAVA; } } tests/functional/com/android/documentsui/services/AbstractJobTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -86,9 +86,11 @@ public abstract class AbstractJobTest<T extends Job> { @After public void tearDown() throws Exception { if (mDocs != null) { resetStorage(); mDocs.cleanUp(); } } private void resetStorage() throws RemoteException { mDocs.clear(null, null); Loading tests/functional/com/android/documentsui/services/RestoreJobTest.kt +15 −3 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Notification.CATEGORY_ERROR import android.app.Notification.EXTRA_TEXT import android.app.Notification.EXTRA_TITLE import android.net.Uri import android.os.Build import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule Loading @@ -28,12 +27,13 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.provider.DocumentsContract.buildDocumentUri import android.provider.Flags.FLAG_ENABLE_DOCUMENTS_TRASH_API import androidx.test.filters.MediumTest import androidx.test.filters.SdkSuppress import com.android.documentsui.TrashDocumentHelper import com.android.documentsui.flags.Flags import com.android.documentsui.rules.OverrideFlagsRule import com.android.documentsui.services.FileOperationService.OPERATION_RESTORE import com.android.documentsui.util.VersionUtils import com.google.common.truth.Truth.assertThat import org.junit.Assume.assumeTrue import org.junit.Rule import org.junit.Test Loading @@ -52,13 +52,25 @@ import org.junit.Test * directories (<parent_1>, <parent_2>) inside ".trash-storage" are then removed. */ @MediumTest @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) internal class RestoreJobTest : AbstractJobTest<TrashJob>() { @get:Rule val setFlags = OverrideFlagsRule() @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() override fun setUp() { // Skip test if the platform SDK is not newer than Android Baklava (SDK 36). // The Trash feature under test relies on DocumentsContract APIs introduced in the // Android release after Baklava (SDK 36). // As DocumentsUI is a Mainline module, it's subject to MTS testing, which runs on // older Android base builds to verify backward compatibility. However, this specific // Trash feature lacks backward compatibility with platforms at or below Baklava. // This assumption prevents failures when the test runs on an older base OS // without the necessary APIs. assumeTrue(VersionUtils.isGreaterThanB()) super.setUp() } /** * Tests the restoration of a single file. Verifies that the file is moved to its original path * and that the parent directories within the trash are removed. Loading tests/functional/com/android/documentsui/services/TrashJobTest.kt +16 −7 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Notification.CATEGORY_ERROR import android.app.Notification.EXTRA_TEXT import android.app.Notification.EXTRA_TITLE import android.net.Uri import android.os.Build import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule Loading @@ -28,26 +27,39 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.provider.DocumentsContract.buildDocumentUri import android.provider.Flags.FLAG_ENABLE_DOCUMENTS_TRASH_API import androidx.test.filters.MediumTest import androidx.test.filters.SdkSuppress import com.android.documentsui.TrashDocumentHelper import com.android.documentsui.base.DocumentInfo import com.android.documentsui.flags.Flags import com.android.documentsui.rules.OverrideFlagsRule import com.android.documentsui.services.FileOperationService.OPERATION_TRASH import com.android.documentsui.util.VersionUtils import com.google.common.truth.Truth.assertThat import org.junit.Assume.assumeTrue import org.junit.Rule import org.junit.Test /** Tests TrashJob. */ @MediumTest @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) internal class TrashJobTest : AbstractJobTest<TrashJob>() { @get:Rule val setFlags = OverrideFlagsRule() @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() override fun setUp() { // Skip test if the platform SDK is not newer than Android Baklava (SDK 36). // The Trash feature under test relies on DocumentsContract APIs introduced in the // Android release after Baklava (SDK 36). // As DocumentsUI is a Mainline module, it's subject to MTS testing, which runs on // older Android base builds to verify backward compatibility. However, this specific // Trash feature lacks backward compatibility with platforms at or below Baklava. // This assumption prevents failures when the test runs on an older base OS // without the necessary APIs. assumeTrue(VersionUtils.isGreaterThanB()) super.setUp() } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashSingleFile() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -92,7 +104,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashMultipleFile() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -140,7 +151,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashFolder() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -203,7 +213,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashFailedNoFileFound() { // create a document in mDestRoot, trashDocument only working for mSrcRoot, Loading Loading
src/com/android/documentsui/util/FlagUtils.kt +31 −28 Original line number Diff line number Diff line Loading @@ -21,12 +21,9 @@ import android.util.Log import com.android.documentsui.flags.Flags import com.android.modules.utils.build.SdkLevel /** * Wrap aconfig generated flags to allow us to override flags in tests. */ class FlagUtils private constructor( private val overrides: MutableMap<String, Boolean> = mutableMapOf() ) { /** Wrap aconfig generated flags to allow us to override flags in tests. */ class FlagUtils private constructor(private val overrides: MutableMap<String, Boolean> = mutableMapOf()) { companion object { private const val TAG = "FlagUtils" @Volatile private var instance: FlagUtils = FlagUtils() Loading Loading @@ -69,27 +66,26 @@ class FlagUtils private constructor( @JvmStatic fun isSearchV2Enabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_USE_SEARCH_V2_READ_ONLY, Flags.useSearchV2ReadOnly() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_USE_SEARCH_V2_READ_ONLY, Flags.useSearchV2ReadOnly()) return flag && isUseMaterial3FlagEnabled() } @JvmStatic fun isDesktopFileHandlingFlagEnabled(): Boolean { return getInstance().overrides.getOrDefault( Flags.FLAG_DESKTOP_FILE_HANDLING_RO, Flags.desktopFileHandlingRo() ) return getInstance() .overrides .getOrDefault(Flags.FLAG_DESKTOP_FILE_HANDLING_RO, Flags.desktopFileHandlingRo()) } @JvmStatic fun isDesktopUxPhase2FlagEnabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_DESKTOP_UX_PHASE_2_RO, Flags.desktopUxPhase2Ro() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_DESKTOP_UX_PHASE_2_RO, Flags.desktopUxPhase2Ro()) return flag && isUseMaterial3FlagEnabled() } Loading @@ -102,10 +98,10 @@ class FlagUtils private constructor( @JvmStatic fun isVisualSignalsFlagEnabled(): Boolean { val flag = getInstance().overrides.getOrDefault( Flags.FLAG_VISUAL_SIGNALS_RO, Flags.visualSignalsRo() ) val flag = getInstance() .overrides .getOrDefault(Flags.FLAG_VISUAL_SIGNALS_RO, Flags.visualSignalsRo()) return flag && isUseMaterial3FlagEnabled() } Loading @@ -118,17 +114,24 @@ class FlagUtils private constructor( @JvmStatic fun isTrashFlowEnabled(): Boolean { if (!SdkLevel.isAtLeastB()) { // Check if the platform SDK is newer than Android Baklava (SDK 36). // The Trash feature relies on DocumentsContract APIs introduced in the // Android release after Baklava. // This specific Trash feature is NOT backward compatible with platforms // at or below Baklava because the required APIs are missing. // This check ensures the feature is only considered enabled on // supported platform versions, preventing runtime errors if the module // runs on an older base OS. if (!VersionUtils.isGreaterThanB()) { return false } // If API flag is not enabled, then trash flow will be disabled if (!enableDocumentsTrashApi()) { return false } return getInstance().overrides.getOrDefault( Flags.FLAG_ENABLE_TRASH_FLOW_RO, Flags.enableTrashFlowRo() ) return getInstance() .overrides .getOrDefault(Flags.FLAG_ENABLE_TRASH_FLOW_RO, Flags.enableTrashFlowRo()) } @JvmStatic Loading
src/com/android/documentsui/util/VersionUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.documentsui.util; import android.os.Build; import com.android.modules.utils.build.SdkLevel; /** Loading @@ -40,4 +42,11 @@ public class VersionUtils { public static boolean isAtLeastS() { return SdkLevel.isAtLeastS(); } /** * Returns whether the device is running on a version newer than Android BAKLAVA. */ public static boolean isGreaterThanB() { return Build.VERSION.SDK_INT > Build.VERSION_CODES.BAKLAVA; } }
tests/functional/com/android/documentsui/services/AbstractJobTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -86,9 +86,11 @@ public abstract class AbstractJobTest<T extends Job> { @After public void tearDown() throws Exception { if (mDocs != null) { resetStorage(); mDocs.cleanUp(); } } private void resetStorage() throws RemoteException { mDocs.clear(null, null); Loading
tests/functional/com/android/documentsui/services/RestoreJobTest.kt +15 −3 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Notification.CATEGORY_ERROR import android.app.Notification.EXTRA_TEXT import android.app.Notification.EXTRA_TITLE import android.net.Uri import android.os.Build import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule Loading @@ -28,12 +27,13 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.provider.DocumentsContract.buildDocumentUri import android.provider.Flags.FLAG_ENABLE_DOCUMENTS_TRASH_API import androidx.test.filters.MediumTest import androidx.test.filters.SdkSuppress import com.android.documentsui.TrashDocumentHelper import com.android.documentsui.flags.Flags import com.android.documentsui.rules.OverrideFlagsRule import com.android.documentsui.services.FileOperationService.OPERATION_RESTORE import com.android.documentsui.util.VersionUtils import com.google.common.truth.Truth.assertThat import org.junit.Assume.assumeTrue import org.junit.Rule import org.junit.Test Loading @@ -52,13 +52,25 @@ import org.junit.Test * directories (<parent_1>, <parent_2>) inside ".trash-storage" are then removed. */ @MediumTest @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) internal class RestoreJobTest : AbstractJobTest<TrashJob>() { @get:Rule val setFlags = OverrideFlagsRule() @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() override fun setUp() { // Skip test if the platform SDK is not newer than Android Baklava (SDK 36). // The Trash feature under test relies on DocumentsContract APIs introduced in the // Android release after Baklava (SDK 36). // As DocumentsUI is a Mainline module, it's subject to MTS testing, which runs on // older Android base builds to verify backward compatibility. However, this specific // Trash feature lacks backward compatibility with platforms at or below Baklava. // This assumption prevents failures when the test runs on an older base OS // without the necessary APIs. assumeTrue(VersionUtils.isGreaterThanB()) super.setUp() } /** * Tests the restoration of a single file. Verifies that the file is moved to its original path * and that the parent directories within the trash are removed. Loading
tests/functional/com/android/documentsui/services/TrashJobTest.kt +16 −7 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Notification.CATEGORY_ERROR import android.app.Notification.EXTRA_TEXT import android.app.Notification.EXTRA_TITLE import android.net.Uri import android.os.Build import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule Loading @@ -28,26 +27,39 @@ import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.provider.DocumentsContract.buildDocumentUri import android.provider.Flags.FLAG_ENABLE_DOCUMENTS_TRASH_API import androidx.test.filters.MediumTest import androidx.test.filters.SdkSuppress import com.android.documentsui.TrashDocumentHelper import com.android.documentsui.base.DocumentInfo import com.android.documentsui.flags.Flags import com.android.documentsui.rules.OverrideFlagsRule import com.android.documentsui.services.FileOperationService.OPERATION_TRASH import com.android.documentsui.util.VersionUtils import com.google.common.truth.Truth.assertThat import org.junit.Assume.assumeTrue import org.junit.Rule import org.junit.Test /** Tests TrashJob. */ @MediumTest @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) internal class TrashJobTest : AbstractJobTest<TrashJob>() { @get:Rule val setFlags = OverrideFlagsRule() @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() override fun setUp() { // Skip test if the platform SDK is not newer than Android Baklava (SDK 36). // The Trash feature under test relies on DocumentsContract APIs introduced in the // Android release after Baklava (SDK 36). // As DocumentsUI is a Mainline module, it's subject to MTS testing, which runs on // older Android base builds to verify backward compatibility. However, this specific // Trash feature lacks backward compatibility with platforms at or below Baklava. // This assumption prevents failures when the test runs on an older base OS // without the necessary APIs. assumeTrue(VersionUtils.isGreaterThanB()) super.setUp() } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashSingleFile() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -92,7 +104,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashMultipleFile() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -140,7 +151,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashFolder() { val testDir1 = mDocs.createFolder(mSrcRoot, "dir1") Loading Loading @@ -203,7 +213,6 @@ internal class TrashJobTest : AbstractJobTest<TrashJob>() { } @Test @RequiresFlagsEnabled(FLAG_ENABLE_DOCUMENTS_TRASH_API) @EnableFlags(Flags.FLAG_ENABLE_TRASH_FLOW_RO) fun testTrashFailedNoFileFound() { // create a document in mDestRoot, trashDocument only working for mSrcRoot, Loading