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

Commit 741c60f3 authored by Nathalie Le Clair's avatar Nathalie Le Clair Committed by Android (Google) Code Review
Browse files

Merge changes Id94cad54,I25f6b8ae

* changes:
  Fix unit tests after binding to the eARC HAL
  EArc AIDL Binding
parents 11a60a27 5e21bb07
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ java_library_static {
    defaults: ["platform_service_defaults"],
    srcs: [
        ":android.hardware.biometrics.face-V3-java-source",
        ":android.hardware.tv.hdmi.connection-V1-java-source",
        ":android.hardware.tv.hdmi.earc-V1-java-source",
        ":statslog-art-java-gen",
        ":statslog-contexthub-java-gen",
        ":services.core-sources",
@@ -160,6 +162,7 @@ java_library_static {
        "android.hardware.tv.cec-V1.1-java",
        "android.hardware.tv.hdmi.cec-V1-java",
        "android.hardware.tv.hdmi.connection-V1-java",
        "android.hardware.tv.hdmi.earc-V1-java",
        "android.hardware.weaver-V1.0-java",
        "android.hardware.weaver-V2-java",
        "android.hardware.biometrics.face-V1.0-java",
+14 −6
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.hdmi;
import android.annotation.IntDef;
import android.annotation.StringDef;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.tv.hdmi.connection.HpdSignal;
import android.hardware.tv.hdmi.earc.IEArcStatus;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -599,10 +601,13 @@ final class Constants {
    })
    @interface RcProfileSource {}

    static final int HDMI_EARC_STATUS_IDLE = 0;             // IDLE1
    static final int HDMI_EARC_STATUS_EARC_PENDING = 1;     // DISC1 and DISC2
    static final int HDMI_EARC_STATUS_ARC_PENDING = 2;      // IDLE2 for ARC
    static final int HDMI_EARC_STATUS_EARC_CONNECTED = 3;   // eARC connected
    static final int HDMI_EARC_STATUS_IDLE = IEArcStatus.STATUS_IDLE; // IDLE1
    static final int HDMI_EARC_STATUS_EARC_PENDING =
            IEArcStatus.STATUS_EARC_PENDING; // DISC1 and DISC2
    static final int HDMI_EARC_STATUS_ARC_PENDING = IEArcStatus.STATUS_ARC_PENDING; // IDLE2 for ARC
    static final int HDMI_EARC_STATUS_EARC_CONNECTED =
            IEArcStatus.STATUS_EARC_CONNECTED; // eARC connected

    @IntDef({
            HDMI_EARC_STATUS_IDLE,
            HDMI_EARC_STATUS_EARC_PENDING,
@@ -611,8 +616,11 @@ final class Constants {
            })
    @interface EarcStatus {}

    static final int HDMI_HPD_TYPE_PHYSICAL = 0;   // Default. Physical hotplug signal.
    static final int HDMI_HPD_TYPE_STATUS_BIT = 1; // HDMI_HPD status bit.
    static final int HDMI_HPD_TYPE_PHYSICAL =
            HpdSignal.HDMI_HPD_PHYSICAL; // Default. Physical hotplug signal.
    static final int HDMI_HPD_TYPE_STATUS_BIT =
            HpdSignal.HDMI_HPD_STATUS_BIT; // HDMI_HPD status bit.

    @IntDef({
            HDMI_HPD_TYPE_PHYSICAL,
            HDMI_HPD_TYPE_STATUS_BIT
+5 −0
Original line number Diff line number Diff line
@@ -930,6 +930,11 @@ public class HdmiControlService extends SystemService {
        mCecController = cecController;
    }

    @VisibleForTesting
    void setEarcController(HdmiEarcController earcController) {
        mEarcController = earcController;
    }

    @VisibleForTesting
    void setHdmiCecNetwork(HdmiCecNetwork hdmiCecNetwork) {
        mHdmiCecNetwork = hdmiCecNetwork;
+145 −20
Original line number Diff line number Diff line
@@ -16,8 +16,14 @@

package com.android.server.hdmi;

import android.hardware.tv.hdmi.earc.IEArc;
import android.hardware.tv.hdmi.earc.IEArcCallback;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;

import com.android.internal.annotations.VisibleForTesting;

@@ -29,9 +35,109 @@ final class HdmiEarcController {

    private final HdmiControlService mService;

    private EArcNativeWrapper mEArcNativeWrapperImpl;

    protected interface EArcNativeWrapper {
        boolean nativeInit();
        void nativeSetEArcEnabled(boolean enabled);
        boolean nativeIsEArcEnabled();
        void nativeSetCallback(EarcAidlCallback callback);
        byte nativeGetState(int portId);
        byte[] nativeGetLastReportedAudioCapabilities(int portId);
    }

    private static final class EArcNativeWrapperImpl implements EArcNativeWrapper,
            IBinder.DeathRecipient {
        private IEArc mEArc;
        private EarcAidlCallback mEArcCallback;

        @Override
        public void binderDied() {
            mEArc.asBinder().unlinkToDeath(this, 0);
            connectToHal();
            if (mEArcCallback != null) {
                nativeSetCallback(mEArcCallback);
            }
        }

        boolean connectToHal() {
            mEArc =
                    IEArc.Stub.asInterface(
                            ServiceManager.getService(IEArc.DESCRIPTOR + "/default"));
            if (mEArc == null) {
                return false;
            }
            try {
                mEArc.asBinder().linkToDeath(this, 0);
            } catch (RemoteException e) {
                HdmiLogger.error("Couldn't link callback object: ", e);
            }
            return true;
        }

        @Override
        public boolean nativeInit() {
            return connectToHal();
        }

        @Override
        public void nativeSetEArcEnabled(boolean enabled) {
            try {
                mEArc.setEArcEnabled(enabled);
            } catch (ServiceSpecificException sse) {
                HdmiLogger.error(
                        "Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode);
            } catch (RemoteException re) {
                HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", re);
            }
        }

        @Override
        public boolean nativeIsEArcEnabled() {
            try {
                return mEArc.isEArcEnabled();
            } catch (RemoteException re) {
                HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re);
                return false;
            }
        }

        @Override
        public void nativeSetCallback(EarcAidlCallback callback) {
            mEArcCallback = callback;
            try {
                mEArc.setCallback(callback);
            } catch (RemoteException re) {
                HdmiLogger.error("Could not set callback. Exception: ", re);
            }
        }

        @Override
        public byte nativeGetState(int portId) {
            try {
                return mEArc.getState(portId);
            } catch (RemoteException re) {
                HdmiLogger.error("Could not get eARC state. Exception: ", re);
                return -1;
            }
        }

        @Override
        public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
            try {
                return mEArc.getLastReportedAudioCapabilities(portId);
            } catch (RemoteException re) {
                HdmiLogger.error(
                        "Could not read last reported audio capabilities. Exception: ", re);
                return null;
            }
        }
    }

    // Private constructor. Use HdmiEarcController.create().
    private HdmiEarcController(HdmiControlService service) {
    private HdmiEarcController(HdmiControlService service, EArcNativeWrapper nativeWrapper) {
        mService = service;
        mEArcNativeWrapperImpl = nativeWrapper;
    }

    /**
@@ -45,14 +151,29 @@ final class HdmiEarcController {
     *         returns {@code null}.
     */
    static HdmiEarcController create(HdmiControlService service) {
        // TODO add the native wrapper and return null if eARC HAL is not present.
        HdmiEarcController controller = new HdmiEarcController(service);
        controller.init();
        return createWithNativeWrapper(service, new EArcNativeWrapperImpl());
    }

    /**
     * A factory method with injection of native methods for testing.
     */
    static HdmiEarcController createWithNativeWrapper(HdmiControlService service,
            EArcNativeWrapper nativeWrapper) {
        HdmiEarcController controller = new HdmiEarcController(service, nativeWrapper);
        if (!controller.init(nativeWrapper)) {
            HdmiLogger.warning("Could not connect to eARC AIDL HAL.");
            return null;
        }
        return controller;
    }

    private void init() {
    private boolean init(EArcNativeWrapper nativeWrapper) {
        if (nativeWrapper.nativeInit()) {
            mControlHandler = new Handler(mService.getServiceLooper());
            mEArcNativeWrapperImpl.nativeSetCallback(new EarcAidlCallback());
            return true;
        }
        return false;
    }

    private void assertRunOnServiceThread() {
@@ -73,9 +194,7 @@ final class HdmiEarcController {
    @HdmiAnnotations.ServiceThreadOnly
    void setEarcEnabled(boolean enabled) {
        assertRunOnServiceThread();
        // Stub.
        // TODO: bind to native.
        // TODO: handle error return values here, with logging.
        mEArcNativeWrapperImpl.nativeSetEArcEnabled(enabled);
    }

    /**
@@ -86,23 +205,21 @@ final class HdmiEarcController {
    @HdmiAnnotations.ServiceThreadOnly
    @Constants.EarcStatus
    int getState(int portId) {
        // Stub.
        // TODO: bind to native.
        return Constants.HDMI_EARC_STATUS_IDLE;
        return mEArcNativeWrapperImpl.nativeGetState(portId);
    }

    /**
     * Ask the HAL to report the last eARC capabilities that the connected audio system reported.
     *
     * @return the raw eARC capabilities
     */
    @HdmiAnnotations.ServiceThreadOnly
    byte[] getLastReportedCaps() {
        // Stub. TODO: bind to native.
        return new byte[] {};
    byte[] getLastReportedCaps(int portId) {
        return mEArcNativeWrapperImpl.nativeGetLastReportedAudioCapabilities(portId);
    }

    final class EarcCallback {
        public void onStateChange(@Constants.EarcStatus int status, int portId) {
    final class EarcAidlCallback extends IEArcCallback.Stub {
        public void onStateChange(@Constants.EarcStatus byte status, int portId) {
            runOnServiceThread(
                    () -> mService.handleEarcStateChange(status, portId));
        }
@@ -111,7 +228,15 @@ final class HdmiEarcController {
            runOnServiceThread(
                    () -> mService.handleEarcCapabilitiesReported(rawCapabilities, portId));
        }

        @Override
        public synchronized String getInterfaceHash() throws RemoteException {
            return IEArcCallback.Stub.HASH;
        }

    // TODO: bind to native.
        @Override
        public int getInterfaceVersion() throws RemoteException {
            return IEArcCallback.Stub.VERSION;
        }
    }
}
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.server.hdmi;

import android.hardware.tv.hdmi.earc.IEArcStatus;

final class FakeEArcNativeWrapper implements HdmiEarcController.EArcNativeWrapper {
    private static final String TAG = "FakeEArcNativeWrapper";

    private boolean mIsEArcEnabled = true;

    @Override
    public boolean nativeInit() {
        return true;
    }

    @Override
    public void nativeSetEArcEnabled(boolean enabled) {
        mIsEArcEnabled = enabled;
    }

    @Override
    public boolean nativeIsEArcEnabled() {
        return mIsEArcEnabled;
    }

    @Override
    public void nativeSetCallback(HdmiEarcController.EarcAidlCallback callback) {
    }

    @Override
    public byte nativeGetState(int portId) {
        return IEArcStatus.STATUS_IDLE;
    }

    @Override
    public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
        return new byte[] {};
    }
}
Loading