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

Commit 696989fd authored by Robert Shih's avatar Robert Shih
Browse files

MediaDrm: API to retrieve LogMessages

Bug: 162255728
Test: cts/gts MediaDrmTest
Change-Id: Icba4945a75eb00b737d65572b40cf2035504ca08
parent d8385e06
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -21591,6 +21591,7 @@ package android.media {
    method @android.media.MediaDrm.HdcpLevel public int getConnectedHdcpLevel();
    method public android.media.MediaDrm.CryptoSession getCryptoSession(@NonNull byte[], @NonNull String, @NonNull String);
    method @NonNull public android.media.MediaDrm.KeyRequest getKeyRequest(@NonNull byte[], @Nullable byte[], @Nullable String, int, @Nullable java.util.HashMap<java.lang.String,java.lang.String>) throws android.media.NotProvisionedException;
    method @NonNull public java.util.List<android.media.MediaDrm.LogMessage> getLogMessages();
    method @android.media.MediaDrm.HdcpLevel public int getMaxHdcpLevel();
    method public static int getMaxSecurityLevel();
    method public int getMaxSessionCount();
@@ -21699,6 +21700,12 @@ package android.media {
    field public static final int STATUS_USABLE_IN_FUTURE = 5; // 0x5
  }
  public static class MediaDrm.LogMessage {
    field @NonNull public final String message;
    field public final int priority;
    field public final long timestampMillis;
  }
  public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
    method @NonNull public String getDiagnosticInfo();
  }
+77 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -2493,4 +2494,80 @@ public final class MediaDrm implements AutoCloseable {
            return mPlaybackId;
        }
    }

    /**
     * Returns recent {@link LogMessage LogMessages} associated with this {@link MediaDrm}
     * instance.
     */
    @NonNull
    public native List<LogMessage> getLogMessages();

    /**
     * A {@link LogMessage} records an event in the {@link MediaDrm} framework
     * or vendor plugin.
     */
    public static class LogMessage {

        /**
         * Timing of the recorded event measured in milliseconds since the Epoch,
         * 1970-01-01 00:00:00 +0000 (UTC).
         */
        public final long timestampMillis;

        /**
         * Priority of the recorded event.
         * <p>
         * Possible priority constants are defined in {@link Log}, e.g.:
         * <ul>
         *     <li>{@link Log#ASSERT}</li>
         *     <li>{@link Log#ERROR}</li>
         *     <li>{@link Log#WARN}</li>
         *     <li>{@link Log#INFO}</li>
         *     <li>{@link Log#DEBUG}</li>
         *     <li>{@link Log#VERBOSE}</li>
         * </ul>
         */
        @Log.Level
        public final int priority;

        /**
         * Description of the recorded event.
         */
        @NonNull
        public final String message;

        private LogMessage(long timestampMillis, int priority, String message) {
            this.timestampMillis = timestampMillis;
            if (priority < Log.VERBOSE || priority > Log.ASSERT) {
                throw new IllegalArgumentException("invalid log priority " + priority);
            }
            this.priority = priority;
            this.message = message;
        }

        private char logPriorityChar() {
            switch (priority) {
                case Log.VERBOSE:
                    return 'V';
                case Log.DEBUG:
                    return 'D';
                case Log.INFO:
                    return 'I';
                case Log.WARN:
                    return 'W';
                case Log.ERROR:
                    return 'E';
                case Log.ASSERT:
                    return 'F';
                default:
            }
            return 'U';
        }

        @Override
        public String toString() {
            return String.format("LogMessage{%s %c %s}",
                    Instant.ofEpochMilli(timestampMillis), logPriorityChar(), message);
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ cc_library_shared {
        "android.hardware.cas@1.0",
        "android.hardware.cas.native@1.0",
        "android.hardware.drm@1.3",
        "android.hardware.drm@1.4",
        "android.hidl.memory@1.0",
        "android.hidl.token@1.0-utils",
    ],
+43 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrmMetricsConsumer.h>
#include <mediadrm/IDrm.h>
#include <utils/Vector.h>

using ::android::os::PersistableBundle;
namespace drm = ::android::hardware::drm;
@@ -187,6 +188,11 @@ struct KeyStatusFields {
    jclass classId;
};

struct LogMessageFields {
    jmethodID init;
    jclass classId;
};

struct fields_t {
    jfieldID context;
    jmethodID post_event;
@@ -208,6 +214,7 @@ struct fields_t {
    jmethodID createFromParcelId;
    jclass parcelCreatorClassId;
    KeyStatusFields keyStatus;
    LogMessageFields logMessage;
};

static fields_t gFields;
@@ -224,6 +231,19 @@ jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
    return result;
}

jobject hidlLogMessagesToJavaList(JNIEnv *env, const Vector<drm::V1_4::LogMessage> &logs) {
    jclass clazz = gFields.arraylistClassId;
    jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
    clazz = gFields.logMessage.classId;
    for (auto log: logs) {
        jobject jLog = env->NewObject(clazz, gFields.logMessage.init,
                static_cast<jlong>(log.timeMs),
                static_cast<jint>(log.priority),
                env->NewStringUTF(log.message.c_str()));
        env->CallBooleanMethod(arrayList, gFields.arraylist.add, jLog);
    }
    return arrayList;
}
}  // namespace anonymous

// ----------------------------------------------------------------------------
@@ -907,6 +927,10 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
    FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
    gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
    GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");

    FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
    gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
    GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
}

static void android_media_MediaDrm_native_setup(
@@ -1996,6 +2020,22 @@ static void android_media_MediaDrm_setPlaybackId(
    throwExceptionAsNecessary(env, err, "Failed to set playbackId");
}

static jobject android_media_MediaDrm_getLogMessages(
        JNIEnv *env, jobject thiz) {
    sp<IDrm> drm = GetDrm(env, thiz);
    if (!CheckDrm(env, drm)) {
        return NULL;
    }

    Vector<drm::V1_4::LogMessage> logs;
    status_t err = drm->getLogMessages(logs);
    ALOGI("drm->getLogMessages %zu logs", logs.size());
    if (throwExceptionAsNecessary(env, err, "Failed to get log messages")) {
        return NULL;
    }
    return hidlLogMessagesToJavaList(env, logs);
}

static const JNINativeMethod gMethods[] = {
    { "native_release", "()V", (void *)android_media_MediaDrm_native_release },

@@ -2123,6 +2163,9 @@ static const JNINativeMethod gMethods[] = {

    { "setPlaybackId", "([BLjava/lang/String;)V",
      (void *)android_media_MediaDrm_setPlaybackId },

    { "getLogMessages", "()Ljava/util/List;",
      (void *)android_media_MediaDrm_getLogMessages },
};

int register_android_media_Drm(JNIEnv *env) {