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

Commit 1479637e authored by Vinit Nayak's avatar Vinit Nayak Committed by Android (Google) Code Review
Browse files

Merge "Add ability to register listeners with SplitState" into main

parents f6a4d285 a72264cc
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -23,10 +23,13 @@ import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_3_1
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_3_45_45_10;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SplitScreenState;

import android.annotation.NonNull;
import android.graphics.Rect;
import android.graphics.RectF;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * A class that manages the "state" of split screen. See {@link SplitScreenState} for definitions.
@@ -34,10 +37,13 @@ import java.util.List;
public class SplitState {
    private @SplitScreenState int mState = NOT_IN_SPLIT;
    private SplitSpec mSplitSpec;
    private final Set<SplitStateChangeListener> mListeners = new HashSet<>();


    /** Updates the current state of split screen on this device. */
    public void set(@SplitScreenState int newState) {
        mState = newState;
        notifyListeners();
    }

    /** Reports the current state of split screen on this device. */
@@ -74,4 +80,44 @@ public class SplitState {
                || mState == SNAP_TO_3_10_45_45
                || mState == SNAP_TO_3_45_45_10;
    }

    /**
     * Registers a listener to receive notifications when the split state changes.
     * Multiple instances of the same listener will not be tolerated. Don't be weird.
     *
     * @param listener The listener to register.
     */
    public void registerSplitStateChangeListener(@NonNull SplitStateChangeListener listener) {
        mListeners.add(listener);
    }

    /**
     * Unregisters a listener, so it no longer receives notifications.
     *
     * @param listener The listener to unregister.
     */
    public void unregisterSplitStateChangeListener(@NonNull SplitStateChangeListener listener) {
        mListeners.remove(listener);
    }

    /**
     * Notifies all registered listeners of the current split state.
     */
    private void notifyListeners() {
        for (SplitStateChangeListener listener : mListeners) {
            listener.onSplitStateChanged(mState);
        }
    }

    /**
     * An interface for listeners that want to be notified of split state changes.
     */
    public interface SplitStateChangeListener {
        /**
         * Called when the split state of the splitter changes.
         *
         * @param splitState The new split state.
         */
        void onSplitStateChanged(@SplitScreenState int splitState);
    }
}
+113 −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.wm.shell.splitscreen

import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.wm.shell.common.split.SplitState
import com.android.wm.shell.shared.split.SplitScreenConstants
import com.android.wm.shell.shared.split.SplitScreenConstants.NOT_IN_SPLIT
import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50
import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_3_10_45_45
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class SplitStateTests {

    val DEFAULT_VALUE = -4

    private lateinit var splitter: SplitState
    private lateinit var listener1: TestListener
    private lateinit var listener2: TestListener

    @Before
    fun setUp() {
        splitter = SplitState()
        listener1 = TestListener()
        listener2 = TestListener()
    }

    @Test
    fun testRegisterAndNotify() {
        splitter.registerSplitStateChangeListener(listener1)
        splitter.set(SNAP_TO_2_50_50)
        assertEquals(SNAP_TO_2_50_50, listener1.lastState)

        splitter.set(SNAP_TO_3_10_45_45)
        assertEquals(SNAP_TO_3_10_45_45, listener1.lastState)
    }

    @Test
    fun testMultipleListeners() {
        splitter.registerSplitStateChangeListener(listener1)
        splitter.registerSplitStateChangeListener(listener2)

        splitter.set(SNAP_TO_3_10_45_45)
        assertEquals(SNAP_TO_3_10_45_45, listener1.lastState)
        assertEquals(SNAP_TO_3_10_45_45, listener2.lastState)
    }

    @Test
    fun testUnregisterListener() {
        splitter.registerSplitStateChangeListener(listener1)
        splitter.registerSplitStateChangeListener(listener2)
        splitter.unregisterSplitStateChangeListener(listener1)

        splitter.set(SNAP_TO_2_50_50)
        assertEquals(DEFAULT_VALUE, listener1.lastState) // Listener 1 should not be notified
        assertEquals(SNAP_TO_2_50_50, listener2.lastState)
    }

    @Test
    fun testNoListeners() {
        splitter.set(SNAP_TO_2_50_50)
        // No listeners registered, so no exceptions should be thrown.
    }

    @Test
    fun testRegisterSameListenerMultipleTimes() {
        splitter.registerSplitStateChangeListener(listener1)
        splitter.registerSplitStateChangeListener(listener1)

        splitter.set(SNAP_TO_2_50_50)
        assertEquals(SNAP_TO_2_50_50, listener1.lastState)
        assertEquals(1, listener1.callCount) // should only be called once.
    }

    @Test
    fun testExit() {
        splitter.registerSplitStateChangeListener(listener1)
        splitter.exit()

        assertEquals(NOT_IN_SPLIT, listener1.lastState)
    }

    // Helper class for testing
    inner class TestListener : SplitState.SplitStateChangeListener {
        var lastState = DEFAULT_VALUE
        var callCount = 0

        override fun onSplitStateChanged(@SplitScreenConstants.SplitScreenState splitState: Int) {
            this.lastState = splitState
            callCount++
        }
    }
}
 No newline at end of file