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

Commit 98af1591 authored by Marin Shalamanov's avatar Marin Shalamanov
Browse files

DeviceProductInfo API.

DeviceProductInfo API that can be used to prime an Android TV remote
with entries from an infrared database for controlling connected
audio and TV devices. See go/display-identifiers.

Bug: 145299597
Test: adb shell dumpsys display
Change-Id: I8d709d55d830eed932b51bb8c374d32e20eecf6d
parent 5cbf58e3
Loading
Loading
Loading
Loading
+224 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.hardware.display;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Product-specific information about the display or the directly connected device on the
 * display chain. For example, if the display is transitively connected, this field may contain
 * product information about the intermediate device.
 * @hide
 */
public final class DeviceProductInfo implements Parcelable {
    final private String mName;
    final private String mManufacturerPnpId;
    final private String mProductId;
    final private Integer mModelYear;
    final private ManufactureDate mManufactureDate;

    public DeviceProductInfo(
            String name,
            String manufacturerPnpId,
            String productCode,
            Integer modelYear,
            ManufactureDate manufactureDate) {
        this.mName = name;
        this.mManufacturerPnpId = manufacturerPnpId;
        this.mProductId = productCode;
        this.mModelYear = modelYear;
        this.mManufactureDate = manufactureDate;
    }

    private DeviceProductInfo(Parcel in) {
        mName = in.readString();
        mManufacturerPnpId = in.readString();
        mProductId = (String) in.readValue(null);
        mModelYear = (Integer) in.readValue(null);
        mManufactureDate = (ManufactureDate) in.readValue(null);
    }

    /**
     * @return Display name.
     */
    public String getName() {
        return mName;
    }

    /**
     * @return Manufacturer Plug and Play ID.
     */
    public String getManufacturerPnpId() {
        return mManufacturerPnpId;
    }

    /**
     * @return Manufacturer product ID.
     */
    public String getProductId() {
        return mProductId;
    }

    /**
     * @return Model year of the device. Typically exactly one of model year or
     *      manufacture date will be present.
     */
    public Integer getModelYear() {
        return mModelYear;
    }

    /**
     * @return Manufacture date. Typically exactly one of model year or manufacture
     * date will be present.
     */
    public ManufactureDate getManufactureDate() {
        return mManufactureDate;
    }

