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

Commit 86b4247d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Use generated Java bindings for CEC HAL" am: dc48cad7

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1284590

Change-Id: I5bbfc0acab24d2ced30e5eca8753b2c958abfd36
parents 1332fd3a dc48cad7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ java_library_static {
        "services.net",
        "android.hardware.light-V2.0-java",
        "android.hardware.power-V1.0-java",
        "android.hardware.tv.cec-V1.0-java",
        "android.hardware.vibrator-java",
        "android.net.ipsec.ike.stubs.module_lib",
        "app-compat-annotations",
@@ -46,6 +45,7 @@ java_library_static {
        "android.hardware.health-V2.0-java",
        "android.hardware.health-V2.1-java",
        "android.hardware.light-java",
        "android.hardware.tv.cec-V1.0-java",
        "android.hardware.weaver-V1.0-java",
        "android.hardware.biometrics.face-V1.0-java",
        "android.hardware.biometrics.fingerprint-V2.1-java",
+209 −69
Original line number Diff line number Diff line
@@ -17,11 +17,18 @@
package com.android.server.hdmi;

import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.CecMessage;
import android.hardware.tv.cec.V1_0.HotplugEvent;
import android.hardware.tv.cec.V1_0.IHdmiCec;
import android.hardware.tv.cec.V1_0.IHdmiCec.getPhysicalAddressCallback;
import android.hardware.tv.cec.V1_0.IHdmiCecCallback;
import android.hardware.tv.cec.V1_0.Result;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.Handler;
import android.os.IHwBinder;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;

@@ -78,6 +85,11 @@ final class HdmiCecController {

    private static final int MAX_CEC_MESSAGE_HISTORY = 200;

    private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;

    /** Cookie for matching the right end point. */
    protected static final int HDMI_CEC_HAL_DEATH_COOKIE = 353;

    // Predicate for whether the given logical address is remote device's one or not.
    private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() {
        @Override
@@ -101,10 +113,6 @@ final class HdmiCecController {
    // device or issued by internal state change.
    private Handler mControlHandler;

    // Stores the pointer to the native implementation of the service that
    // interacts with HAL.
    private volatile long mNativePtr;

    private final HdmiControlService mService;

    // Stores the local CEC devices in the system. Device type is used for key.
@@ -142,21 +150,19 @@ final class HdmiCecController {
    static HdmiCecController createWithNativeWrapper(
            HdmiControlService service, NativeWrapper nativeWrapper) {
        HdmiCecController controller = new HdmiCecController(service, nativeWrapper);
            long nativePtr = nativeWrapper
                .nativeInit(controller, service.getServiceLooper().getQueue());
            if (nativePtr == 0L) {
                controller = null;
        String nativePtr = nativeWrapper.nativeInit();
        if (nativePtr == null) {
            HdmiLogger.warning("Couldn't get tv.cec service.");
            return null;
        }

            controller.init(nativePtr);
        controller.init(nativeWrapper);
        return controller;
    }

    private void init(long nativePtr) {
    private void init(NativeWrapper nativeWrapper) {
        mIoHandler = new Handler(mService.getIoLooper());
        mControlHandler = new Handler(mService.getServiceLooper());
        mNativePtr = nativePtr;
        nativeWrapper.setCallback(new HdmiCecCallback());
    }

    @ServiceThreadOnly
@@ -251,7 +257,7 @@ final class HdmiCecController {


    HdmiPortInfo[] getPortInfos() {
        return mNativeWrapperImpl.nativeGetPortInfos(mNativePtr);
        return mNativeWrapperImpl.nativeGetPortInfos();
    }

    /**
@@ -279,7 +285,7 @@ final class HdmiCecController {
    int addLogicalAddress(int newLogicalAddress) {
        assertRunOnServiceThread();
        if (HdmiUtils.isValidAddress(newLogicalAddress)) {
            return mNativeWrapperImpl.nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
            return mNativeWrapperImpl.nativeAddLogicalAddress(newLogicalAddress);
        } else {
            return Result.FAILURE_INVALID_ARGS;
        }
@@ -296,7 +302,7 @@ final class HdmiCecController {
        for (int i = 0; i < mLocalDevices.size(); ++i) {
            mLocalDevices.valueAt(i).clearAddress();
        }
        mNativeWrapperImpl.nativeClearLogicalAddress(mNativePtr);
        mNativeWrapperImpl.nativeClearLogicalAddress();
    }

    @ServiceThreadOnly
@@ -316,7 +322,7 @@ final class HdmiCecController {
    @ServiceThreadOnly
    int getPhysicalAddress() {
        assertRunOnServiceThread();
        return mNativeWrapperImpl.nativeGetPhysicalAddress(mNativePtr);
        return mNativeWrapperImpl.nativeGetPhysicalAddress();
    }

    /**
@@ -327,7 +333,7 @@ final class HdmiCecController {
    @ServiceThreadOnly
    int getVersion() {
        assertRunOnServiceThread();
        return mNativeWrapperImpl.nativeGetVersion(mNativePtr);
        return mNativeWrapperImpl.nativeGetVersion();
    }

    /**
@@ -338,7 +344,7 @@ final class HdmiCecController {
    @ServiceThreadOnly
    int getVendorId() {
        assertRunOnServiceThread();
        return mNativeWrapperImpl.nativeGetVendorId(mNativePtr);
        return mNativeWrapperImpl.nativeGetVendorId();
    }

    /**
@@ -351,7 +357,7 @@ final class HdmiCecController {
    void setOption(int flag, boolean enabled) {
        assertRunOnServiceThread();
        HdmiLogger.debug("setOption: [flag:%d, enabled:%b]", flag, enabled);
        mNativeWrapperImpl.nativeSetOption(mNativePtr, flag, enabled);
        mNativeWrapperImpl.nativeSetOption(flag, enabled);
    }

    /**
@@ -365,7 +371,7 @@ final class HdmiCecController {
        if (!LanguageTag.isLanguage(language)) {
            return;
        }
        mNativeWrapperImpl.nativeSetLanguage(mNativePtr, language);
        mNativeWrapperImpl.nativeSetLanguage(language);
    }

    /**
@@ -377,7 +383,7 @@ final class HdmiCecController {
    @ServiceThreadOnly
    void enableAudioReturnChannel(int port, boolean enabled) {
        assertRunOnServiceThread();
        mNativeWrapperImpl.nativeEnableAudioReturnChannel(mNativePtr, port, enabled);
        mNativeWrapperImpl.nativeEnableAudioReturnChannel(port, enabled);
    }

    /**
@@ -389,7 +395,7 @@ final class HdmiCecController {
    @ServiceThreadOnly
    boolean isConnected(int port) {
        assertRunOnServiceThread();
        return mNativeWrapperImpl.nativeIsConnected(mNativePtr, port);
        return mNativeWrapperImpl.nativeIsConnected(port);
    }

    /**
@@ -511,7 +517,7 @@ final class HdmiCecController {
            // <Polling Message> is a message which has empty body.
            int ret =
                    mNativeWrapperImpl.nativeSendCecCommand(
                        mNativePtr, sourceAddress, destinationAddress, EMPTY_BODY);
                        sourceAddress, destinationAddress, EMPTY_BODY);
            if (ret == SendMessageResult.SUCCESS) {
                return true;
            } else if (ret != SendMessageResult.NACK) {
@@ -615,7 +621,7 @@ final class HdmiCecController {
                int i = 0;
                int errorCode = SendMessageResult.SUCCESS;
                do {
                    errorCode = mNativeWrapperImpl.nativeSendCecCommand(mNativePtr,
                    errorCode = mNativeWrapperImpl.nativeSendCecCommand(
                        cecMessage.getSource(), cecMessage.getDestination(), body);
                    if (errorCode == SendMessageResult.SUCCESS) {
                        break;
@@ -639,7 +645,7 @@ final class HdmiCecController {
    }

    /**
     * Called by native when incoming CEC message arrived.
     * Called when incoming CEC message arrived.
     */
    @ServiceThreadOnly
    private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
@@ -651,7 +657,7 @@ final class HdmiCecController {
    }

    /**
     * Called by native when a hotplug event issues.
     * Called when a hotplug event issues.
     */
    @ServiceThreadOnly
    private void handleHotplug(int port, boolean connected) {
@@ -687,18 +693,19 @@ final class HdmiCecController {
    }

    protected interface NativeWrapper {
        long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
        int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress, byte[] body);
        int nativeAddLogicalAddress(long controllerPtr, int logicalAddress);
        void nativeClearLogicalAddress(long controllerPtr);
        int nativeGetPhysicalAddress(long controllerPtr);
        int nativeGetVersion(long controllerPtr);
        int nativeGetVendorId(long controllerPtr);
        HdmiPortInfo[] nativeGetPortInfos(long controllerPtr);
        void nativeSetOption(long controllerPtr, int flag, boolean enabled);
        void nativeSetLanguage(long controllerPtr, String language);
        void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag);
        boolean nativeIsConnected(long controllerPtr, int port);
        String nativeInit();
        void setCallback(HdmiCecCallback callback);
        int nativeSendCecCommand(int srcAddress, int dstAddress, byte[] body);
        int nativeAddLogicalAddress(int logicalAddress);
        void nativeClearLogicalAddress();
        int nativeGetPhysicalAddress();
        int nativeGetVersion();
        int nativeGetVendorId();
        HdmiPortInfo[] nativeGetPortInfos();
        void nativeSetOption(int flag, boolean enabled);
        void nativeSetLanguage(String language);
        void nativeEnableAudioReturnChannel(int port, boolean flag);
        boolean nativeIsConnected(int port);
    }

    private static native long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
@@ -716,67 +723,200 @@ final class HdmiCecController {
        int port, boolean flag);
    private static native boolean nativeIsConnected(long controllerPtr, int port);

    private static final class NativeWrapperImpl implements NativeWrapper {
    private static final class NativeWrapperImpl implements NativeWrapper,
            IHwBinder.DeathRecipient, getPhysicalAddressCallback {
        private IHdmiCec mHdmiCec;
        private final Object mLock = new Object();
        private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;

        @Override
        public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
            return HdmiCecController.nativeInit(handler, messageQueue);
        public String nativeInit() {
            return (connectToHal() ? mHdmiCec.toString() : null);
        }

        boolean connectToHal() {
            try {
                mHdmiCec = IHdmiCec.getService();
                try {
                    mHdmiCec.linkToDeath(this, HDMI_CEC_HAL_DEATH_COOKIE);
                } catch (RemoteException e) {
                    HdmiLogger.error("Couldn't link to death : ", e);
                }
            } catch (RemoteException e) {
                HdmiLogger.error("Couldn't get tv.cec service : ", e);
                return false;
            }
            return true;
        }

        @Override
        public int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress,
            byte[] body) {
            return HdmiCecController.nativeSendCecCommand(controllerPtr, srcAddress, dstAddress, body);
        public void setCallback(HdmiCecCallback callback) {
            try {
                mHdmiCec.setCallback(callback);
            } catch (RemoteException e) {
                HdmiLogger.error("Couldn't initialise tv.cec callback : ", e);
            }
        }

        @Override
        public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
            return HdmiCecController.nativeAddLogicalAddress(controllerPtr, logicalAddress);
        public int nativeSendCecCommand(int srcAddress, int dstAddress, byte[] body) {
            CecMessage message = new CecMessage();
            message.initiator = srcAddress;
            message.destination = dstAddress;
            message.body = new ArrayList<>(body.length);
            for (byte b : body) {
                message.body.add(b);
            }
            try {
                return mHdmiCec.sendMessage(message);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to send CEC message : ", e);
                return SendMessageResult.FAIL;
            }
        }

        @Override
        public void nativeClearLogicalAddress(long controllerPtr) {
            HdmiCecController.nativeClearLogicalAddress(controllerPtr);
        public int nativeAddLogicalAddress(int logicalAddress) {
            try {
                return mHdmiCec.addLogicalAddress(logicalAddress);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to add a logical address : ", e);
                return Result.FAILURE_INVALID_ARGS;
            }
        }

        @Override
        public int nativeGetPhysicalAddress(long controllerPtr) {
            return HdmiCecController.nativeGetPhysicalAddress(controllerPtr);
        public void nativeClearLogicalAddress() {
            try {
                mHdmiCec.clearLogicalAddress();
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to clear logical address : ", e);
            }
        }

        @Override
        public int nativeGetVersion(long controllerPtr) {
            return HdmiCecController.nativeGetVersion(controllerPtr);
        public int nativeGetPhysicalAddress() {
            try {
                mHdmiCec.getPhysicalAddress(this);
                return mPhysicalAddress;
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to get physical address : ", e);
                return INVALID_PHYSICAL_ADDRESS;
            }
        }

        @Override
        public int nativeGetVendorId(long controllerPtr) {
            return HdmiCecController.nativeGetVendorId(controllerPtr);
        public int nativeGetVersion() {
            try {
                return mHdmiCec.getCecVersion();
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to get cec version : ", e);
                return Result.FAILURE_UNKNOWN;
            }
        }

        @Override
        public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
            return HdmiCecController.nativeGetPortInfos(controllerPtr);
        public int nativeGetVendorId() {
            try {
                return mHdmiCec.getVendorId();
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to get vendor id : ", e);
                return Result.FAILURE_UNKNOWN;
            }
        }

        @Override
        public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {
            HdmiCecController.nativeSetOption(controllerPtr, flag, enabled);
        public HdmiPortInfo[] nativeGetPortInfos() {
            try {
                ArrayList<android.hardware.tv.cec.V1_0.HdmiPortInfo> hdmiPortInfos =
                        mHdmiCec.getPortInfo();
                HdmiPortInfo[] hdmiPortInfo = new HdmiPortInfo[hdmiPortInfos.size()];
                int i = 0;
                for (android.hardware.tv.cec.V1_0.HdmiPortInfo portInfo : hdmiPortInfos) {
                    hdmiPortInfo[i] = new HdmiPortInfo(portInfo.portId,
                            portInfo.type,
                            portInfo.physicalAddress,
                            portInfo.cecSupported,
                            false,
                            portInfo.arcSupported);
                    i++;
                }
                return hdmiPortInfo;
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to get port information : ", e);
                return null;
            }
        }

        @Override
        public void nativeSetLanguage(long controllerPtr, String language) {
            HdmiCecController.nativeSetLanguage(controllerPtr, language);
        public void nativeSetOption(int flag, boolean enabled) {
            try {
                mHdmiCec.setOption(flag, enabled);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to set option : ", e);
            }
        }

        @Override
        public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {
            HdmiCecController.nativeEnableAudioReturnChannel(controllerPtr, port, flag);
        public void nativeSetLanguage(String language) {
            try {
                mHdmiCec.setLanguage(language);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to set language : ", e);
            }
        }

        @Override
        public void nativeEnableAudioReturnChannel(int port, boolean flag) {
            try {
                mHdmiCec.enableAudioReturnChannel(port, flag);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to enable/disable ARC : ", e);
            }
        }

        @Override
        public boolean nativeIsConnected(int port) {
            try {
                return mHdmiCec.isConnected(port);
            } catch (RemoteException e) {
                HdmiLogger.error("Failed to get connection info : ", e);
                return false;
            }
        }

        @Override
        public void serviceDied(long cookie) {
            if (cookie == HDMI_CEC_HAL_DEATH_COOKIE) {
                HdmiLogger.error(TAG, "Service died cokkie : " + cookie + "; reconnecting");
                connectToHal();
            }
        }

        @Override
        public void onValues(int result, short addr) {
            if (result == Result.SUCCESS) {
                synchronized (mLock) {
                    mPhysicalAddress = new Short(addr).intValue();
                }
            }
        }
    }

    final class HdmiCecCallback extends IHdmiCecCallback.Stub {
        @Override
        public void onCecMessage(CecMessage message) throws RemoteException {
            byte[] body = new byte[message.body.size()];
            for (int i = 0; i < message.body.size(); i++) {
                body[i] = message.body.get(i);
            }
            runOnServiceThread(
                    () -> handleIncomingCecCommand(message.initiator, message.destination, body));
        }

        @Override
        public boolean nativeIsConnected(long controllerPtr, int port) {
            return HdmiCecController.nativeIsConnected(controllerPtr, port);
        public void onHotplugEvent(HotplugEvent event) throws RemoteException {
            runOnServiceThread(() -> handleHotplug(event.portId, event.connected));
        }
    }

+4 −0
Original line number Diff line number Diff line
@@ -71,6 +71,10 @@ final class HdmiLogger {
        getLogger().errorInternal(toLogString(logMessage, objs));
    }

    static final void error(String logMessage, Exception e, Object... objs) {
        getLogger().errorInternal(toLogString(logMessage + e, objs));
    }

    private void errorInternal(String logMessage) {
        String log = updateLog(mErrorTimingCache, logMessage);
        if (!log.isEmpty()) {
+16 −14
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package com.android.server.hdmi;

import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.MessageQueue;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiCecController.NativeWrapper;
@@ -53,13 +52,16 @@ final class FakeNativeWrapper implements NativeWrapper {
    private HdmiPortInfo[] mHdmiPortInfo = null;

    @Override
    public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
        return 1L;
    public String nativeInit() {
        return "[class or subclass of IHdmiCec]@Proxy";
    }

    @Override
    public void setCallback(HdmiCecController.HdmiCecCallback callback) {}

    @Override
    public int nativeSendCecCommand(
            long controllerPtr, int srcAddress, int dstAddress, byte[] body) {
            int srcAddress, int dstAddress, byte[] body) {
        if (body.length == 0) {
            return mPollAddressResponse[dstAddress];
        } else {
@@ -69,30 +71,30 @@ final class FakeNativeWrapper implements NativeWrapper {
    }

    @Override
    public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
    public int nativeAddLogicalAddress(int logicalAddress) {
        return 0;
    }

    @Override
    public void nativeClearLogicalAddress(long controllerPtr) {}
    public void nativeClearLogicalAddress() {}

    @Override
    public int nativeGetPhysicalAddress(long controllerPtr) {
    public int nativeGetPhysicalAddress() {
        return mMyPhysicalAddress;
    }

    @Override
    public int nativeGetVersion(long controllerPtr) {
    public int nativeGetVersion() {
        return 0;
    }

    @Override
    public int nativeGetVendorId(long controllerPtr) {
    public int nativeGetVendorId() {
        return 0;
    }

    @Override
    public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
    public HdmiPortInfo[] nativeGetPortInfos() {
        if (mHdmiPortInfo == null) {
            mHdmiPortInfo = new HdmiPortInfo[1];
            mHdmiPortInfo[0] = new HdmiPortInfo(1, 1, 0x1000, true, true, true);
@@ -101,16 +103,16 @@ final class FakeNativeWrapper implements NativeWrapper {
    }

    @Override
    public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {}
    public void nativeSetOption(int flag, boolean enabled) {}

    @Override
    public void nativeSetLanguage(long controllerPtr, String language) {}
    public void nativeSetLanguage(String language) {}

    @Override
    public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {}
    public void nativeEnableAudioReturnChannel(int port, boolean flag) {}

    @Override
    public boolean nativeIsConnected(long controllerPtr, int port) {
    public boolean nativeIsConnected(int port) {
        return false;
    }