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

Commit 4c352cb7 authored by Jernej Virag's avatar Jernej Virag
Browse files

Register QS content observers on bg thread

Content observers do Binder calls to register/unregister, use the new async APIs to handle the registration.

Bug: 351766769
Test: created SettingObserverTest
Flag: com.android.systemui.qs_register_setting_observer_on_bg_thread
Change-Id: I3c25365ce7460f1d763223c8a7cc281a2f1be7a7
parent 218de6a5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1143,3 +1143,13 @@ flag {
       purpose: PURPOSE_BUGFIX
   }
}

flag {
  namespace: "systemui"
  name: "qs_register_setting_observer_on_bg_thread"
  description: "Registers Quick Settings content providers on background thread"
  bug: "351766769"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
+117 −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.qs

import android.net.Uri
import android.os.Handler
import android.os.Looper
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.util.settings.SettingsProxy
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.capture
import org.mockito.kotlin.eq
import org.mockito.kotlin.reset
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
class SettingObserverTest : SysuiTestCase() {

    private val DEFAULT_VALUE = 7

    @Mock lateinit var settingsProxy: SettingsProxy
    @Captor private lateinit var argumentCaptor: ArgumentCaptor<Runnable>

    private lateinit var testSettingObserver: SettingObserver

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        whenever(settingsProxy.getInt(any(), any())).thenReturn(5)
        whenever(settingsProxy.getUriFor(any())).thenReturn(Uri.parse("content://test_uri"))
        testSettingObserver =
            object :
                SettingObserver(
                    settingsProxy,
                    Handler(Looper.getMainLooper()),
                    "test_setting",
                    DEFAULT_VALUE
                ) {
                override fun handleValueChanged(value: Int, observedChange: Boolean) {}
            }
    }

    @Test
    @EnableFlags(Flags.FLAG_QS_REGISTER_SETTING_OBSERVER_ON_BG_THREAD)
    fun setListening_true_settingsProxyRegistered() {
        testSettingObserver.isListening = true
        verify(settingsProxy)
            .registerContentObserverAsync(
                any<Uri>(),
                eq(false),
                eq(testSettingObserver),
                capture(argumentCaptor)
            )
        assertThat(testSettingObserver.value).isEqualTo(5)

        // Verify if the callback applies updated value after the fact
        whenever(settingsProxy.getInt(any(), any())).thenReturn(12341234)
        argumentCaptor.value.run()
        assertThat(testSettingObserver.value).isEqualTo(12341234)
    }

    @Test
    @EnableFlags(Flags.FLAG_QS_REGISTER_SETTING_OBSERVER_ON_BG_THREAD)
    fun setListening_false_settingsProxyRegistered() {
        testSettingObserver.isListening = true
        reset(settingsProxy)
        testSettingObserver.isListening = false

        verify(settingsProxy).unregisterContentObserverAsync(eq(testSettingObserver))
    }

    @Test
    @DisableFlags(Flags.FLAG_QS_REGISTER_SETTING_OBSERVER_ON_BG_THREAD)
    fun setListening_bgFlagDisabled_true_settingsProxyRegistered() {
        testSettingObserver.isListening = true
        verify(settingsProxy)
            .registerContentObserverSync(any<Uri>(), eq(false), eq(testSettingObserver))
    }

    @Test
    @DisableFlags(Flags.FLAG_QS_REGISTER_SETTING_OBSERVER_ON_BG_THREAD)
    fun setListening_bgFlagDisabled_false_settingsProxyRegistered() {
        testSettingObserver.isListening = true
        reset(settingsProxy)
        testSettingObserver.isListening = false

        verify(settingsProxy).unregisterContentObserverSync(eq(testSettingObserver))
    }
}
+14 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.qs;
import android.database.ContentObserver;
import android.os.Handler;

import com.android.systemui.Flags;
import com.android.systemui.statusbar.policy.Listenable;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.settings.SettingsProxy;
@@ -74,10 +75,20 @@ public abstract class SettingObserver extends ContentObserver implements Listena
        mListening = listening;
        if (listening) {
            mObservedValue = getValueFromProvider();
            if (Flags.qsRegisterSettingObserverOnBgThread()) {
                mSettingsProxy.registerContentObserverAsync(
                        mSettingsProxy.getUriFor(mSettingName), false, this,
                        () -> mObservedValue = getValueFromProvider());
            } else {
                mSettingsProxy.registerContentObserverSync(
                        mSettingsProxy.getUriFor(mSettingName), false, this);
            }
        } else {
            if (Flags.qsRegisterSettingObserverOnBgThread()) {
                mSettingsProxy.unregisterContentObserverAsync(this);
            } else {
                mSettingsProxy.unregisterContentObserverSync(this);
            }
            mObservedValue = mDefaultValue;
        }
    }