    @Override
    public String toString() {
        return "DeviceProductInfo{"
                + "name="
                + mName
                + ", manufacturerPnpId="
                + mManufacturerPnpId
                + ", productId="
                + mProductId
                + ", modelYear="
                + mModelYear
                + ", manufactureDate="
                + mManufactureDate
                + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DeviceProductInfo that = (DeviceProductInfo) o;
        return Objects.equals(mName, that.mName)
                && Objects.equals(mManufacturerPnpId, that.mManufacturerPnpId)
                && Objects.equals(mProductId, that.mProductId)
                && Objects.equals(mModelYear, that.mModelYear)
                && Objects.equals(mManufactureDate, that.mManufactureDate);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate);
    }

    public static final Creator<DeviceProductInfo> CREATOR =
            new Creator<DeviceProductInfo>() {
                @Override
                public DeviceProductInfo createFromParcel(Parcel in) {
                    return new DeviceProductInfo(in);
                }

                @Override
                public DeviceProductInfo[] newArray(int size) {
                    return new DeviceProductInfo[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mName);
        dest.writeString(mManufacturerPnpId);
        dest.writeValue(mProductId);
        dest.writeValue(mModelYear);
        dest.writeValue(mManufactureDate);
    }

    /**
     * Stores information about the date of manufacture.
     *
     * @hide
     */
    public static class ManufactureDate implements Parcelable {
        final private Integer mWeek;
        final private Integer mYear;

        public ManufactureDate(Integer week, Integer year) {
            mWeek = week;
            mYear = year;
        }

        protected ManufactureDate(Parcel in) {
            mWeek = (Integer) in.readValue(null);
            mYear = (Integer) in.readValue(null);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeValue(mWeek);
            dest.writeValue(mYear);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final Creator<ManufactureDate> CREATOR =
                new Creator<ManufactureDate>() {
                    @Override
                    public ManufactureDate createFromParcel(Parcel in) {
                        return new ManufactureDate(in);
                    }

                    @Override
                    public ManufactureDate[] newArray(int size) {
                        return new ManufactureDate[size];
                    }
                };

        public int getYear() {
            return mYear;
        }

        public int getWeek() {
            return mWeek;
        }

        @Override
        public String toString() {
            return "ManufactureDate{week=" + mWeek + ", year=" + mYear + '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ManufactureDate that = (ManufactureDate) o;
            return Objects.equals(mWeek, that.mWeek) && Objects.equals(mYear, that.mYear);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mWeek, mYear);
        }
    }
}
+14 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.hardware.display.DeviceProductInfo;
import android.os.Build;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
@@ -69,6 +70,13 @@ public final class DisplayInfo implements Parcelable {
     */
     */
    public DisplayAddress address;
    public DisplayAddress address;


    /**
     * Product-specific information about the display or the directly connected device on the
     * display chain. For example, if the display is transitively connected, this field may contain
     * product information about the intermediate device.
     */
    public DeviceProductInfo deviceProductInfo;

    /**
    /**
     * The human-readable name of the display.
     * The human-readable name of the display.
     */
     */
@@ -297,6 +305,7 @@ public final class DisplayInfo implements Parcelable {
                && type == other.type
                && type == other.type
                && displayId == other.displayId
                && displayId == other.displayId
                && Objects.equals(address, other.address)
                && Objects.equals(address, other.address)
                && Objects.equals(deviceProductInfo, other.deviceProductInfo)
                && Objects.equals(uniqueId, other.uniqueId)
                && Objects.equals(uniqueId, other.uniqueId)
                && appWidth == other.appWidth
                && appWidth == other.appWidth
                && appHeight == other.appHeight
                && appHeight == other.appHeight
@@ -336,6 +345,7 @@ public final class DisplayInfo implements Parcelable {
        type = other.type;
        type = other.type;
        displayId = other.displayId;
        displayId = other.displayId;
        address = other.address;
        address = other.address;
        deviceProductInfo = other.deviceProductInfo;
        name = other.name;
        name = other.name;
        uniqueId = other.uniqueId;
        uniqueId = other.uniqueId;
        appWidth = other.appWidth;
        appWidth = other.appWidth;
@@ -373,6 +383,7 @@ public final class DisplayInfo implements Parcelable {
        type = source.readInt();
        type = source.readInt();
        displayId = source.readInt();
        displayId = source.readInt();
        address = source.readParcelable(null);
        address = source.readParcelable(null);
        deviceProductInfo = source.readParcelable(null);
        name = source.readString();
        name = source.readString();
        appWidth = source.readInt();
        appWidth = source.readInt();
        appHeight = source.readInt();
        appHeight = source.readInt();
@@ -418,6 +429,7 @@ public final class DisplayInfo implements Parcelable {
        dest.writeInt(type);
        dest.writeInt(type);
        dest.writeInt(displayId);
        dest.writeInt(displayId);
        dest.writeParcelable(address, flags);
        dest.writeParcelable(address, flags);
        dest.writeParcelable(deviceProductInfo, flags);
        dest.writeString(name);
        dest.writeString(name);
        dest.writeInt(appWidth);
        dest.writeInt(appWidth);
        dest.writeInt(appHeight);
        dest.writeInt(appHeight);
@@ -645,6 +657,8 @@ public final class DisplayInfo implements Parcelable {
        if (address != null) {
        if (address != null) {
            sb.append(", address ").append(address);
            sb.append(", address ").append(address);
        }
        }
        sb.append(", deviceProductInfo ");
        sb.append(deviceProductInfo);
        sb.append(", state ");
        sb.append(", state ");
        sb.append(Display.stateToString(state));
        sb.append(Display.stateToString(state));
        if (ownerUid != 0 || ownerPackageName != null) {
        if (ownerUid != 0 || ownerPackageName != null) {
+4 −1
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region;
import android.hardware.display.DeviceProductInfo;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
import android.hardware.display.DisplayedContentSamplingAttributes;
import android.os.Build;
import android.os.Build;
@@ -1286,12 +1287,14 @@ public final class SurfaceControl implements Parcelable {
        public boolean isInternal;
        public boolean isInternal;
        public float density;
        public float density;
        public boolean secure;
        public boolean secure;
        public DeviceProductInfo deviceProductInfo;


        @Override
        @Override
        public String toString() {
        public String toString() {
            return "DisplayInfo{isInternal=" + isInternal
            return "DisplayInfo{isInternal=" + isInternal
                    + ", density=" + density
                    + ", density=" + density
                    + ", secure=" + secure + "}";
                    + ", secure=" + secure
                    + ", deviceProductInfo=" + deviceProductInfo + "}";
        }
        }
    }
    }


+84 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdio.h>
#include <system/graphics.h>
#include <system/graphics.h>
#include <ui/ConfigStoreTypes.h>
#include <ui/ConfigStoreTypes.h>
#include <ui/DeviceProductInfo.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayedFrameStats.h>
#include <ui/DisplayedFrameStats.h>
@@ -62,12 +63,22 @@ static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) {
static const char* const OutOfResourcesException =
static const char* const OutOfResourcesException =
    "android/view/Surface$OutOfResourcesException";
    "android/view/Surface$OutOfResourcesException";


static struct {
    jclass clazz;
    jmethodID ctor;
} gIntegerClassInfo;

static jobject toInteger(JNIEnv* env, int32_t i) {
    return env->NewObject(gIntegerClassInfo.clazz, gIntegerClassInfo.ctor, i);
}

static struct {
static struct {
    jclass clazz;
    jclass clazz;
    jmethodID ctor;
    jmethodID ctor;
    jfieldID isInternal;
    jfieldID isInternal;
    jfieldID density;
    jfieldID density;
    jfieldID secure;
    jfieldID secure;
    jfieldID deviceProductInfo;
} gDisplayInfoClassInfo;
} gDisplayInfoClassInfo;


static struct {
static struct {
@@ -109,6 +120,16 @@ static struct {
    jmethodID ctor;
    jmethodID ctor;
} gHdrCapabilitiesClassInfo;
} gHdrCapabilitiesClassInfo;


static struct {
    jclass clazz;
    jmethodID ctor;
} gDeviceProductInfoClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
} gDeviceProductInfoManufactureDateClassInfo;

static struct {
static struct {
    jclass clazz;
    jclass clazz;
    jmethodID builder;
    jmethodID builder;
@@ -774,6 +795,41 @@ static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
    }
    }
}
}


static jobject convertDeviceProductInfoToJavaObject(
        JNIEnv* env, const std::optional<DeviceProductInfo>& info) {
    using ModelYear = android::DeviceProductInfo::ModelYear;
    using ManufactureYear = android::DeviceProductInfo::ManufactureYear;
    using ManufactureWeekAndYear = android::DeviceProductInfo::ManufactureWeekAndYear;

    if (!info) return nullptr;
    jstring name = env->NewStringUTF(info->name.data());
    jstring manufacturerPnpId = env->NewStringUTF(info->manufacturerPnpId.data());
    jobject productId = env->NewStringUTF(info->productId.data());
    const auto& date = info->manufactureOrModelDate;
    jobject modelYear, manufactureDate;
    if (const auto* model = std::get_if<ModelYear>(&date)) {
        modelYear = toInteger(env, model->year);
        manufactureDate = nullptr;
    } else if (const auto* manufactureWeekAndYear = std::get_if<ManufactureWeekAndYear>(&date)) {
        modelYear = nullptr;
        manufactureDate = env->NewObject(gDeviceProductInfoManufactureDateClassInfo.clazz,
                                               gDeviceProductInfoManufactureDateClassInfo.ctor,
                                               toInteger(env, manufactureWeekAndYear->week),
                                               toInteger(env, manufactureWeekAndYear->year));
    } else if (const auto* manufactureYear = std::get_if<ManufactureYear>(&date)) {
        modelYear = nullptr;
        manufactureDate = env->NewObject(gDeviceProductInfoManufactureDateClassInfo.clazz,
                                       gDeviceProductInfoManufactureDateClassInfo.ctor,
                                       nullptr,
                                       toInteger(env, manufactureYear->year));
    } else {
        LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
    }

    return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name,
                          manufacturerPnpId, productId, modelYear, manufactureDate);
}

static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
    DisplayInfo info;
    DisplayInfo info;
    if (const auto token = ibinderForJavaObject(env, tokenObj);
    if (const auto token = ibinderForJavaObject(env, tokenObj);
@@ -786,6 +842,8 @@ static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj)
                         info.connectionType == DisplayConnectionType::Internal);
                         info.connectionType == DisplayConnectionType::Internal);
    env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
    env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
    env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
    env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
    env->SetObjectField(object, gDisplayInfoClassInfo.deviceProductInfo,
                        convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo));
    return object;
    return object;
}
}


