diff options
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | api/current.txt | 24 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 8 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 13 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/HdmiCecClient.java | 119 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/HdmiCecManager.java | 68 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/IHdmiCecListener.aidl | 29 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/IHdmiCecService.aidl | 40 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecDevice.java | 230 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java | 129 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java | 35 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecService.java | 383 | ||||
-rw-r--r-- | services/core/jni/Android.mk | 1 | ||||
-rw-r--r-- | services/core/jni/com_android_server_hdmi_HdmiCecService.cpp | 756 | ||||
-rw-r--r-- | services/core/jni/onload.cpp | 3 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 8 |
16 files changed, 5 insertions, 1843 deletions
@@ -147,8 +147,6 @@ LOCAL_SRC_FILES += \ core/java/android/hardware/ISerialManager.aidl \ core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/display/IDisplayManagerCallback.aidl \ - core/java/android/hardware/hdmi/IHdmiCecListener.aidl \ - core/java/android/hardware/hdmi/IHdmiCecService.aidl \ core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \ core/java/android/hardware/hdmi/IHdmiControlService.aidl \ core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \ diff --git a/api/current.txt b/api/current.txt index 8731a0e..dbc0945 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7003,8 +7003,13 @@ package android.content { field public static final java.lang.String DISPLAY_SERVICE = "display"; field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; +<<<<<<< HEAD field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec"; +||||||| merged common ancestors + field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec"; +======= +>>>>>>> 4ce22057e48f7ca176057a9410bfcbbfd913cfde field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -12922,21 +12927,6 @@ package android.hardware.hdmi { field public static final int UNKNOWN_VENDOR_ID = 16777215; // 0xffffff } - public final class HdmiCecClient { - method public boolean isTvOn(); - method public void sendActiveSource(); - method public void sendGiveDevicePowerStatus(int); - method public void sendImageViewOn(); - method public void sendInactiveSource(); - method public void sendTextViewOn(); - } - - public static abstract class HdmiCecClient.Listener { - ctor public HdmiCecClient.Listener(); - method public void onCableStatusChanged(boolean); - method public void onMessageReceived(android.hardware.hdmi.HdmiCecMessage); - } - public final class HdmiCecDeviceInfo implements android.os.Parcelable { method public int describeContents(); method public int getDeviceType(); @@ -12948,10 +12938,6 @@ package android.hardware.hdmi { field public static final android.os.Parcelable.Creator CREATOR; } - public final class HdmiCecManager { - method public android.hardware.hdmi.HdmiCecClient getClient(int, android.hardware.hdmi.HdmiCecClient.Listener); - } - public final class HdmiCecMessage implements android.os.Parcelable { ctor public HdmiCecMessage(int, int, int, byte[]); method public int describeContents(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index e03224c..ad506e4 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -59,9 +59,7 @@ import android.hardware.ConsumerIrManager; import android.hardware.ISerialManager; import android.hardware.SerialManager; import android.hardware.SystemSensorManager; -import android.hardware.hdmi.HdmiCecManager; import android.hardware.hdmi.HdmiControlManager; -import android.hardware.hdmi.IHdmiCecService; import android.hardware.hdmi.IHdmiControlService; import android.hardware.camera2.CameraManager; import android.hardware.display.DisplayManager; @@ -386,12 +384,6 @@ class ContextImpl extends Context { return new BluetoothManager(ctx); }}); - registerService(HDMI_CEC_SERVICE, new StaticServiceFetcher() { - public Object createStaticService() { - IBinder b = ServiceManager.getService(HDMI_CEC_SERVICE); - return new HdmiCecManager(IHdmiCecService.Stub.asInterface(b)); - }}); - registerService(HDMI_CONTROL_SERVICE, new StaticServiceFetcher() { public Object createStaticService() { IBinder b = ServiceManager.getService(HDMI_CONTROL_SERVICE); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a040efb..1cf661f 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2148,8 +2148,6 @@ public abstract class Context { * @see android.app.SearchManager * @see #SENSOR_SERVICE * @see android.hardware.SensorManager - * @see #HDMI_CEC_SERVICE - * @see android.hardware.hdmi.HdmiCecManager * @see #STORAGE_SERVICE * @see android.os.storage.StorageManager * @see #VIBRATOR_SERVICE @@ -2637,17 +2635,6 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.hardware.hdmi.HdmiCecManager} for controlling and managing - * HDMI-CEC protocol. - * - * @see #getSystemService - * @see android.hardware.hdmi.HdmiCecManager - */ - // TODO: Remove this once HdmiControlService is ready. - public static final String HDMI_CEC_SERVICE = "hdmi_cec"; - - /** - * Use with {@link #getSystemService} to retrieve a * {@link android.hardware.hdmi.HdmiControlManager} for controlling and managing * HDMI-CEC protocol. * diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java deleted file mode 100644 index dcb3624..0000000 --- a/core/java/android/hardware/hdmi/HdmiCecClient.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 android.hardware.hdmi; - -import android.os.IBinder; -import android.os.RemoteException; - -import android.util.Log; - -/** - * HdmiCecClient is used to control HDMI-CEC logical device instance in the system. - * It is connected to actual hardware part via HdmiCecService. It provides with methods - * to send CEC messages to other device on the bus, and listener that allows to receive - * incoming messages to the device. - */ -public final class HdmiCecClient { - private static final String TAG = "HdmiCecClient"; - - private final IHdmiCecService mService; - private final IBinder mBinder; - - /** - * Listener used by the client to get the incoming messages. - */ - public static abstract class Listener { - /** - * Called when CEC message arrives. Override this method to receive the incoming - * CEC messages from other device on the bus. - * - * @param message {@link HdmiCecMessage} object - */ - public void onMessageReceived(HdmiCecMessage message) { } - - /** - * Called when hotplug event occurs. Override this method to receive the events. - * - * @param connected true if the cable is connected; otherwise false. - */ - public void onCableStatusChanged(boolean connected) { } - } - - // Private constructor. - private HdmiCecClient(IHdmiCecService service, IBinder b) { - mService = service; - mBinder = b; - } - - // Factory method for HdmiCecClient. - // Declared package-private. Accessed by HdmiCecManager only. - static HdmiCecClient create(IHdmiCecService service, IBinder b) { - return new HdmiCecClient(service, b); - } - - /** - * Send <Active Source> message. - */ - public void sendActiveSource() { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - } - - /** - * Send <Inactive Source> message. - */ - public void sendInactiveSource() { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - } - - /** - * Send <Text View On> message. - */ - public void sendTextViewOn() { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - } - - /** - * Send <Image View On> message. - */ - public void sendImageViewOn() { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - } - - /** - * Send <Give Device Power Status> message. - * - * @param address logical address of the device to send the message to, such as - * {@link HdmiCec#ADDR_TV}. - */ - public void sendGiveDevicePowerStatus(int address) { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - } - - /** - * Returns true if the TV or attached display is powered on. - * <p> - * The result of this method is only meaningful on playback devices (where the device - * type is {@link HdmiCec#DEVICE_PLAYBACK}). - * </p> - * - * @return true if TV is on; otherwise false. - */ - public boolean isTvOn() { - Log.w(TAG, "In transition to HdmiControlManager. Will not work."); - return true; - } -} diff --git a/core/java/android/hardware/hdmi/HdmiCecManager.java b/core/java/android/hardware/hdmi/HdmiCecManager.java deleted file mode 100644 index 03c46d8..0000000 --- a/core/java/android/hardware/hdmi/HdmiCecManager.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 android.hardware.hdmi; - -import android.os.IBinder; -import android.os.RemoteException; - -/** - * The HdmiCecManager class is used to provide an HdmiCecClient instance, - * get various information on HDMI ports configuration. It is connected to actual hardware - * via HdmiCecService. - */ -public final class HdmiCecManager { - private final IHdmiCecService mService; - - /** - * @hide - hide this constructor because it has a parameter of type IHdmiCecService, - * which is a system private class. The right way to create an instance of this class - * is using the factory Context.getSystemService. - */ - public HdmiCecManager(IHdmiCecService service) { - mService = service; - } - - /** - * Provide the HdmiCecClient instance of the given type. It also registers the listener - * for client to get the events coming to the device. - * - * @param type type of the HDMI-CEC logical device - * @param listener listener to be called - * @return {@link HdmiCecClient} instance. {@code null} on failure. - */ - public HdmiCecClient getClient(int type, HdmiCecClient.Listener listener) { - return HdmiCecClient.create(mService, null); - } - - private IHdmiCecListener getListenerWrapper(final HdmiCecClient.Listener listener) { - // TODO: The message/events are not yet forwarded to client since it is not clearly - // defined as to how/who to handle them. Revisit it once the decision is - // made on what messages will have to reach the clients, what will be - // handled by service/manager. - return new IHdmiCecListener.Stub() { - @Override - public void onMessageReceived(HdmiCecMessage message) { - // Do nothing. - } - - @Override - public void onCableStatusChanged(boolean connected) { - // Do nothing. - } - }; - } -} diff --git a/core/java/android/hardware/hdmi/IHdmiCecListener.aidl b/core/java/android/hardware/hdmi/IHdmiCecListener.aidl deleted file mode 100644 index d281ce6..0000000 --- a/core/java/android/hardware/hdmi/IHdmiCecListener.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 android.hardware.hdmi; - -import android.hardware.hdmi.HdmiCecMessage; - -/** - * Interface definition for HdmiCecService to do interprocess communcation. - * - * @hide - */ -oneway interface IHdmiCecListener { - void onMessageReceived(in HdmiCecMessage message); - void onCableStatusChanged(in boolean connected); -} diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl deleted file mode 100644 index ecdd345..0000000 --- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 android.hardware.hdmi; - -import android.hardware.hdmi.HdmiCecMessage; -import android.hardware.hdmi.IHdmiCecListener; -import android.os.IBinder; - -/** - * Binder interface that components running in the appplication process - * will use to enable HDMI-CEC protocol exchange with other devices. - * - * @hide - */ -interface IHdmiCecService { - IBinder allocateLogicalDevice(int type, IHdmiCecListener listener); - void removeServiceListener(IBinder b, IHdmiCecListener listener); - void sendActiveSource(IBinder b); - void sendInactiveSource(IBinder b); - void sendImageViewOn(IBinder b); - void sendTextViewOn(IBinder b); - void sendGiveDevicePowerStatus(IBinder b, int address); - boolean isTvOn(IBinder b); - void sendMessage(IBinder b, in HdmiCecMessage message); -} - diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java deleted file mode 100644 index baae1d9..0000000 --- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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; -import android.hardware.hdmi.HdmiCecMessage; -import android.hardware.hdmi.IHdmiCecListener; -import android.os.Binder; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -/** - * HdmiCecDevice class represents a CEC logical device characterized - * by its device type. It is a superclass of those serving concrete device type. - * Currently we're interested in playback(one of sources), display(sink) device type - * only. The support for the other types like recorder, audio system will come later. - * - * <p>A physical device can contain the functions of - * more than one logical device, in which case it should create - * as many logical devices as necessary. - * - * <p>Note that if a physical device has multiple instances of a particular - * functionality, it should advertize only one instance. For instance, if - * a device has multiple tuners, it should only expose one for control - * via CEC. In this case, it is up to the device itself to manage multiple tuners. - * - * <p>The version of HDMI-CEC protocol supported in this class is 1.3a. - * - * <p>Declared as package-private, accessed by HdmiCecService only. - */ -abstract class HdmiCecDevice { - private static final String TAG = "HdmiCecDevice"; - - private final int mType; - - // List of listeners to the message/event coming to the device. - private final List<IHdmiCecListener> mListeners = new ArrayList<IHdmiCecListener>(); - private final Binder mBinder = new Binder(); - private final HdmiCecService mService; - - private boolean mIsActiveSource; - - /** - * Factory method that creates HdmiCecDevice instance to the device type. - */ - public static HdmiCecDevice create(HdmiCecService service, int type) { - if (type == HdmiCec.DEVICE_PLAYBACK) { - return new HdmiCecDevicePlayback(service, type); - } else if (type == HdmiCec.DEVICE_TV) { - return new HdmiCecDeviceTv(service, type); - } - return null; - } - - /** - * Constructor. - */ - public HdmiCecDevice(HdmiCecService service, int type) { - mService = service; - mType = type; - mIsActiveSource = false; - } - - /** - * Called right after the class is instantiated. This method can be used to - * implement any initialization tasks for the instance. - */ - abstract public void initialize(); - - /** - * Return the binder token that identifies this instance. - */ - public Binder getToken() { - return mBinder; - } - - /** - * Return the service instance. - */ - public HdmiCecService getService() { - return mService; - } - - /** - * Return the type of this device. - */ - public int getType() { - return mType; - } - - /** - * Register a listener to be invoked when events occur. - * - * @param listener the listern that will run - */ - public void addListener(IHdmiCecListener listener) { - mListeners.add(listener); - } - - /** - * Remove the listener that was previously registered. - * - * @param listener IHdmiCecListener instance to be removed - */ - public void removeListener(IHdmiCecListener listener) { - mListeners.remove(listener); - } - - /** - * Indicate if the device has listeners. - * - * @return true if there are listener instances for this device - */ - public boolean hasListener() { - return !mListeners.isEmpty(); - } - - /** - * Handle HDMI-CEC message coming to the device by invoking the registered - * listeners. - */ - public void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) { - if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE) { - mIsActiveSource = false; - } - - if (mListeners.size() == 0) { - return; - } - HdmiCecMessage message = new HdmiCecMessage(srcAddress, dstAddress, opcode, params); - for (IHdmiCecListener listener : mListeners) { - try { - listener.onMessageReceived(message); - } catch (RemoteException e) { - Log.e(TAG, "listener.onMessageReceived failed."); - } - } - } - - public void handleHotplug(boolean connected) { - for (IHdmiCecListener listener : mListeners) { - try { - listener.onCableStatusChanged(connected); - } catch (RemoteException e) { - Log.e(TAG, "listener.onCableStatusChanged failed."); - } - } - } - - /** - * Return the active status of the device. - * - * @return true if the device is the active source among the connected - * HDMI-CEC-enabled devices; otherwise false. - */ - public boolean isActiveSource() { - return mIsActiveSource; - } - - /** - * Update the active source state of the device. - */ - public void setIsActiveSource(boolean state) { - mIsActiveSource = state; - } - - /** - * Send <Active Source> command. The default implementation does nothing. Should be - * overriden by subclass. - */ - public void sendActiveSource(int physicalAddress) { - logWarning("<Active Source> not valid for the device type: " + mType - + " address:" + physicalAddress); - } - - /** - * Send <Inactive Source> command. The default implementation does nothing. Should be - * overriden by subclass. - */ - public void sendInactiveSource(int physicalAddress) { - logWarning("<Inactive Source> not valid for the device type: " + mType - + " address:" + physicalAddress); - } - - /** - * Send <Image View On> command. The default implementation does nothing. Should be - * overriden by subclass. - */ - public void sendImageViewOn() { - logWarning("<Image View On> not valid for the device type: " + mType); - } - - /** - * Send <Text View On> command. The default implementation does nothing. Should be - * overriden by subclass. - */ - public void sendTextViewOn() { - logWarning("<Text View On> not valid for the device type: " + mType); - } - - /** - * Check if the connected sink device is in powered-on state. The default implementation - * simply returns false. Should be overriden by subclass to report the correct state. - */ - public boolean isSinkDeviceOn() { - logWarning("isSinkDeviceOn() not valid for the device type: " + mType); - return false; - } - - private void logWarning(String msg) { - Log.w(TAG, msg); - } -} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java deleted file mode 100644 index f8cf11d..0000000 --- a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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; - -/** - * Class for the logical device of playback type. Devices such as DVD/Blueray player - * that support 'playback' feature are classified as playback device. It is common - * that they don't have built-in display, therefore need to talk, stream their contents - * to TV/display device which is connected through HDMI cable. - * - * <p>It closely monitors the status of display device (other devices can be of interest - * too, but with much less priority), declares itself as 'active source' to have - * display show its output, switch the source state as ordered by display that may be - * talking to many other devices connected to it. It also receives commands from display - * such as remote control signal, standby, status report, playback mode. - * - * <p>Declared as package-private, accessed by HdmiCecService only. - */ -final class HdmiCecDevicePlayback extends HdmiCecDevice { - private static final String TAG = "HdmiCecDevicePlayback"; - - private int mSinkDevicePowerStatus; - - /** - * Constructor. - */ - public HdmiCecDevicePlayback(HdmiCecService service, int type) { - super(service, type); - mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN; - } - - @Override - public void initialize() { - // Playback device tries to obtain the power status of TV/display when created, - // and maintains it all through its lifecycle. CEC spec says there is - // a maximum 1 second response time. Therefore it should be kept in mind - // that there can be as much amount of period of time the power status - // of the display remains unknown after the query is sent out. - queryTvPowerStatus(); - } - - private void queryTvPowerStatus() { - getService().sendMessage(getType(), HdmiCec.ADDR_TV, - HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, HdmiCecService.EMPTY_PARAM); - } - - @Override - public void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) { - // Updates power status of display. The cases are: - // 1) Response for the queried power status request arrives. Update the status. - // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going - // into standby mode too. - if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) { - mSinkDevicePowerStatus = params[0]; - } else if (srcAddress == HdmiCec.ADDR_TV) { - if (opcode == HdmiCec.MESSAGE_STANDBY) { - mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY; - } - } - super.handleMessage(srcAddress, dstAddress, opcode, params); - } - - @Override - public void handleHotplug(boolean connected) { - // If cable get disconnected sink device becomes unreachable. Switch the status - // to unknown, and query the status once the cable gets connected back. - if (!connected) { - mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN; - } else { - queryTvPowerStatus(); - } - super.handleHotplug(connected); - } - - @Override - public boolean isSinkDeviceOn() { - return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON; - } - - @Override - public void sendActiveSource(int physicalAddress) { - setIsActiveSource(true); - byte[] param = new byte[] { - (byte) ((physicalAddress >> 8) & 0xff), - (byte) (physicalAddress & 0xff) - }; - getService().sendMessage(getType(), HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE, - param); - } - - @Override - public void sendInactiveSource(int physicalAddress) { - setIsActiveSource(false); - byte[] param = new byte[] { - (byte) ((physicalAddress >> 8) & 0xff), - (byte) (physicalAddress & 0xff) - }; - getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_INACTIVE_SOURCE, - param); - } - - @Override - public void sendImageViewOn() { - getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_IMAGE_VIEW_ON, - HdmiCecService.EMPTY_PARAM); - } - - @Override - public void sendTextViewOn() { - getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_TEXT_VIEW_ON, - HdmiCecService.EMPTY_PARAM); - } -} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java deleted file mode 100644 index 09ff3ca..0000000 --- a/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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; - -/** - * Class for logical device of TV type. - */ -final class HdmiCecDeviceTv extends HdmiCecDevice { - private static final String TAG = "HdmiCecDeviceTv"; - - /** - * Constructor. - */ - public HdmiCecDeviceTv(HdmiCecService service, int type) { - super(service, type); - } - - public void initialize() { - // TODO: Do the initialization task for TV device here. - } -} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java deleted file mode 100644 index 98dc72f..0000000 --- a/services/core/java/com/android/server/hdmi/HdmiCecService.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * 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.content.Context; -import android.content.pm.PackageManager; -import android.hardware.hdmi.HdmiCec; -import android.hardware.hdmi.HdmiCecMessage; -import android.hardware.hdmi.IHdmiCecListener; -import android.hardware.hdmi.IHdmiCecService; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; - -import com.android.server.SystemService; -import libcore.util.EmptyArray; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Locale; - -/** - * Provides a service for sending and processing HDMI-CEC messages, and providing - * the information on HDMI settings in general. - */ -public final class HdmiCecService extends SystemService { - private static final String TAG = "HdmiCecService"; - - // Maintains the allocated logical devices. Device type, not logical address, - // is used for key as logical address is likely to change over time while - // device type is permanent. Type-address mapping is maintained only at - // native level. - private final SparseArray<HdmiCecDevice> mLogicalDevices = new SparseArray<HdmiCecDevice>(); - - // List of IBinder.DeathRecipient instances to handle dead IHdmiCecListener - // objects. - private final ArrayList<ListenerRecord> mListenerRecords = new ArrayList<ListenerRecord>(); - - // Used to synchronize the access to the service. - private final Object mLock = new Object(); - - // Stores the pointer to the native implementation of the service that - // interacts with HAL. - private long mNativePtr; - - private static final String PERMISSION = "android.permission.HDMI_CEC"; - - static final byte[] EMPTY_PARAM = EmptyArray.BYTE; - - public HdmiCecService(Context context) { - super(context); - } - - private static native long nativeInit(HdmiCecService service); - - @Override - public void onStart() { - // Stop publishing the service. Soon to be deprecated. - Log.w(TAG, "In transition to HdmiControlService. May not work."); - } - - /** - * Called by native when an HDMI-CEC message arrived. Invokes the registered - * listeners to handle the message. - */ - private void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) { - // TODO: Messages like <Standby> may not need be passed to listener - // but better be handled in service by turning off the screen - // or putting the device into suspend mode. List up such messages - // and handle them here. - synchronized (mLock) { - if (dstAddress == HdmiCec.ADDR_BROADCAST) { - for (int i = 0; i < mLogicalDevices.size(); ++i) { - mLogicalDevices.valueAt(i).handleMessage(srcAddress, dstAddress, opcode, - params); - } - } else { - int type = HdmiCec.getTypeFromAddress(dstAddress); - HdmiCecDevice device = mLogicalDevices.get(type); - if (device == null) { - Log.w(TAG, "logical device not found. type: " + type); - return; - } - device.handleMessage(srcAddress, dstAddress, opcode, params); - } - } - } - - /** - * Called by native when internal HDMI hotplug event occurs. Invokes the registered - * listeners to handle the event. - */ - private void handleHotplug(boolean connected) { - synchronized(mLock) { - for (int i = 0; i < mLogicalDevices.size(); ++i) { - mLogicalDevices.valueAt(i).handleHotplug(connected); - } - } - } - - /** - * Called by native when it needs to know whether we have an active source. - * The native part uses the return value to respond to <Request Active - * Source >. - * - * @return type of the device which is active; DEVICE_INACTIVE if there is - * no active logical device in the system. - */ - private int getActiveSource() { - synchronized(mLock) { - for (int i = 0; i < mLogicalDevices.size(); ++i) { - if (mLogicalDevices.valueAt(i).isActiveSource()) { - return mLogicalDevices.keyAt(i); - } - } - } - return HdmiCec.DEVICE_INACTIVE; - } - - /** - * Called by native when a request for the menu language of the device was - * received. The native part uses the return value to generate the message - * <Set Menu Language> in response. The language should be of - * the 3-letter format as defined in ISO/FDIS 639-2. We use system default - * locale. - */ - private String getLanguage(int type) { - return Locale.getDefault().getISO3Language(); - } - - private void enforceAccessPermission() { - getContext().enforceCallingOrSelfPermission(PERMISSION, "HdmiCecService"); - } - - private void dumpInternal(PrintWriter pw) { - pw.println("HdmiCecService (dumpsys hdmi_cec)"); - pw.println(""); - synchronized (mLock) { - for (int i = 0; i < mLogicalDevices.size(); ++i) { - HdmiCecDevice device = mLogicalDevices.valueAt(i); - pw.println("Device: type=" + device.getType() + - ", active=" + device.isActiveSource()); - } - } - } - - // Remove logical device of a given type. - private void removeLogicalDeviceLocked(int type) { - ensureValidType(type); - mLogicalDevices.remove(type); - nativeRemoveLogicalAddress(mNativePtr, type); - } - - private static void ensureValidType(int type) { - if (!HdmiCec.isValidType(type)) { - throw new IllegalArgumentException("invalid type: " + type); - } - } - - // Return the logical device identified by the given binder token. - private HdmiCecDevice getLogicalDeviceLocked(IBinder b) { - for (int i = 0; i < mLogicalDevices.size(); ++i) { - HdmiCecDevice device = mLogicalDevices.valueAt(i); - if (device.getToken() == b) { - return device; - } - } - throw new IllegalArgumentException("Device not found"); - } - - // package-private. Used by HdmiCecDevice and its subclasses only. - void sendMessage(int type, int address, int opcode, byte[] params) { - nativeSendMessage(mNativePtr, type, address, opcode, params); - } - - private void setOsdNameLocked(String name) { - nativeSetOsdName(mNativePtr, name.getBytes(Charset.forName("US-ASCII"))); - } - - private final class ListenerRecord implements IBinder.DeathRecipient { - private final IHdmiCecListener mListener; - private final int mType; - - public ListenerRecord(IHdmiCecListener listener, int type) { - mListener = listener; - mType = type; - } - - @Override - public void binderDied() { - synchronized (mLock) { - mListenerRecords.remove(this); - HdmiCecDevice device = mLogicalDevices.get(mType); - if (device != null) { - device.removeListener(mListener); - if (!device.hasListener()) { - removeLogicalDeviceLocked(mType); - } - } - } - } - } - - private final class BinderService extends IHdmiCecService.Stub { - - @Override - public IBinder allocateLogicalDevice(int type, IHdmiCecListener listener) { - enforceAccessPermission(); - ensureValidType(type); - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - synchronized (mLock) { - HdmiCecDevice device = mLogicalDevices.get(type); - if (device != null) { - Log.v(TAG, "Logical address already allocated. Adding listener only."); - } else { - int address = nativeAllocateLogicalAddress(mNativePtr, type); - if (!HdmiCec.isValidAddress(address)) { - Log.e(TAG, "Logical address was not allocated"); - return null; - } else { - device = HdmiCecDevice.create(HdmiCecService.this, type); - if (device == null) { - Log.e(TAG, "Device type not supported yet."); - return null; - } - device.initialize(); - mLogicalDevices.put(type, device); - } - } - - // Adds the listener and its monitor - ListenerRecord record = new ListenerRecord(listener, type); - try { - listener.asBinder().linkToDeath(record, 0); - } catch (RemoteException e) { - Log.w(TAG, "Listener already died"); - if (!device.hasListener()) { - removeLogicalDeviceLocked(type); - } - return null; - } - mListenerRecords.add(record); - device.addListener(listener); - return device.getToken(); - } - } - - @Override - public void sendActiveSource(IBinder b) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - device.sendActiveSource(nativeGetPhysicalAddress(mNativePtr)); - } - } - - @Override - public void sendInactiveSource(IBinder b) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - device.sendInactiveSource(nativeGetPhysicalAddress(mNativePtr)); - } - } - - @Override - public void sendImageViewOn(IBinder b) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - device.sendImageViewOn(); - } - } - - @Override - public void sendTextViewOn(IBinder b) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - device.sendTextViewOn(); - } - } - - public void sendGiveDevicePowerStatus(IBinder b, int address) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - nativeSendMessage(mNativePtr, device.getType(), address, - HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM); - } - } - - @Override - public boolean isTvOn(IBinder b) { - enforceAccessPermission(); - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - return device.isSinkDeviceOn(); - } - } - - @Override - public void removeServiceListener(IBinder b, IHdmiCecListener listener) { - enforceAccessPermission(); - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - for (ListenerRecord record : mListenerRecords) { - if (record.mType == device.getType() - && record.mListener.asBinder() == listener.asBinder()) { - mListenerRecords.remove(record); - device.removeListener(record.mListener); - if (!device.hasListener()) { - removeLogicalDeviceLocked(record.mType); - } - break; - } - } - } - } - - @Override - public void sendMessage(IBinder b, HdmiCecMessage message) { - enforceAccessPermission(); - if (message == null) { - throw new IllegalArgumentException("message must not be null"); - } - synchronized (mLock) { - HdmiCecDevice device = getLogicalDeviceLocked(b); - nativeSendMessage(mNativePtr, device.getType(), message.getDestination(), - message.getOpcode(), message.getParams()); - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission denial: can't dump HdmiCecService from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " without permission " + android.Manifest.permission.DUMP); - return; - } - final long ident = Binder.clearCallingIdentity(); - try { - dumpInternal(pw); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - private static native int nativeAllocateLogicalAddress(long handler, int deviceType); - private static native void nativeRemoveLogicalAddress(long handler, int deviceType); - private static native void nativeSendMessage(long handler, int deviceType, int destination, - int opcode, byte[] params); - private static native int nativeGetPhysicalAddress(long handler); - private static native void nativeSetOsdName(long handler, byte[] name); -} diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 3cfb45b..db44d3a 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -12,7 +12,6 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ $(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \ - $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecService.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiMhlController.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp deleted file mode 100644 index 1d111a1..0000000 --- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp +++ /dev/null @@ -1,756 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "HdmiCecJni" - -#define LOG_NDEBUG 1 - -#include "ScopedPrimitiveArray.h" - -#include <string> -#include <deque> -#include <map> - -#include <android_runtime/AndroidRuntime.h> -#include <android_runtime/Log.h> -#include <hardware/hdmi_cec.h> - -namespace android { - -static struct { - jmethodID handleMessage; - jmethodID handleHotplug; - jmethodID getActiveSource; - jmethodID getLanguage; -} gHdmiCecServiceClassInfo; - -#ifndef min -#define min(a, b) ((a) > (b) ? (b) : (a)) -#endif - -class HdmiCecHandler { -public: - enum HdmiCecError { - SUCCESS = 0, - FAILED = -1 - }; - - // Data type to hold a CEC message or internal event data. - typedef union { - cec_message_t cec; - hotplug_event_t hotplug; - } queue_item_t; - - // Entry used for message queue. - typedef std::pair<int, const queue_item_t> MessageEntry; - - HdmiCecHandler(hdmi_cec_device_t* device, jobject callbacksObj); - - void initialize(); - - // initialize individual logical device. - cec_logical_address_t initLogicalDevice(cec_device_type_t type); - void releaseLogicalDevice(cec_device_type_t type); - - cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType); - uint16_t getPhysicalAddress(); - cec_device_type_t getDeviceType(cec_logical_address_t addr); - void queueMessage(const MessageEntry& message); - void queueOutgoingMessage(const cec_message_t& message); - void sendReportPhysicalAddress(cec_logical_address_t srcAddr); - void sendActiveSource(cec_logical_address_t srcAddr); - void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr, - int opcode, int reason); - void sendCecVersion(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr, - int version); - void sendDeviceVendorId(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr); - void sendGiveDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr); - void sendSetOsdName(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr, - const char* name, size_t len); - void sendSetMenuLanguage(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr); - - void sendCecMessage(const cec_message_t& message); - void setOsdName(const char* name, size_t len); - -private: - enum { - EVENT_TYPE_RX, - EVENT_TYPE_TX, - EVENT_TYPE_HOTPLUG, - EVENT_TYPE_STANDBY - }; - - /* - * logical address pool for each device type. - */ - static const cec_logical_address_t TV_ADDR_POOL[]; - static const cec_logical_address_t PLAYBACK_ADDR_POOL[]; - static const cec_logical_address_t RECORDER_ADDR_POOL[]; - static const cec_logical_address_t TUNER_ADDR_POOL[]; - - static const unsigned int MAX_BUFFER_SIZE = 256; - static const uint16_t INVALID_PHYSICAL_ADDRESS = 0xFFFF; - - static void onReceived(const hdmi_event_t* event, void* arg); - static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); - - void updatePhysicalAddress(); - void updateLogicalAddress(); - - // Allocate logical address. The CEC standard recommends that we try to use the address - // we have ever used before, in case this is to allocate an address afte the cable is - // connected again. If preferredAddr is given a valid one (not CEC_ADDR_UNREGISTERED), then - // this method checks if the address is available first. If not, it tries other addresses - // int the address pool available for the given type. - cec_logical_address_t allocateLogicalAddress(cec_device_type_t type, - cec_logical_address_t preferredAddr); - - // Send a CEC ping message. Returns true if successful. - bool sendPing(cec_logical_address_t addr); - - // Return the pool of logical addresses that are used for a given device type. - // One of the addresses in the pool will be chosen in the allocation logic. - bool getLogicalAddressPool(cec_device_type_t type, const cec_logical_address_t** addrPool, - size_t* poolSize); - - // Handles the message retrieved from internal message queue. The message can be - // for either rx or tx. - void dispatchMessage(const MessageEntry& message); - void processIncomingMessage(const cec_message_t& msg); - - // Check the message before we pass it up to framework. If true, we proceed. - // otherwise do not propagate it. - bool precheckMessage(const cec_message_t& msg); - - // Propagate the message up to Java layer. - void propagateMessage(const cec_message_t& msg); - void propagateHotplug(bool connected); - - // Handles incoming <Request Active Source> message. If one of logical - // devices is active, it should reply with <Active Source> message. - void handleRequestActiveSource(); - void handleGiveOsdName(const cec_message_t& msg); - void handleGiveDeviceVendorID(const cec_message_t& msg); - void handleGetCECVersion(const cec_message_t& msg); - void handleGetMenuLanguage(const cec_message_t& msg); - - // Internal thread for message queue handler - class HdmiThread : public Thread { - public: - HdmiThread(HdmiCecHandler* hdmiCecHandler, bool canCallJava) : - Thread(canCallJava), - mHdmiCecHandler(hdmiCecHandler) { - } - private: - virtual bool threadLoop() { - ALOGV("HdmiThread started"); - AutoMutex _l(mHdmiCecHandler->mMessageQueueLock); - mHdmiCecHandler->mMessageQueueCondition.wait(mHdmiCecHandler->mMessageQueueLock); - /* Process all messages in the queue */ - while (mHdmiCecHandler->mMessageQueue.size() > 0) { - MessageEntry entry = mHdmiCecHandler->mMessageQueue.front(); - mHdmiCecHandler->dispatchMessage(entry); - } - return true; - } - - HdmiCecHandler* mHdmiCecHandler; - }; - - // device type -> logical address mapping - std::map<cec_device_type_t, cec_logical_address_t> mLogicalDevices; - - hdmi_cec_device_t* mDevice; - jobject mCallbacksObj; - Mutex mLock; - Mutex mMessageQueueLock; - Condition mMessageQueueCondition; - sp<HdmiThread> mMessageQueueHandler; - - std::deque<MessageEntry> mMessageQueue; - uint16_t mPhysicalAddress; - std::string mOsdName; -}; - - const cec_logical_address_t HdmiCecHandler::TV_ADDR_POOL[] = { - CEC_ADDR_TV, - CEC_ADDR_FREE_USE, - }; - - const cec_logical_address_t HdmiCecHandler::PLAYBACK_ADDR_POOL[] = { - CEC_ADDR_PLAYBACK_1, - CEC_ADDR_PLAYBACK_2, - CEC_ADDR_PLAYBACK_3 - }; - - const cec_logical_address_t HdmiCecHandler::RECORDER_ADDR_POOL[] = { - CEC_ADDR_RECORDER_1, - CEC_ADDR_RECORDER_2, - CEC_ADDR_RECORDER_3 - }; - - const cec_logical_address_t HdmiCecHandler::TUNER_ADDR_POOL[] = { - CEC_ADDR_TUNER_1, - CEC_ADDR_TUNER_2, - CEC_ADDR_TUNER_3, - CEC_ADDR_TUNER_4 - }; - -HdmiCecHandler::HdmiCecHandler(hdmi_cec_device_t* device, jobject callbacksObj) : - mDevice(device), - mCallbacksObj(callbacksObj) { -} - -void HdmiCecHandler::initialize() { - mDevice->register_event_callback(mDevice, HdmiCecHandler::onReceived, this); - mMessageQueueHandler = new HdmiThread(this, true /* canCallJava */); - mMessageQueueHandler->run("MessageHandler"); - updatePhysicalAddress(); -} - -uint16_t HdmiCecHandler::getPhysicalAddress() { - return mPhysicalAddress; -} - -cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) { - cec_logical_address addr = allocateLogicalAddress(type, CEC_ADDR_UNREGISTERED); - if (addr != CEC_ADDR_UNREGISTERED && !mDevice->add_logical_address(mDevice, addr)) { - mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr)); - - // Broadcast <Report Physical Address> when a new logical address was allocated to let - // other devices discover the new logical device and its logical - physical address - // association. - sendReportPhysicalAddress(addr); - } - return addr; -} - -void HdmiCecHandler::releaseLogicalDevice(cec_device_type_t type) { - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type); - if (it != mLogicalDevices.end()) { - mLogicalDevices.erase(it); - } - // TODO: remove the address monitored in HAL as well. -} - -cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type) { - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type); - if (it != mLogicalDevices.end()) { - return it->second; - } - return CEC_ADDR_UNREGISTERED; -} - -cec_device_type_t HdmiCecHandler::getDeviceType(cec_logical_address_t addr) { - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); - for (; it != mLogicalDevices.end(); ++it) { - if (it->second == addr) { - return it->first; - } - } - return CEC_DEVICE_INACTIVE; -} - -void HdmiCecHandler::queueMessage(const MessageEntry& entry) { - AutoMutex _l(mMessageQueueLock); - if (mMessageQueue.size() <= MAX_BUFFER_SIZE) { - mMessageQueue.push_back(entry); - mMessageQueueCondition.signal(); - } else { - ALOGW("Queue is full! Message dropped."); - } -} - -void HdmiCecHandler::queueOutgoingMessage(const cec_message_t& message) { - queue_item_t item; - item.cec = message; - MessageEntry entry = std::make_pair(EVENT_TYPE_TX, item); - queueMessage(entry); -} - -void HdmiCecHandler::sendReportPhysicalAddress(cec_logical_address_t addr) { - if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { - ALOGE("Invalid physical address."); - return; - } - cec_device_type_t deviceType = getDeviceType(addr); - if (deviceType == CEC_DEVICE_INACTIVE) { - ALOGE("Invalid logical address: %d", addr); - return; - } - - cec_message_t msg; - msg.initiator = addr; - msg.destination = CEC_ADDR_BROADCAST; - msg.length = 4; - msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS; - msg.body[1] = (mPhysicalAddress >> 8) & 0xff; - msg.body[2] = mPhysicalAddress & 0xff; - msg.body[3] = deviceType; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendActiveSource(cec_logical_address_t srcAddr) { - if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { - ALOGE("Error getting physical address."); - return; - } - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = CEC_ADDR_BROADCAST; - msg.length = 3; - msg.body[0] = CEC_MESSAGE_ACTIVE_SOURCE; - msg.body[1] = (mPhysicalAddress >> 8) & 0xff; - msg.body[2] = mPhysicalAddress & 0xff; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendFeatureAbort(cec_logical_address_t srcAddr, - cec_logical_address_t dstAddr, int opcode, int reason) { - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.length = 3; - msg.body[0] = CEC_MESSAGE_FEATURE_ABORT; - msg.body[1] = opcode; - msg.body[2] = reason; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendCecVersion(cec_logical_address_t srcAddr, - cec_logical_address_t dstAddr, int version) { - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.length = 2; - msg.body[0] = CEC_MESSAGE_CEC_VERSION; - msg.body[1] = version; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendGiveDeviceVendorID(cec_logical_address_t srcAddr, - cec_logical_address_t dstAddr) { - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.length = 1; - msg.body[0] = CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendDeviceVendorId(cec_logical_address_t srcAddr, - cec_logical_address_t dstAddr) { - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.length = 4; - msg.body[0] = CEC_MESSAGE_DEVICE_VENDOR_ID; - uint32_t vendor_id; - mDevice->get_vendor_id(mDevice, &vendor_id); - msg.body[1] = (vendor_id >> 16) & 0xff; - msg.body[2] = (vendor_id >> 8) & 0xff; - msg.body[3] = vendor_id & 0xff; - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendSetOsdName(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr, - const char* name, size_t len) { - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.body[0] = CEC_MESSAGE_SET_OSD_NAME; - msg.length = min(len + 1, CEC_MESSAGE_BODY_MAX_LENGTH); - std::memcpy(msg.body + 1, name, msg.length - 1); - queueOutgoingMessage(msg); -} - -void HdmiCecHandler::sendSetMenuLanguage(cec_logical_address_t srcAddr, - cec_logical_address_t dstAddr) { - char lang[4]; // buffer for 3-letter language code - JNIEnv* env = AndroidRuntime::getJNIEnv(); - jstring res = (jstring) env->CallObjectMethod(mCallbacksObj, - gHdmiCecServiceClassInfo.getLanguage, - getDeviceType(srcAddr)); - const char *clang = env->GetStringUTFChars(res, NULL); - strlcpy(lang, clang, sizeof(lang)); - env->ReleaseStringUTFChars(res, clang); - - cec_message_t msg; - msg.initiator = srcAddr; - msg.destination = dstAddr; - msg.length = 4; // opcode (1) + language code (3) - msg.body[0] = CEC_MESSAGE_SET_MENU_LANGUAGE; - std::memcpy(msg.body + 1, lang, 3); - queueOutgoingMessage(msg); - checkAndClearExceptionFromCallback(env, __FUNCTION__); -} - -void HdmiCecHandler::sendCecMessage(const cec_message_t& message) { - AutoMutex _l(mLock); - ALOGV("sendCecMessage"); - mDevice->send_message(mDevice, &message); -} - -void HdmiCecHandler::setOsdName(const char* name, size_t len) { - mOsdName.assign(name, min(len, CEC_MESSAGE_BODY_MAX_LENGTH - 1)); -} - -// static -void HdmiCecHandler::onReceived(const hdmi_event_t* event, void* arg) { - HdmiCecHandler* handler = static_cast<HdmiCecHandler*>(arg); - if (handler == NULL) { - return; - } - queue_item_t item; - if (event->type == HDMI_EVENT_CEC_MESSAGE) { - item.cec = event->cec; - MessageEntry entry = std::make_pair<int, const queue_item_t>(EVENT_TYPE_RX, item); - handler->queueMessage(entry); - } else if (event->type == HDMI_EVENT_HOT_PLUG) { - item.hotplug = event->hotplug; - MessageEntry entry = std::make_pair<int, const queue_item_t>(EVENT_TYPE_HOTPLUG, item); - handler->queueMessage(entry); - } -} - -// static -void HdmiCecHandler::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { - if (env->ExceptionCheck()) { - ALOGE("An exception was thrown by callback '%s'.", methodName); - LOGE_EX(env); - env->ExceptionClear(); - } -} - -void HdmiCecHandler::updatePhysicalAddress() { - uint16_t addr; - if (!mDevice->get_physical_address(mDevice, &addr)) { - mPhysicalAddress = addr; - } else { - mPhysicalAddress = INVALID_PHYSICAL_ADDRESS; - } -} - -void HdmiCecHandler::updateLogicalAddress() { - mDevice->clear_logical_address(mDevice); - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); - for (; it != mLogicalDevices.end(); ++it) { - cec_logical_address_t addr; - cec_logical_address_t preferredAddr = it->second; - cec_device_type_t deviceType = it->first; - addr = allocateLogicalAddress(deviceType, preferredAddr); - if (!mDevice->add_logical_address(mDevice, addr)) { - it->second = addr; - } else { - it->second = CEC_ADDR_UNREGISTERED; - } - } -} - -cec_logical_address_t HdmiCecHandler::allocateLogicalAddress(cec_device_type_t type, - cec_logical_address_t preferredAddr) { - const cec_logical_address_t* addrPool; - size_t poolSize; - if (getLogicalAddressPool(type, &addrPool, &poolSize) < 0) { - return CEC_ADDR_UNREGISTERED; - } - unsigned start = 0; - - // Find the index of preferred address in the pool. If not found, the start - // position will be 0. This happens when the passed preferredAddr is set to - // CEC_ADDR_UNREGISTERED, meaning that no preferred address is given. - for (unsigned i = 0; i < poolSize; i++) { - if (addrPool[i] == preferredAddr) { - start = i; - break; - } - } - for (unsigned i = 0; i < poolSize; i++) { - cec_logical_address_t addr = addrPool[(start + i) % poolSize]; - if (!sendPing(addr)) { - // Failure in pinging means the address is available, not taken by any device. - ALOGV("Logical Address Allocation success: %d", addr); - return addr; - } - } - ALOGE("Logical Address Allocation failed"); - return CEC_ADDR_UNREGISTERED; -} - -bool HdmiCecHandler::sendPing(cec_logical_address addr) { - cec_message_t msg; - msg.initiator = msg.destination = addr; - msg.length = 0; - return !mDevice->send_message(mDevice, &msg); - -} - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -bool HdmiCecHandler::getLogicalAddressPool(cec_device_type_t deviceType, - const cec_logical_address_t** addrPool, size_t* poolSize) { - switch (deviceType) { - case CEC_DEVICE_TV: - *addrPool = TV_ADDR_POOL; - *poolSize = ARRAY_SIZE(TV_ADDR_POOL); - break; - case CEC_DEVICE_RECORDER: - *addrPool = RECORDER_ADDR_POOL; - *poolSize = ARRAY_SIZE(RECORDER_ADDR_POOL); - break; - case CEC_DEVICE_TUNER: - *addrPool = TUNER_ADDR_POOL; - *poolSize = ARRAY_SIZE(TUNER_ADDR_POOL); - break; - case CEC_DEVICE_PLAYBACK: - *addrPool = PLAYBACK_ADDR_POOL; - *poolSize = ARRAY_SIZE(PLAYBACK_ADDR_POOL); - break; - default: - ALOGE("Unsupported device type: %d", deviceType); - return false; - } - return true; -} - -#undef ARRAY_SIZE - -void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) { - int type = entry.first; - mMessageQueueLock.unlock(); - if (type == EVENT_TYPE_RX) { - mMessageQueue.pop_front(); - processIncomingMessage(entry.second.cec); - } else if (type == EVENT_TYPE_TX) { - sendCecMessage(entry.second.cec); - mMessageQueue.pop_front(); - } else if (type == EVENT_TYPE_HOTPLUG) { - mMessageQueue.pop_front(); - bool connected = entry.second.hotplug.connected; - if (connected) { - updatePhysicalAddress(); - updateLogicalAddress(); - } - propagateHotplug(connected); - } - mMessageQueueLock.lock(); -} - -void HdmiCecHandler::processIncomingMessage(const cec_message_t& msg) { - int opcode = msg.body[0]; - if (opcode == CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS) { - sendReportPhysicalAddress(msg.destination); - } else if (opcode == CEC_MESSAGE_REQUEST_ACTIVE_SOURCE) { - handleRequestActiveSource(); - } else if (opcode == CEC_MESSAGE_GIVE_OSD_NAME) { - handleGiveOsdName(msg); - } else if (opcode == CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID) { - handleGiveDeviceVendorID(msg); - } else if (opcode == CEC_MESSAGE_GET_CEC_VERSION) { - handleGetCECVersion(msg); - } else if (opcode == CEC_MESSAGE_GET_MENU_LANGUAGE) { - handleGetMenuLanguage(msg); - } else if (opcode == CEC_MESSAGE_ABORT) { - // Compliance testing requires that abort message be responded with feature abort. - sendFeatureAbort(msg.destination, msg.initiator, msg.body[0], ABORT_REFUSED); - } else { - if (precheckMessage(msg)) { - propagateMessage(msg); - } - } -} - -bool HdmiCecHandler::precheckMessage(const cec_message_t& msg) { - // Check if this is the broadcast message coming to itself, which need not be passed - // back to framework. This happens because CEC spec specifies that a physical device - // may host multiple logical devices. A broadcast message sent by one of them therefore - // should be able to reach the others by the loopback mechanism. - // - // Currently we don't deal with multiple logical devices, so this is not necessary. - // It should be revisited once we support hosting multiple logical devices. - int opcode = msg.body[0]; - if (msg.destination == CEC_ADDR_BROADCAST && - (opcode == CEC_MESSAGE_ACTIVE_SOURCE || - opcode == CEC_MESSAGE_SET_STREAM_PATH || - opcode == CEC_MESSAGE_INACTIVE_SOURCE)) { - uint16_t senderAddr = (msg.body[1] << 8) + msg.body[2]; - if (senderAddr == mPhysicalAddress) { - return false; - } - } - return true; -} - -void HdmiCecHandler::propagateMessage(const cec_message_t& msg) { - int paramLen = msg.length - 1; - jint srcAddr = msg.initiator; - jint dstAddr = msg.destination; - jint opcode = msg.body[0]; - JNIEnv* env = AndroidRuntime::getJNIEnv(); - jbyteArray params = env->NewByteArray(paramLen); - const jbyte* body = reinterpret_cast<const jbyte *>(msg.body + 1); - if (paramLen > 0) { - env->SetByteArrayRegion(params, 0, paramLen, body); - } - env->CallVoidMethod(mCallbacksObj, - gHdmiCecServiceClassInfo.handleMessage, - srcAddr, dstAddr, opcode, params); - env->DeleteLocalRef(params); - checkAndClearExceptionFromCallback(env, __FUNCTION__); -} - -void HdmiCecHandler::propagateHotplug(bool connected) { - JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->CallVoidMethod(mCallbacksObj, - gHdmiCecServiceClassInfo.handleHotplug, - connected); - checkAndClearExceptionFromCallback(env, __FUNCTION__); -} - - -void HdmiCecHandler::handleRequestActiveSource() { - JNIEnv* env = AndroidRuntime::getJNIEnv(); - jint activeDeviceType = env->CallIntMethod(mCallbacksObj, - gHdmiCecServiceClassInfo.getActiveSource); - if (activeDeviceType != CEC_DEVICE_INACTIVE) { - sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType))); - } - checkAndClearExceptionFromCallback(env, __FUNCTION__); -} - -void HdmiCecHandler::handleGiveOsdName(const cec_message_t& msg) { - if (!mOsdName.empty()) { - sendSetOsdName(msg.destination, msg.initiator, mOsdName.c_str(), mOsdName.length()); - } -} - -void HdmiCecHandler::handleGiveDeviceVendorID(const cec_message_t& msg) { - sendDeviceVendorId(msg.destination, msg.initiator); -} - -void HdmiCecHandler::handleGetCECVersion(const cec_message_t& msg) { - int version; - mDevice->get_version(mDevice, &version); - sendCecVersion(msg.destination, msg.initiator, version); -} - -void HdmiCecHandler::handleGetMenuLanguage(const cec_message_t& msg) { - sendSetMenuLanguage(msg.destination, msg.initiator); -} - -//------------------------------------------------------------------------------ - -#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ - var = env->GetMethodID(clazz, methodName, methodDescriptor); \ - LOG_FATAL_IF(! var, "Unable to find method " methodName); - -static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) { - int err; - hw_module_t* module; - err = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID, const_cast<const hw_module_t **>(&module)); - if (err != 0) { - ALOGE("Error acquiring hardware module: %d", err); - return 0; - } - hw_device_t* device; - err = module->methods->open(module, HDMI_CEC_HARDWARE_INTERFACE, &device); - if (err != 0) { - ALOGE("Error opening hardware module: %d", err); - return 0; - } - HdmiCecHandler *handler = new HdmiCecHandler(reinterpret_cast<hdmi_cec_device *>(device), - env->NewGlobalRef(callbacksObj)); - handler->initialize(); - - GET_METHOD_ID(gHdmiCecServiceClassInfo.handleMessage, clazz, - "handleMessage", "(III[B)V"); - GET_METHOD_ID(gHdmiCecServiceClassInfo.handleHotplug, clazz, - "handleHotplug", "(Z)V"); - GET_METHOD_ID(gHdmiCecServiceClassInfo.getActiveSource, clazz, - "getActiveSource", "()I"); - GET_METHOD_ID(gHdmiCecServiceClassInfo.getLanguage, clazz, - "getLanguage", "(I)Ljava/lang/String;"); - - return reinterpret_cast<jlong>(handler); -} - -static void nativeSendMessage(JNIEnv* env, jclass clazz, jlong handlerPtr, jint deviceType, - jint dstAddr, jint opcode, jbyteArray params) { - HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); - cec_logical_address_t srcAddr = handler->getLogicalAddress( - static_cast<cec_device_type_t>(deviceType)); - jsize len = env->GetArrayLength(params); - ScopedByteArrayRO paramsPtr(env, params); - cec_message_t message; - message.initiator = srcAddr; - message.destination = static_cast<cec_logical_address_t>(dstAddr); - message.length = min(len + 1, CEC_MESSAGE_BODY_MAX_LENGTH); - message.body[0] = opcode; - std::memcpy(message.body + 1, paramsPtr.get(), message.length - 1); - handler->sendCecMessage(message); -} - -static jint nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr, - jint deviceType) { - HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); - return handler->initLogicalDevice(static_cast<cec_device_type_t>(deviceType)); -} - -static void nativeRemoveLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr, - jint deviceType) { - HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); - return handler->releaseLogicalDevice(static_cast<cec_device_type_t>(deviceType)); -} - -static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr) { - HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); - return handler->getPhysicalAddress(); -} - -static void nativeSetOsdName(JNIEnv* env, jclass clazz, jlong handlerPtr, jbyteArray name) { - HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr); - jsize len = env->GetArrayLength(name); - if (len > 0) { - ScopedByteArrayRO namePtr(env, name); - handler->setOsdName(reinterpret_cast<const char *>(namePtr.get()), len); - } -} - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - { "nativeInit", "(Lcom/android/server/hdmi/HdmiCecService;)J", - (void *)nativeInit }, - { "nativeSendMessage", "(JIII[B)V", - (void *)nativeSendMessage }, - { "nativeAllocateLogicalAddress", "(JI)I", - (void *)nativeAllocateLogicalAddress }, - { "nativeRemoveLogicalAddress", "(JI)V", - (void *)nativeRemoveLogicalAddress }, - { "nativeGetPhysicalAddress", "(J)I", - (void *)nativeGetPhysicalAddress }, - { "nativeSetOsdName", "(J[B)V", - (void *)nativeSetOsdName }, -}; - -#define CLASS_PATH "com/android/server/hdmi/HdmiCecService" - -int register_android_server_hdmi_HdmiCecService(JNIEnv* env) { - int res = jniRegisterNativeMethods(env, CLASS_PATH, sMethods, NELEM(sMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - return 0; -} - -} /* namespace android */ diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index bfa8286..a302104 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -39,7 +39,6 @@ int register_android_server_location_FlpHardwareProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_dreams_McuHal(JNIEnv* env); int register_android_server_hdmi_HdmiCecController(JNIEnv* env); -int register_android_server_hdmi_HdmiCecService(JNIEnv* env); int register_android_server_hdmi_HdmiMhlController(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); }; @@ -76,8 +75,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) register_android_server_dreams_McuHal(env); register_android_server_BatteryStatsService(env); register_android_server_hdmi_HdmiCecController(env); - // TODO: remove this once replaces HdmiCecService with HdmiControlService. - register_android_server_hdmi_HdmiCecService(env); register_android_server_hdmi_HdmiMhlController(env); register_android_server_tv_TvInputHal(env); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 18ece5b..bb61b81 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -130,8 +130,6 @@ public final class SystemServer { "com.android.server.wifi.passpoint.WifiPasspointService"; private static final String WIFI_P2P_SERVICE_CLASS = "com.android.server.wifi.p2p.WifiP2pService"; - private static final String HDMI_CEC_SERVICE_CLASS = - "com.android.server.hdmi.HdmiCecService"; private static final String ETHERNET_SERVICE_CLASS = "com.android.server.ethernet.EthernetService"; private static final String TASK_SERVICE_CLASS = @@ -954,12 +952,6 @@ public final class SystemServer { } try { - mSystemServiceManager.startService(HDMI_CEC_SERVICE_CLASS); - } catch (Throwable e) { - reportWtf("starting HdmiCec Service", e); - } - - try { mSystemServiceManager.startService(HdmiControlService.class); } catch (Throwable e) { reportWtf("starting HdmiControlService", e); |