Merge "Implement skeleton of new HDMI Control Service."

This commit is contained in:
Jungshik Jang
2014-04-25 14:09:17 +00:00
committed by Android (Google) Code Review
6 changed files with 261 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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.");
}
}
}

View File

@@ -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 \

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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);