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

Commit d9cda67f authored by Sal Savage's avatar Sal Savage
Browse files

Add image member to Metadata object

This moves the Metadata object more in line with the available
attributes defined in the AVRCP specification. Image can be
passed to the AVRCP code where they can be updated with an image handle
based on where BIP has stored the iamage. The native stack can use that
handle if one is assigned.

This change does not actually assign any image handle yet. The native
stack also needs to be notified that Java has a BIP client for a given
device before it will actually hand off the handle. This will happen in
future patches.

Tag: #feature
Bug: 153076316
Test: atest BluetoothInstrumentationTests
Test: build, flash, make sure the existing UX is not impacted.

Change-Id: Ic10816f1fd09153418bb57d93a6a2978e4a0f7c3
parent ba4a1c5f
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -337,6 +337,26 @@ static void sendMediaKeyEvent(int key, KeyState state) {
      state == KeyState::PUSHED ? JNI_TRUE : JNI_FALSE);
}

static std::string getImageHandleFromJavaObj(JNIEnv* env, jobject image) {
  std::string handle;

  if (image == nullptr) return handle;

  jclass class_image = env->GetObjectClass(image);
  jmethodID method_getImageHandle =
      env->GetMethodID(class_image, "getImageHandle", "()Ljava/lang/String;");
  jstring imageHandle = (jstring) env->CallObjectMethod(
      image, method_getImageHandle);
  if (imageHandle == nullptr) {
    return handle;
  }

  const char* value = env->GetStringUTFChars(imageHandle, nullptr);
  handle = std::string(value);
  env->ReleaseStringUTFChars(imageHandle, value);
  return handle;
}

