Merge "Implement skeleton of new HDMI Control Service."
This commit is contained in:
committed by
Android (Google) Code Review
commit
a77f358eed
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
/**
|
||||
* Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
|
||||
* and pass it to CEC HAL so that it sends message to other device. For incoming
|
||||
* message it translates the message and delegates it to proper module.
|
||||
*
|
||||
* <p>It can be created only by {@link HdmiCecController#create}
|
||||
*
|
||||
* <p>Declared as package-private, accessed by {@link HdmiControlService} only.
|
||||
*/
|
||||
class HdmiCecController {
|
||||
private static final String TAG = "HdmiCecController";
|
||||
|
||||
// Handler instance to process synchronous I/O (mainly send) message.
|
||||
private Handler mIoHandler;
|
||||
|
||||
// Handler instance to process various messages coming from other CEC
|
||||
// device or issued by internal state change.
|
||||
private Handler mMessageHandler;
|
||||
|
||||
// Stores the pointer to the native implementation of the service that
|
||||
// interacts with HAL.
|
||||
private long mNativePtr;
|
||||
|
||||
// Private constructor. Use HdmiCecController.create().
|
||||
private HdmiCecController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method to get {@link HdmiCecController}. If it fails to initialize
|
||||
* inner device or has no device it will return {@code null}.
|
||||
*
|
||||
* <p>Declared as package-private, accessed by {@link HdmiControlService} only.
|
||||
*
|
||||
* @param ioLooper a Looper instance to handle IO (mainly send message) operation.
|
||||
* @param messageHandler a message handler that processes a message coming from other
|
||||
* CEC compatible device or callback of internal state change.
|
||||
* @return {@link HdmiCecController} if device is initialized successfully. Otherwise,
|
||||
* returns {@code null}.
|
||||
*/
|
||||
static HdmiCecController create(Looper ioLooper, Handler messageHandler) {
|
||||
HdmiCecController handler = new HdmiCecController();
|
||||
long nativePtr = nativeInit(handler);
|
||||
if (nativePtr == 0L) {
|
||||
handler = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
handler.init(ioLooper, messageHandler, nativePtr);
|
||||
return handler;
|
||||
}
|
||||
|
||||
private void init(Looper ioLooper, Handler messageHandler, long nativePtr) {
|
||||
mIoHandler = new Handler(ioLooper) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
// TODO: Call native sendMessage.
|
||||
}
|
||||
};
|
||||
|
||||
mMessageHandler = messageHandler;
|
||||
mNativePtr = nativePtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by native when an HDMI-CEC message arrived.
|
||||
*/
|
||||
private void handleMessage(int srcAddress, int dstAddres, int opcode, byte[] params) {
|
||||
// TODO: Translate message and delegate it to main message handler.
|
||||
}
|
||||
|
||||
private static native long nativeInit(HdmiCecController handler);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.SystemService;
|
||||
|
||||
/**
|
||||
* Provides a service for sending and processing HDMI control messages,
|
||||
* HDMI-CEC and MHL control command, and providing the information on both standard.
|
||||
*/
|
||||
public final class HdmiControlService extends SystemService {
|
||||
private static final String TAG = "HdmiControlService";
|
||||
|
||||
// A thread to handle synchronous IO of CEC and MHL control service.
|
||||
// Since all of CEC and MHL HAL interfaces processed in short time (< 200ms)
|
||||
// and sparse call it shares a thread to handle IO operations.
|
||||
private final HandlerThread mIoThread = new HandlerThread("Hdmi Control Io Thread");
|
||||
|
||||
// Main handler class to handle incoming message from each controller.
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
// TODO: Add handler for each message type.
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private HdmiCecController mCecController;
|
||||
|
||||
@Nullable
|
||||
private HdmiMhlController mMhlController;
|
||||
|
||||
public HdmiControlService(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mCecController = HdmiCecController.create(mIoThread.getLooper(), mHandler);
|
||||
if (mCecController == null) {
|
||||
Slog.i(TAG, "Device does not support HDMI-CEC.");
|
||||
}
|
||||
|
||||
mMhlController = HdmiMhlController.create(mIoThread.getLooper(), mHandler);
|
||||
if (mMhlController == null) {
|
||||
Slog.i(TAG, "Device does not support MHL-control.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,9 @@ LOCAL_SRC_FILES += \
|
||||
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
|
||||
$(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 \
|
||||
$(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 "HdmiCecControllerJni"
|
||||
|
||||
#define LOG_NDEBUG 1
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android_runtime/Log.h>
|
||||
#include <hardware/hdmi_cec.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
static struct {
|
||||
jmethodID handleMessage;
|
||||
} gHdmiCecControllerClassInfo;
|
||||
|
||||
|
||||
class HdmiCecController {
|
||||
public:
|
||||
HdmiCecController(jobject callbacksObj);
|
||||
|
||||
private:
|
||||
static void onReceived(const hdmi_event_t* event, void* arg);
|
||||
|
||||
jobject mCallbacksObj;
|
||||
};
|
||||
|
||||
HdmiCecController::HdmiCecController(jobject callbacksObj) :
|
||||
mCallbacksObj(callbacksObj) {
|
||||
}
|
||||
|
||||
// static
|
||||
void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) {
|
||||
HdmiCecController* handler = static_cast<HdmiCecController*>(arg);
|
||||
if (handler == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: propagate message to Java layer.
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) {
|
||||
// TODO: initialize hal and pass it to controller if ready.
|
||||
|
||||
HdmiCecController* controller = new HdmiCecController(
|
||||
env->NewGlobalRef(callbacksObj));
|
||||
|
||||
return reinterpret_cast<jlong>(controller);
|
||||
}
|
||||
|
||||
static JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeInit", "(Lcom/android/server/hdmi/HdmiCecController;)J",
|
||||
(void *) nativeInit },
|
||||
};
|
||||
|
||||
#define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
|
||||
|
||||
int register_android_server_hdmi_HdmiCecController(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 */
|
||||
@@ -38,7 +38,9 @@ int register_android_server_location_GpsLocationProvider(JNIEnv* env);
|
||||
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);
|
||||
};
|
||||
|
||||
using namespace android;
|
||||
@@ -72,7 +74,10 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
register_android_server_ConsumerIrService(env);
|
||||
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);
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import com.android.server.clipboard.ClipboardService;
|
||||
import com.android.server.content.ContentService;
|
||||
import com.android.server.display.DisplayManagerService;
|
||||
import com.android.server.dreams.DreamManagerService;
|
||||
import com.android.server.hdmi.HdmiControlService;
|
||||
import com.android.server.input.InputManagerService;
|
||||
import com.android.server.lights.LightsManager;
|
||||
import com.android.server.lights.LightsService;
|
||||
@@ -918,6 +919,12 @@ public final class SystemServer {
|
||||
reportWtf("starting HdmiCec Service", e);
|
||||
}
|
||||
|
||||
try {
|
||||
mSystemServiceManager.startService(HdmiControlService.class);
|
||||
} catch (Throwable e) {
|
||||
reportWtf("starting HdmiControlService", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "TvInputManagerService");
|
||||
mSystemServiceManager.startService(TvInputManagerService.class);
|
||||
|
||||
Reference in New Issue
Block a user