@@ -1528,12 +1586,19 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
    int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));


    jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
    gIntegerClassInfo.clazz = MakeGlobalRefOrDie(env, integerClass);
    gIntegerClassInfo.ctor = GetMethodIDOrDie(env, gIntegerClassInfo.clazz, "<init>", "(I)V");

    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
    gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
    gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
    gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
    gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
    gDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
    gDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
    gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
    gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
    gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
    gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
    gDisplayInfoClassInfo.deviceProductInfo =
            GetFieldIDOrDie(env, infoClazz, "deviceProductInfo",
                            "Landroid/hardware/display/DeviceProductInfo;");


    jclass configClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayConfig");
    jclass configClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayConfig");
    gDisplayConfigClassInfo.clazz = MakeGlobalRefOrDie(env, configClazz);
    gDisplayConfigClassInfo.clazz = MakeGlobalRefOrDie(env, configClazz);
@@ -1574,6 +1639,25 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gHdrCapabilitiesClassInfo.ctor = GetMethodIDOrDie(env, hdrCapabilitiesClazz, "<init>",
    gHdrCapabilitiesClassInfo.ctor = GetMethodIDOrDie(env, hdrCapabilitiesClazz, "<init>",
            "([IFFF)V");
            "([IFFF)V");


    jclass deviceProductInfoClazz =
            FindClassOrDie(env, "android/hardware/display/DeviceProductInfo");
    gDeviceProductInfoClassInfo.clazz = MakeGlobalRefOrDie(env, deviceProductInfoClazz);
    gDeviceProductInfoClassInfo.ctor =
            GetMethodIDOrDie(env, deviceProductInfoClazz, "<init>",
                             "(Ljava/lang/String;"
                             "Ljava/lang/String;"
                             "Ljava/lang/String;"
                             "Ljava/lang/Integer;"
                             "Landroid/hardware/display/DeviceProductInfo$ManufactureDate;)V");

    jclass deviceProductInfoManufactureDateClazz =
            FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate");
    gDeviceProductInfoManufactureDateClassInfo.clazz =
            MakeGlobalRefOrDie(env, deviceProductInfoManufactureDateClazz);
    gDeviceProductInfoManufactureDateClassInfo.ctor =
            GetMethodIDOrDie(env, deviceProductInfoManufactureDateClazz, "<init>",
                             "(Ljava/lang/Integer;Ljava/lang/Integer;)V");

    jclass graphicsBufferClazz = FindClassOrDie(env, "android/graphics/GraphicBuffer");
    jclass graphicsBufferClazz = FindClassOrDie(env, "android/graphics/GraphicBuffer");
    gGraphicBufferClassInfo.clazz = MakeGlobalRefOrDie(env, graphicsBufferClazz);
    gGraphicBufferClassInfo.clazz = MakeGlobalRefOrDie(env, graphicsBufferClazz);
    gGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env, graphicsBufferClazz,
    gGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env, graphicsBufferClazz,
