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

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

Merge "Add WaitState class for new MessageQueue" into main

parents 70940ba9 3f40ee59
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ per-file HandlerThread.java = file:/MESSAGE_QUEUE_OWNERS
per-file HandlerExecutor.java = file:/MESSAGE_QUEUE_OWNERS
per-file MessageHeap.java = file:/MESSAGE_QUEUE_OWNERS
per-file MessageStack.java = file:/MESSAGE_QUEUE_OWNERS
per-file WaitState.java = file:/MESSAGE_QUEUE_OWNERS

# Stats
per-file IStatsBootstrapAtomService.aidl = file:/services/core/java/com/android/server/stats/OWNERS
+68 −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 athasEqualMessages
 *
 *      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 android.os;

/**
 * Encapsulates the waiting logic of DeliQueue/MessageQueue
 * @hide
 */
public final class WaitState {
    private static final long IS_COUNTER = 1L  << 63;
    private static final long HAS_SYNC_BARRIER = 1L << 62;
    private static final long MASK = ~(IS_COUNTER | HAS_SYNC_BARRIER);

    public static boolean isCounter(long state) {
        return (state & IS_COUNTER) != 0;
    }

    public static long getCount(long state) {
        return state & ~IS_COUNTER;
    }

    public static long incrementCounter(long state) {
        long count = getCount(state) + 1;
        return count | IS_COUNTER;
    }

    public static long initCounter() {
        return IS_COUNTER;
    }

    public static boolean hasSyncBarrier(long state) {
        return (state & HAS_SYNC_BARRIER) != 0;
    }

    private static final long COUNTER_BITS = 20;
    public static long getTSMillis(long state) {
        return (state & MASK) >>> COUNTER_BITS;
    }

    public static long incrementDeadline(long state) {
        long bits = state & ~MASK;
        long ts = state & MASK;
        return (ts + 1) | bits;
    }

    public static long composeDeadline(long deadlineMS, boolean syncBarrier) {
        long state = deadlineMS << COUNTER_BITS;
        if (syncBarrier) {
            state |= HAS_SYNC_BARRIER;
        }

        return state;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ per-file RemoteCallbackListTest.java = shayba@google.com
per-file MessageQueueTest.java = file:/MESSAGE_QUEUE_OWNERS
per-file MessageHeapTest.java = file:/MESSAGE_QUEUE_OWNERS
per-file MessageStackTest.java = file:/MESSAGE_QUEUE_OWNERS
per-file WaitStateTest.java = file:/MESSAGE_QUEUE_OWNERS

# Perfetto SDK
per-file PerfettoTrace*Test.java = file:/PERFETTO_OWNERS
+80 −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 athasEqualMessages
 *
 *      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 android.os;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.os.WaitState;

import android.util.Log;

import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public final class WaitStateTest {
    private static final String TAG = "WaitStateTest";

    @Test
    public void testCountOperations() {
        long state = WaitState.initCounter();

        assertTrue(WaitState.isCounter(state));
        assertEquals(WaitState.getCount(state), 0);
        Log.d(TAG, "state = " + Long.toHexString(state));

        state = WaitState.incrementCounter(state);
        Log.d(TAG, "state = " + Long.toHexString(state));
        assertTrue(WaitState.isCounter(state));
        assertEquals(WaitState.getCount(state), 1);
        for (int i = 2; i < 10; i++) {
            state = WaitState.incrementCounter(state);
            assertEquals(WaitState.getCount(state), i);
            assertTrue(WaitState.isCounter(state));
        }
    }

    @Test
    public void testDeadlineOperations() {
        final long now = SystemClock.uptimeMillis();
        long state = WaitState.composeDeadline(now, false);
        assertFalse(WaitState.hasSyncBarrier(state));
        long tsMillis = WaitState.getTSMillis(state);
        assertEquals(tsMillis, now);

        state = WaitState.incrementDeadline(state);
        state = WaitState.incrementDeadline(state);
        tsMillis = WaitState.getTSMillis(state);
        assertEquals(tsMillis, now);


        /* Do the same but with sync barrier bit set */
        state = WaitState.composeDeadline(now, true);
        assertTrue(WaitState.hasSyncBarrier(state));
        tsMillis = WaitState.getTSMillis(state);
        assertEquals(tsMillis, now);

        state = WaitState.incrementDeadline(state);
        state = WaitState.incrementDeadline(state);
        tsMillis = WaitState.getTSMillis(state);
        assertEquals(tsMillis, now);
    }
}