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

Commit 3a551cb5 authored by Jungshik Jang's avatar Jungshik Jang Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE: CEC Initialization per device type" into lmp-preview-dev

parents b79ddaf1 47927f75
Loading
Loading
Loading
Loading
+42 −53
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
import android.os.Handler;
import android.util.SparseArray;
import android.util.SparseIntArray;

import libcore.util.EmptyArray;

@@ -75,14 +74,12 @@ final class HdmiCecController {
    // used as key of container.
    private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos =
            new SparseArray<HdmiCecDeviceInfo>();
    // Set-like container for all local devices' logical address.
    // Key and value are same.
    private final SparseIntArray mLocalAddresses = new SparseIntArray();

    // Stores the local CEC devices in the system.
    private final ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();

    // Private constructor.  Use HdmiCecController.create().
    private HdmiCecController() {
        // TODO: Consider restoring the local device addresses from persistent storage
        //       to allocate the same addresses again if possible.
    }

    /**
@@ -96,53 +93,41 @@ final class HdmiCecController {
     *         returns {@code null}.
     */
    static HdmiCecController create(HdmiControlService service) {
        HdmiCecController handler = new HdmiCecController();
        long nativePtr = nativeInit(handler);
        HdmiCecController controller = new HdmiCecController();
        long nativePtr = nativeInit(controller);
        if (nativePtr == 0L) {
            handler = null;
            controller = null;
            return null;
        }

        handler.init(service, nativePtr);
        return handler;
        controller.init(service, nativePtr);
        return controller;
    }

    /**
     * Initialize {@link #mLocalAddresses} by allocating logical addresses for each hosted type.
     *
     * @param deviceTypes local device types
     */
    void initializeLocalDevices(int[] deviceTypes) {
        for (int deviceType : deviceTypes) {
            int preferred = getPreferredAddress(deviceType);
            allocateLogicalAddress(deviceType, preferred, new AllocateLogicalAddressCallback() {
                @Override
                public void onAllocated(int deviceType, int logicalAddress) {
                    addLogicalAddress(logicalAddress);
                }
            });
        }
    private void init(HdmiControlService service, long nativePtr) {
        mService = service;
        mIoHandler = new Handler(service.getServiceLooper());
        mControlHandler = new Handler(service.getServiceLooper());
        mNativePtr = nativePtr;
    }

    /**
     * Get the preferred address for a given type.
     * Perform initialization for each hosted device.
     *
     * @param deviceType logical device type to get the address for
     * @return preferred address; {@link HdmiCec#ADDR_UNREGISTERED} if not available.
     * @param deviceTypes array of device types
     */
    private int getPreferredAddress(int deviceType) {
        // Uses the data restored from persistent memory at boot up if they are available.
        // Otherwise we return UNREGISTERED indicating there is no preferred address.
        // Note that for address SPECIFIC_USE(14), HdmiCec.getTypeFromAddress() returns DEVICE_TV,
        // meaning that we do not support device type video processor yet.
        for (int i = 0; i < mLocalAddresses.size(); ++i) {
            int address = mLocalAddresses.keyAt(i);
            int type = HdmiCec.getTypeFromAddress(address);
            if (type == deviceType) {
                return address;
    void initializeLocalDevices(int[] deviceTypes) {
        for (int type : deviceTypes) {
            HdmiCecLocalDevice device = HdmiCecLocalDevice.create(this, type);
            if (device == null) {
                continue;
            }
            // TODO: Consider restoring the local device addresses from persistent storage
            //       to allocate the same addresses again if possible.
            device.setPreferredAddress(HdmiCec.ADDR_UNREGISTERED);
            mLocalDevices.add(device);
            device.init();
        }
        return HdmiCec.ADDR_UNREGISTERED;
    }

    /**
@@ -310,7 +295,6 @@ final class HdmiCecController {
     */
    int addLogicalAddress(int newLogicalAddress) {
        if (HdmiCec.isValidAddress(newLogicalAddress)) {
            mLocalAddresses.put(newLogicalAddress, newLogicalAddress);
            return nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
        } else {
            return -1;
@@ -325,7 +309,9 @@ final class HdmiCecController {
    void clearLogicalAddress() {
        // TODO: consider to backup logical address so that new logical address
        // allocation can use it as preferred address.
        mLocalAddresses.clear();
        for (HdmiCecLocalDevice device : mLocalDevices) {
            device.clearAddress();
        }
        nativeClearLogicalAddress(mNativePtr);
    }

@@ -367,18 +353,17 @@ final class HdmiCecController {
        mControlHandler.post(runnable);
    }

    private void init(HdmiControlService service, long nativePtr) {
        mService = service;
        mIoHandler = new Handler(service.getServiceLooper());
        mControlHandler = new Handler(service.getServiceLooper());
        mNativePtr = nativePtr;
    }

    private boolean isAcceptableAddress(int address) {
        // Can access command targeting devices available in local device or
        // broadcast command.
        return address == HdmiCec.ADDR_BROADCAST
                || mLocalAddresses.indexOfKey(address) < 0;
        // Can access command targeting devices available in local device or broadcast command.
        if (address == HdmiCec.ADDR_BROADCAST) {
            return true;
        }
        for (HdmiCecLocalDevice device : mLocalDevices) {
            if (device.isAddressOf(address)) {
                return true;
            }
        }
        return false;
    }

    private void onReceiveCommand(HdmiCecMessage message) {
@@ -397,6 +382,10 @@ final class HdmiCecController {
        sendCommand(cecMessage, null);
    }

    void sendCommand(HdmiCecMessage cecMessage) {
        sendCommand(cecMessage, null);
    }

    void sendCommand(final HdmiCecMessage cecMessage,
            final HdmiControlService.SendMessageCallback callback) {
        runOnIoThread(new Runnable() {
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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 com.android.server.hdmi.HdmiCecController.AllocateLogicalAddressCallback;

import android.hardware.hdmi.HdmiCec;

/**
 * Class that models a logical CEC device hosted in this system. Handles initialization,
 * CEC commands that call for actions customized per device type.
 */
abstract class HdmiCecLocalDevice {

    protected final HdmiCecController mController;
    protected final int mDeviceType;
    protected int mAddress;
    protected int mPreferredAddress;

    protected HdmiCecLocalDevice(HdmiCecController controller, int deviceType) {
        mController = controller;
        mDeviceType = deviceType;
        mAddress = HdmiCec.ADDR_UNREGISTERED;
    }

    // Factory method that returns HdmiCecLocalDevice of corresponding type.
    static HdmiCecLocalDevice create(HdmiCecController controller, int deviceType) {
        switch (deviceType) {
        case HdmiCec.DEVICE_TV:
            return new HdmiCecLocalDeviceTv(controller);
        case HdmiCec.DEVICE_PLAYBACK:
            return new HdmiCecLocalDevicePlayback(controller);
        default:
            return null;
        }
    }

    abstract void init();

    protected void allocateAddress(int type) {
        mController.allocateLogicalAddress(type, mPreferredAddress,
                new AllocateLogicalAddressCallback() {
            @Override
            public void onAllocated(int deviceType, int logicalAddress) {
                mAddress = mPreferredAddress = logicalAddress;
                mController.addLogicalAddress(logicalAddress);
            }
        });
    }

    // Returns true if the logical address is same as the argument.
    boolean isAddressOf(int addr) {
        return addr == mAddress;
    }

    // Resets the logical address to unregistered(15), meaning the logical device is invalid.
    void clearAddress() {
        mAddress = HdmiCec.ADDR_UNREGISTERED;
    }

    void setPreferredAddress(int addr) {
        mPreferredAddress = addr;
    }
}
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.hdmi.HdmiCec;

/**
 * Represent a logical device of type Playback residing in Android system.
 */
final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {

    HdmiCecLocalDevicePlayback(HdmiCecController controller) {
        super(controller, HdmiCec.DEVICE_PLAYBACK);
    }

    @Override
    void init() {
        allocateAddress(mDeviceType);
        mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                mAddress, mController.getPhysicalAddress(), mDeviceType));
    }
}
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.hdmi.HdmiCec;

/**
 * Represent a logical device of type TV residing in Android system.
 */
final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {

    HdmiCecLocalDeviceTv(HdmiCecController controller) {
        super(controller, HdmiCec.DEVICE_TV);
    }

    @Override
    void init() {
        allocateAddress(mDeviceType);

        // TODO: vendor-specific initialization here.

        mController.sendCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                mAddress, mController.getPhysicalAddress(), mDeviceType));
        mController.sendCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                mAddress, mController.getVendorId()));

        // TODO: Start routing control action, device discovery action.
    }
}