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

Commit 7b3ee3b1 authored by Étienne Ruffieux (xWF)'s avatar Étienne Ruffieux (xWF) Committed by Gerrit Code Review
Browse files

Merge "Prevent updating now playing queue unnecessarily" into main

parents 0dbefb47 9a29ee90
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ public class Metadata implements Cloneable {
                + artist
                + "\" album=\""
                + album
                + "\" genre=\""
                + genre
                + "\" duration="
                + duration
                + " trackPosition="
+34 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ public class AvrcpTargetService extends ProfileService {

            boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata);
            boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state);
            boolean queue = !Objects.equals(mCurrentData.queue, data.queue);
            boolean queue = isQueueUpdated(mCurrentData.queue, data.queue);

            Log.d(
                    TAG,
@@ -562,6 +562,39 @@ public class AvrcpTargetService extends ProfileService {
        mNativeInterface.sendPlayerSettings(repeatMode, shuffleMode);
    }

    /**
     * Compares the {@link Metadata} of the current and new queues
     *
     * <p>Whenever the current playing track changed in the now playing list, its metadata is
     * updated. We should only send an update if the elements of the queue have been modified.
     *
     * <p>Only Title, Album and Artist metadata can be used for comparison. The metadata ID
     * corresponds to the position in the list and is not unique for each media. Genre, duration and
     * cover art are updated when the playing track changes as we are only able to retrieve this
     * information then.
     */
    @VisibleForTesting
    public static boolean isQueueUpdated(List<Metadata> currentQueue, List<Metadata> newQueue) {
        if (newQueue == null && currentQueue == null) {
            return false;
        }
        if (newQueue == null || currentQueue == null || currentQueue.size() != newQueue.size()) {
            return true;
        }

        for (int index = 0; index < currentQueue.size(); index++) {
            Metadata currentMetadata = currentQueue.get(index);
            Metadata newMetadata = newQueue.get(index);

            if (!Objects.equals(currentMetadata.title, newMetadata.title)
                    || !Objects.equals(currentMetadata.artist, newMetadata.artist)
                    || !Objects.equals(currentMetadata.album, newMetadata.album)) {
                return true;
            }
        }
        return false;
    }

    /** Dump debugging information to the string builder */
    public void dump(StringBuilder sb) {
        sb.append("\nProfile: AvrcpTargetService:\n");
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.bluetooth.avrcp;

import static com.google.common.truth.Truth.assertThat;

import android.net.Uri;

import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.audio_util.Image;
import com.android.bluetooth.audio_util.Metadata;

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

import java.util.ArrayList;
import java.util.List;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class AvrcpTargetServiceTest {

    private static final String TEST_DATA = "-1";

    @Test
    public void testQueueUpdateData() {
        List<Metadata> firstQueue = new ArrayList<Metadata>();
        List<Metadata> secondQueue = new ArrayList<Metadata>();

        firstQueue.add(createEmptyMetadata());
        secondQueue.add(createEmptyMetadata());
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isFalse();

        secondQueue.add(createEmptyMetadata());
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isTrue();

        firstQueue.add(createEmptyMetadata());
        firstQueue.get(1).genre = TEST_DATA;
        firstQueue.get(1).mediaId = TEST_DATA;
        firstQueue.get(1).trackNum = TEST_DATA;
        firstQueue.get(1).numTracks = TEST_DATA;
        firstQueue.get(1).duration = TEST_DATA;
        firstQueue.get(1).image =
                new Image(
                        InstrumentationRegistry.getInstrumentation().getTargetContext(), Uri.EMPTY);
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isFalse();

        secondQueue.get(1).title = TEST_DATA;
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isTrue();

        secondQueue.set(1, createEmptyMetadata());
        secondQueue.get(1).artist = TEST_DATA;
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isTrue();

        secondQueue.set(1, createEmptyMetadata());
        secondQueue.get(1).album = TEST_DATA;
        assertThat(AvrcpTargetService.isQueueUpdated(firstQueue, secondQueue)).isTrue();
    }

    private Metadata createEmptyMetadata() {
        Metadata.Builder builder = new Metadata.Builder();
        return builder.useDefaults().build();
    }
}