static SongInfo getSongInfoFromJavaObj(JNIEnv* env, jobject metadata) {
  SongInfo info;

@@ -359,6 +379,8 @@ static SongInfo getSongInfoFromJavaObj(JNIEnv* env, jobject metadata) {
      env->GetFieldID(class_metadata, "genre", "Ljava/lang/String;");
  jfieldID field_playingTime =
      env->GetFieldID(class_metadata, "duration", "Ljava/lang/String;");
  jfieldID field_image =
      env->GetFieldID(class_metadata, "image", "Lcom/android/bluetooth/audio_util/Image;");

  jstring jstr = (jstring)env->GetObjectField(metadata, field_mediaId);
  if (jstr != nullptr) {
@@ -431,6 +453,13 @@ static SongInfo getSongInfoFromJavaObj(JNIEnv* env, jobject metadata) {
    env->DeleteLocalRef(jstr);
  }

  jobject object_image = env->GetObjectField(metadata, field_image);
  std::string imageHandle = getImageHandleFromJavaObj(env, object_image);
  if (!imageHandle.empty()) {
    info.attributes.insert(
        AttributeEntry(Attribute::DEFAULT_COVER_ART, imageHandle));
  }

  return info;
}

+1 −1
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ class BrowsedPlayerWrapper {
                    Folder f = new Folder(item.getMediaId(), false, title);
                    return_list.add(new ListItem(f));
                } else {
                    return_list.add(new ListItem(Util.toMetadata(item)));
                    return_list.add(new ListItem(Util.toMetadata(mContext, item)));
                }
            }

+5 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.bluetooth.audio_util;

import android.content.Context;
import android.media.session.MediaSession;
import android.os.Looper;
import android.util.Log;
@@ -29,8 +30,8 @@ class GPMWrapper extends MediaPlayerWrapper {
    private static final String TAG = "AvrcpGPMWrapper";
    private static final boolean DEBUG = true;

    GPMWrapper(MediaController controller, Looper looper) {
        super(controller, looper);
    GPMWrapper(Context context, MediaController controller, Looper looper) {
        super(context, controller, looper);
    }

    @Override
@@ -50,8 +51,8 @@ class GPMWrapper extends MediaPlayerWrapper {
        }

        // Check if current playing song in Queue matches current Metadata
        Metadata qitem = Util.toMetadata(currItem);
        Metadata mdata = Util.toMetadata(getMetadata());
        Metadata qitem = Util.toMetadata(mContext, currItem);
        Metadata mdata = Util.toMetadata(mContext, getMetadata());
        if (currItem == null || !qitem.equals(mdata)) {
            if (DEBUG) {
                Log.d(TAG, "Metadata currently out of sync for Google Play Music");
+1 −0
Original line number Diff line number Diff line
@@ -503,6 +503,7 @@ public class MediaPlayerList {
        }

        MediaPlayerWrapper newPlayer = MediaPlayerWrapperFactory.wrap(
                mContext,
                controller,
                mLooper);

+19 −16
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.bluetooth.audio_util;

import android.annotation.Nullable;
import android.content.Context;
import android.media.MediaMetadata;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
@@ -46,6 +47,7 @@ public class MediaPlayerWrapper {
    private static final String PLAYBACK_STATE_CHANGE_LOGGER_EVENT_TITLE =
            "Playback State change Event";

    final Context mContext;
    private MediaController mMediaController;
    private String mPackageName;
    private Looper mLooper;
@@ -81,7 +83,8 @@ public class MediaPlayerWrapper {
        return true;
    }

    MediaPlayerWrapper(MediaController controller, Looper looper) {
    MediaPlayerWrapper(Context context, MediaController controller, Looper looper) {
        mContext = context;
        mMediaController = controller;
        mPackageName = controller.getPackageName();
        mLooper = looper;
@@ -89,8 +92,8 @@ public class MediaPlayerWrapper {
                PLAYBACK_STATE_CHANGE_EVENT_LOGGER_SIZE, PLAYBACK_STATE_CHANGE_LOGGER_EVENT_TITLE);

        mCurrentData = new MediaData(null, null, null);
        mCurrentData.queue = Util.toMetadataList(getQueue());
        mCurrentData.metadata = Util.toMetadata(getMetadata());
        mCurrentData.queue = Util.toMetadataList(mContext, getQueue());
        mCurrentData.metadata = Util.toMetadata(mContext, getMetadata());
        mCurrentData.state = getPlaybackState();
    }

@@ -114,7 +117,7 @@ public class MediaPlayerWrapper {
    }

    Metadata getCurrentMetadata() {
        return Util.toMetadata(getMetadata());
        return Util.toMetadata(mContext, getMetadata());
    }

    public PlaybackState getPlaybackState() {
@@ -226,8 +229,8 @@ public class MediaPlayerWrapper {
            }

            // Check if current playing song in Queue matches current Metadata
            Metadata qitem = Util.toMetadata(currItem);
            Metadata mdata = Util.toMetadata(getMetadata());
            Metadata qitem = Util.toMetadata(mContext, currItem);
            Metadata mdata = Util.toMetadata(mContext, getMetadata());
            if (currItem == null || !qitem.equals(mdata)) {
                if (DEBUG) {
                    Log.d(TAG, "Metadata currently out of sync for " + mPackageName);
@@ -258,9 +261,9 @@ public class MediaPlayerWrapper {
        // Update the current data since it could have changed while we weren't registered for
        // updates
        mCurrentData = new MediaData(
                Util.toMetadata(getMetadata()),
                Util.toMetadata(mContext, getMetadata()),
                getPlaybackState(),
                Util.toMetadataList(getQueue()));
                Util.toMetadataList(mContext, getQueue()));

        mControllerCallbacks = new MediaControllerListener(mMediaController, mLooper);
    }
@@ -295,9 +298,9 @@ public class MediaPlayerWrapper {

        // Update the current data since it could be different on the new controller for the player
        mCurrentData = new MediaData(
                Util.toMetadata(getMetadata()),
                Util.toMetadata(mContext, getMetadata()),
                getPlaybackState(),
                Util.toMetadataList(getQueue()));
                Util.toMetadataList(mContext, getQueue()));

        mControllerCallbacks = new MediaControllerListener(mMediaController, mLooper);
        d("Controller for " + mPackageName + " was updated.");
@@ -305,9 +308,9 @@ public class MediaPlayerWrapper {

    private void sendMediaUpdate() {
        MediaData newData = new MediaData(
                Util.toMetadata(getMetadata()),
                Util.toMetadata(mContext, getMetadata()),
                getPlaybackState(),
                Util.toMetadataList(getQueue()));
                Util.toMetadataList(mContext, getQueue()));

        if (newData.equals(mCurrentData)) {
            // This may happen if the controller is fully synced by the time the
@@ -346,9 +349,9 @@ public class MediaPlayerWrapper {
            }

            Log.e(TAG, "Timeout while waiting for metadata to sync for " + mPackageName);
            Log.e(TAG, "  └ Current Metadata: " +  Util.toMetadata(getMetadata()));
            Log.e(TAG, "  └ Current Metadata: " +  Util.toMetadata(mContext, getMetadata()));
            Log.e(TAG, "  └ Current Playstate: " + getPlaybackState());
            List<Metadata> current_queue = Util.toMetadataList(getQueue());
            List<Metadata> current_queue = Util.toMetadataList(mContext, getQueue());
            for (int i = 0; i < current_queue.size(); i++) {
                Log.e(TAG, "  └ QueueItem(" + i + "): " + current_queue.get(i));
            }
@@ -412,7 +415,7 @@ public class MediaPlayerWrapper {

            if (DEBUG) {
                Log.v(TAG, "onMetadataChanged(): " + mPackageName + " : "
                    + Util.toMetadata(metadata));
                        + Util.toMetadata(mContext, metadata));
            }

            if (!Objects.equals(metadata, getMetadata())) {
@@ -480,7 +483,7 @@ public class MediaPlayerWrapper {
                e("The callback queue isn't the current queue");
            }

            List<Metadata> current_queue = Util.toMetadataList(queue);
            List<Metadata> current_queue = Util.toMetadataList(mContext, queue);
            if (current_queue.equals(mCurrentData.queue)) {
                Log.w(TAG, "onQueueChanged(): " + mPackageName
                        + " tried to update with no new data");
Loading