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

Commit 9054c59b authored by Anna Bauza's avatar Anna Bauza Committed by Android (Google) Code Review
Browse files

Merge "Add broadcast to open UserSwitcher Dialog from outside of SystemUI" into main

parents fa68f4ce df131d85
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1120,6 +1120,15 @@
            </intent-filter>
        </receiver>

        <receiver android:name=".user.UserDialogReceiver"
            android:exported="true"
            android:featureFlag="com.android.systemui.multiuser_open_user_switcher_dialog"
            android:permission="android.permission.CREATE_USERS">
            <intent-filter>
                <action android:name="com.android.systemui.action.LAUNCH_USER_SWITCHER_DIALOG" />
            </intent-filter>
        </receiver>

        <receiver android:name=".accessibility.hearingaid.HearingDevicesDialogReceiver"
            android:exported="false">
            <intent-filter android:priority="1">
+93 −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.user

import android.content.Intent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations

/** Tests for [UserDialogReceiver]. */
@SmallTest
@RunWith(AndroidJUnit4::class)
class UserDialogReceiverTest : SysuiTestCase() {

    // Mock the interactor dependency to verify interactions.
    @Mock private lateinit var mockUserSwitcherInteractor: UserSwitcherInteractor

    // The instance of the BroadcastReceiver we are testing.
    private lateinit var userDialogReceiver: UserDialogReceiver

    @Before
    fun setUp() {
        // Initialize mocks created with the @Mock annotation.
        MockitoAnnotations.initMocks(this)
        // Create an instance of the receiver with the mocked dependency.
        userDialogReceiver = UserDialogReceiver(mockUserSwitcherInteractor)
    }

    /**
     * Verifies that when the correct action is received, the user switcher dialog is shown. This
     * assumes the system has already granted permission and allowed the broadcast.
     */
    @Test
    fun onReceive_withLaunchUserSwitcherAction_showsUserSwitcher() {
        // Arrange: Create an intent with the specific action the receiver listens for.
        val intent = Intent(UserDialogReceiver.LAUNCH_USER_SWITCHER_DIALOG)

        // Act: Trigger the onReceive method.
        userDialogReceiver.onReceive(context, intent)

        // Assert: Verify that the interactor's showUserSwitcher method was called correctly.
        verify(mockUserSwitcherInteractor).showUserSwitcher(null, context)
    }

    /** Verifies that if an unknown action is received, the interactor is not called. */
    @Test
    fun onReceive_withUnknownAction_doesNotShowUserSwitcher() {
        // Arrange: Create an intent with an action that the receiver should ignore.
        val intent = Intent("com.android.systemui.action.SOME_OTHER_ACTION")

        // Act: Trigger the onReceive method.
        userDialogReceiver.onReceive(context, intent)

        // Assert: Verify that the showUserSwitcher method was never called.
        verify(mockUserSwitcherInteractor, never()).showUserSwitcher(any(), any())
    }

    /** Verifies that if the intent action is null, the interactor is not called. */
    @Test
    fun onReceive_withNullAction_doesNotShowUserSwitcher() {
        // Arrange: Create an intent with no action set.
        val intent = Intent()

        // Act: Trigger the onReceive method.
        userDialogReceiver.onReceive(context, intent)

        // Assert: Verify that the showUserSwitcher method was never called.
        verify(mockUserSwitcherInteractor, never()).showUserSwitcher(any(), any())
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.media.dialog.MediaOutputDialogReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.screenshot.SmartActionsReceiver;
import com.android.systemui.user.UserDialogReceiver;

import dagger.Binds;
import dagger.Module;
@@ -81,6 +82,16 @@ public abstract class DefaultBroadcastReceiverBinder {
    public abstract BroadcastReceiver bindGuestResetOrExitSessionReceiver(
            GuestResetOrExitSessionReceiver broadcastReceiver);


    /**
     *
     */
    @Binds
    @IntoMap
    @ClassKey(UserDialogReceiver.class)
    public abstract BroadcastReceiver bindUserDialogReceiver(
            UserDialogReceiver broadcastReceiver);

    /**
     *
     */
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.user

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
import javax.inject.Inject

class UserDialogReceiver
@Inject
constructor(private val userSwitcherInteractor: UserSwitcherInteractor) : BroadcastReceiver() {
    companion object {
        private const val TAG = "UserDialogReceiver"
        const val LAUNCH_USER_SWITCHER_DIALOG =
            "com.android.systemui.action.LAUNCH_USER_SWITCHER_DIALOG"
    }

    override fun onReceive(context: Context, intent: Intent) {
        try {
            when (intent.getAction()) {
                LAUNCH_USER_SWITCHER_DIALOG -> {
                    userSwitcherInteractor.showUserSwitcher(null, context)
                }
                else -> Log.e(TAG, "Unknown action " + intent.getAction())
            }
        } catch (e: Exception) {
            Log.e(TAG, "Exception: ", e)
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -548,7 +548,7 @@ constructor(
     * If [context] is provided, the dialog will be created from that context. If not provided, the
     * shade context will be used.
     */
    fun showUserSwitcher(expandable: Expandable, context: Context? = null) {
    fun showUserSwitcher(expandable: Expandable?, context: Context? = null) {
        if (featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
            showDialog(ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog(expandable, context))
        } else {