+11 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.display;
package com.android.server.display;


import android.hardware.display.DeviceProductInfo;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayViewport;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Display;
@@ -287,6 +288,13 @@ final class DisplayDeviceInfo {
     */
     */
    public DisplayAddress address;
    public DisplayAddress address;


    /**
     * Product-specific information about the display or the directly connected device on the
     * display chain. For example, if the display is transitively connected, this field may contain
     * product information about the intermediate device.
     */
    public DeviceProductInfo deviceProductInfo;

    /**
    /**
     * Display state.
     * Display state.
     */
     */
@@ -360,6 +368,7 @@ final class DisplayDeviceInfo {
                || rotation != other.rotation
                || rotation != other.rotation
                || type != other.type
                || type != other.type
                || !Objects.equals(address, other.address)
                || !Objects.equals(address, other.address)
                || !Objects.equals(deviceProductInfo, other.deviceProductInfo)
                || ownerUid != other.ownerUid
                || ownerUid != other.ownerUid
                || !Objects.equals(ownerPackageName, other.ownerPackageName)) {
                || !Objects.equals(ownerPackageName, other.ownerPackageName)) {
            diff |= DIFF_OTHER;
            diff |= DIFF_OTHER;
@@ -396,6 +405,7 @@ final class DisplayDeviceInfo {
        rotation = other.rotation;
        rotation = other.rotation;
        type = other.type;
        type = other.type;
        address = other.address;
        address = other.address;
        deviceProductInfo = other.deviceProductInfo;
        state = other.state;
        state = other.state;
        ownerUid = other.ownerUid;
        ownerUid = other.ownerUid;
        ownerPackageName = other.ownerPackageName;
        ownerPackageName = other.ownerPackageName;
@@ -429,6 +439,7 @@ final class DisplayDeviceInfo {
        if (address != null) {
        if (address != null) {
            sb.append(", address ").append(address);
            sb.append(", address ").append(address);
        }
        }
        sb.append(", deviceProductInfo ").append(deviceProductInfo);
        sb.append(", state ").append(Display.stateToString(state));
        sb.append(", state ").append(Display.stateToString(state));
        if (ownerUid != 0 || ownerPackageName != null) {
        if (ownerUid != 0 || ownerPackageName != null) {
            sb.append(", owner ").append(ownerPackageName);
            sb.append(", owner ").append(ownerPackageName);
Loading