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

Commit b374bcc4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "Move SettingsProxyExt content observer registration call on bg thread."" into main

parents 51883417 9e7d018a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1261,3 +1261,13 @@ flag {
   description: "Adding haptic component infrastructure to sliders in Compose."
   bug: "341968766"
}

flag {
  namespace: "systemui"
  name: "settings_ext_register_content_observer_on_bg_thread"
  description: "Register content observer in callback flow APIs on background thread in SettingsProxyExt."
  bug: "355389014"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
 No newline at end of file
+165 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.util.settings

import android.database.ContentObserver
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.times
import org.mockito.kotlin.verify

/** Tests for [SettingsProxyExt]. */
@RunWith(AndroidJUnit4::class)
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
class SettingsProxyExtTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    @Mock lateinit var settingsProxy: SettingsProxy
    @Mock lateinit var userSettingsProxy: UserSettingsProxy

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    @Test
    @EnableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagEnabled_settingsProxy_registerContentObserverInvoked() =
        testScope.runTest {
            val unused by collectLastValue(settingsProxy.observerFlow(SETTING_1, SETTING_2))
            runCurrent()
            verify(settingsProxy, times(2))
                .registerContentObserver(any<String>(), any<ContentObserver>())
        }

    @Test
    @DisableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagDisabled_multipleSettings_SettingsProxy_registerContentObserverInvoked() =
        testScope.runTest {
            val unused by collectLastValue(settingsProxy.observerFlow(SETTING_1, SETTING_2))
            runCurrent()
            verify(settingsProxy, times(2))
                .registerContentObserverSync(any<String>(), any<ContentObserver>())
        }

    @Test
    @EnableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagEnabled_channelClosed_settingsProxy_unregisterContentObserverInvoked() =
        testScope.runTest {
            val job = Job()
            val unused by
                collectLastValue(settingsProxy.observerFlow(SETTING_1, SETTING_2), context = job)
            runCurrent()
            job.cancel()
            runCurrent()
            verify(settingsProxy).unregisterContentObserverAsync(any<ContentObserver>())
        }

    @Test
    @DisableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagDisabled_channelClosed_settingsProxy_unregisterContentObserverInvoked() =
        testScope.runTest {
            val job = Job()
            val unused by
                collectLastValue(settingsProxy.observerFlow(SETTING_1, SETTING_2), context = job)
            runCurrent()
            job.cancel()
            runCurrent()
            verify(settingsProxy).unregisterContentObserverSync(any<ContentObserver>())
        }

    @Test
    @EnableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagEnabled_userSettingsProxy_registerContentObserverForUserInvoked() =
        testScope.runTest {
            val unused by
                collectLastValue(userSettingsProxy.observerFlow(userId = 0, SETTING_1, SETTING_2))
            runCurrent()
            verify(userSettingsProxy, times(2))
                .registerContentObserverForUser(any<String>(), any<ContentObserver>(), any<Int>())
        }

    @Test
    @DisableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagDisabled_userSettingsProxy_registerContentObserverForUserInvoked() =
        testScope.runTest {
            val unused by
                collectLastValue(userSettingsProxy.observerFlow(userId = 0, SETTING_1, SETTING_2))
            runCurrent()
            verify(userSettingsProxy, times(2))
                .registerContentObserverForUserSync(
                    any<String>(),
                    any<ContentObserver>(),
                    any<Int>()
                )
        }

    @Test
    @EnableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagEnabled_channelClosed_userSettingsProxy_unregisterContentObserverInvoked() =
        testScope.runTest {
            val job = Job()
            val unused by
                collectLastValue(
                    userSettingsProxy.observerFlow(userId = 0, SETTING_1, SETTING_2),
                    context = job
                )
            runCurrent()
            job.cancel()
            runCurrent()
            verify(userSettingsProxy).unregisterContentObserverAsync(any<ContentObserver>())
        }

    @Test
    @DisableFlags(Flags.FLAG_SETTINGS_EXT_REGISTER_CONTENT_OBSERVER_ON_BG_THREAD)
    fun observeFlow_bgFlagDisabled_channelClosed_userSettingsProxy_unregisterContentObserverInvoked() =
        testScope.runTest {
            val job = Job()
            val unused by
                collectLastValue(
                    userSettingsProxy.observerFlow(userId = 0, SETTING_1, SETTING_2),
                    context = job
                )
            runCurrent()
            job.cancel()
            runCurrent()
            verify(userSettingsProxy).unregisterContentObserverSync(any<ContentObserver>())
        }

    private companion object {
        val SETTING_1 = "settings_1"
        val SETTING_2 = "settings_2"
    }
}
+29 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.util.settings

import android.annotation.UserIdInt
import android.database.ContentObserver
import com.android.systemui.Flags
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -39,9 +40,21 @@ object SettingsProxyExt {
                    }
                }

            names.forEach { name -> registerContentObserverForUserSync(name, observer, userId) }
            names.forEach { name ->
                if (Flags.settingsExtRegisterContentObserverOnBgThread()) {
                    registerContentObserverForUser(name, observer, userId)
                } else {
                    registerContentObserverForUserSync(name, observer, userId)
                }
            }

            awaitClose { unregisterContentObserverSync(observer) }
            awaitClose {
                if (Flags.settingsExtRegisterContentObserverOnBgThread()) {
                    unregisterContentObserverAsync(observer)
                } else {
                    unregisterContentObserverSync(observer)
                }
            }
        }
    }

@@ -57,9 +70,21 @@ object SettingsProxyExt {
                    }
                }

            names.forEach { name -> registerContentObserverSync(name, observer) }
            names.forEach { name ->
                if (Flags.settingsExtRegisterContentObserverOnBgThread()) {
                    registerContentObserver(name, observer)
                } else {
                    registerContentObserverSync(name, observer)
                }
            }

            awaitClose { unregisterContentObserverSync(observer) }
            awaitClose {
                if (Flags.settingsExtRegisterContentObserverOnBgThread()) {
                    unregisterContentObserverAsync(observer)
                } else {
                    unregisterContentObserverSync(observer)
                }
            }
        }
    }
}