diff options
Diffstat (limited to 'media/lib')
-rw-r--r-- | media/lib/tvremote/Android.mk | 48 | ||||
-rw-r--r-- | media/lib/tvremote/README.txt | 26 | ||||
-rw-r--r-- | media/lib/tvremote/com.android.media.tv.remoteprovider.xml | 20 | ||||
-rw-r--r-- | media/lib/tvremote/java/com/android/media/tv/remoteprovider/TvRemoteProvider.java | 303 |
4 files changed, 397 insertions, 0 deletions
diff --git a/media/lib/tvremote/Android.mk b/media/lib/tvremote/Android.mk new file mode 100644 index 000000000000..06838c2dbf97 --- /dev/null +++ b/media/lib/tvremote/Android.mk @@ -0,0 +1,48 @@ +# +# Copyright (C) 2016 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. +# +LOCAL_PATH := $(call my-dir) + +# the tvremoteprovider library +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_MODULE:= com.android.media.tv.remoteprovider +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + $(call all-java-files-under, java) \ + $(call all-aidl-files-under, java) + +LOCAL_DEX_PREOPT := false + +include $(BUILD_JAVA_LIBRARY) + + +# ==== com.android.media.tvremote.xml lib def ======================== +include $(CLEAR_VARS) + +LOCAL_MODULE := com.android.media.tv.remoteprovider.xml +LOCAL_MODULE_TAGS := optional + +LOCAL_MODULE_CLASS := ETC + +# This will install the file in /system/etc/permissions +# +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT)
\ No newline at end of file diff --git a/media/lib/tvremote/README.txt b/media/lib/tvremote/README.txt new file mode 100644 index 000000000000..9375f02e1cc8 --- /dev/null +++ b/media/lib/tvremote/README.txt @@ -0,0 +1,26 @@ +This library (com.android.media.tv.remoteprovider.jar) is a shared java library +containing classes required by unbundled atv remote providers. + +--- Rules of this library --- +o This library is effectively a System API for unbundled emote service provider + that may be distributed outside the system image. So it MUST BE API STABLE. + You can add but not remove. The rules are the same as for the + public platform SDK API. +o This library can see and instantiate internal platform classes, but it must not + expose them in any public method (or by extending them via inheritance). This would + break clients of the library because they cannot see the internal platform classes. + +This library is distributed in the system image, and loaded as +a shared library. So you can change the implementation, but not +the interface. In this way it is like framework.jar. + +--- Why does this library exist? --- + +Unbundled atv remote providers (such as Emote app) cannot use internal +platform classes. + +This library will eventually be replaced when the inputmanager +infrastructure is ready with APIs allowing unbundled system apps to +inject events into uhid. +That API isn't ready yet so this library is a compromise to +make new capabilities available to the system.
\ No newline at end of file diff --git a/media/lib/tvremote/com.android.media.tv.remoteprovider.xml b/media/lib/tvremote/com.android.media.tv.remoteprovider.xml new file mode 100644 index 000000000000..dcf479ac78b3 --- /dev/null +++ b/media/lib/tvremote/com.android.media.tv.remoteprovider.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2016 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. +--> + +<permissions> + <library name="com.android.media.tv.remoteprovider" + file="/system/framework/com.android.media.tv.remoteprovider.jar" /> +</permissions>
\ No newline at end of file diff --git a/media/lib/tvremote/java/com/android/media/tv/remoteprovider/TvRemoteProvider.java b/media/lib/tvremote/java/com/android/media/tv/remoteprovider/TvRemoteProvider.java new file mode 100644 index 000000000000..35322ad8ee6b --- /dev/null +++ b/media/lib/tvremote/java/com/android/media/tv/remoteprovider/TvRemoteProvider.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2016 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.media.tv.remoteprovider; + +import android.content.Context; +import android.media.tv.ITvRemoteProvider; +import android.media.tv.ITvRemoteServiceInput; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; + +/** + * Base class for emote providers implemented in unbundled service. + * <p/> + * This object is not thread safe. It is only intended to be accessed on the + * {@link Context#getMainLooper main looper thread} of an application. + * </p><p> + * IMPORTANT: This class is effectively a system API for unbundled emote service, and + * must remain API stable. See README.txt in the root of this package for more information. + * </p> + */ + + +public abstract class TvRemoteProvider { + + /** + * The {@link Intent} that must be declared as handled by the service. + * The service must also require the {@link android.Manifest.permission#BIND_TV_REMOTE_SERVICE} + * permission so that other applications cannot abuse it. + */ + public static final String SERVICE_INTERFACE = + "com.android.media.tv.remoteprovider.TvRemoteProvider"; + + private static final String TAG = "TvRemoteProvider"; + private static final boolean DEBUG_KEYS = false; + private static final int MSG_SET_SERVICE_INPUT = 1; + private static final int MSG_SEND_INPUTBRIDGE_CONNECTED = 2; + private final Context mContext; + private final ProviderStub mStub; + private final ProviderHandler mHandler; + private ITvRemoteServiceInput mRemoteServiceInput; + + /** + * Creates a provider for an unbundled emote controller + * service allowing it to interface with the tv remote controller + * system service. + * + * @param context The application context for the remote provider. + */ + public TvRemoteProvider(Context context) { + mContext = context.getApplicationContext(); + mStub = new ProviderStub(); + mHandler = new ProviderHandler(mContext.getMainLooper()); + } + + /** + * Gets the context of the remote service provider. + */ + public final Context getContext() { + return mContext; + } + + + /** + * Gets the Binder associated with the provider. + * <p> + * This is intended to be used for the onBind() method of a service that implements + * a remote provider service. + * </p> + * + * @return The IBinder instance associated with the provider. + */ + public IBinder getBinder() { + return mStub; + } + + /** + * Information about the InputBridge connected status. + * + * @param token Identifier for the connection. Null, if failed. + */ + public void onInputBridgeConnected(IBinder token) { + } + + /** + * Set a sink for sending events to framework service. + * + * @param tvServiceInput sink defined in framework service + */ + private void setRemoteServiceInputSink(ITvRemoteServiceInput tvServiceInput) { + mRemoteServiceInput = tvServiceInput; + } + + /** + * openRemoteInputBridge : Open an input bridge for a particular device. + * Clients should pass in a token that can be used to match this request with a token that + * will be returned by {@link TvRemoteProvider#onInputBridgeConnected(IBinder token)} + * <p> + * The token should be used for subsequent calls. + * </p> + * + * @param name Device name + * @param token Identifier for this connection + * @param width Width of the device's virtual touchpad + * @param height Height of the device's virtual touchpad + * @param maxPointers Maximum supported pointers + * @throws RuntimeException + */ + public void openRemoteInputBridge(IBinder token, String name, int width, int height, + int maxPointers) throws RuntimeException { + try { + mRemoteServiceInput.openInputBridge(token, name, width, height, maxPointers); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * closeInputBridge : Close input bridge for a device + * + * @param token identifier for this connection + * @throws RuntimeException + */ + public void closeInputBridge(IBinder token) throws RuntimeException { + try { + mRemoteServiceInput.closeInputBridge(token); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * clearInputBridge : Clear out any existing key or pointer events in queue for this device by + * dropping them on the floor and sending an UP to all keys and pointer + * slots. + * + * @param token identifier for this connection + * @throws RuntimeException + */ + public void clearInputBridge(IBinder token) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "clearInputBridge() token " + token); + try { + mRemoteServiceInput.clearInputBridge(token); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendTimestamp : Send a timestamp for a set of pointer events + * + * @param token identifier for the device + * @param timestamp Timestamp to be used in + * {@link android.os.SystemClock#uptimeMillis} time base + * @throws RuntimeException + */ + public void sendTimestamp(IBinder token, long timestamp) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendTimestamp() token: " + token + + ", timestamp: " + timestamp); + try { + mRemoteServiceInput.sendTimestamp(token, timestamp); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendKeyUp : Send key up event for a device + * + * @param token identifier for this connection + * @param keyCode Key code to be sent + * @throws RuntimeException + */ + public void sendKeyUp(IBinder token, int keyCode) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendKeyUp() token: " + token + ", keyCode: " + keyCode); + try { + mRemoteServiceInput.sendKeyUp(token, keyCode); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendKeyDown : Send key down event for a device + * + * @param token identifier for this connection + * @param keyCode Key code to be sent + * @throws RuntimeException + */ + public void sendKeyDown(IBinder token, int keyCode) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendKeyDown() token: " + token + + ", keyCode: " + keyCode); + try { + mRemoteServiceInput.sendKeyDown(token, keyCode); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendPointerUp : Send pointer up event for a device + * + * @param token identifier for the device + * @param pointerId Pointer id to be used. Value may be from 0 + * to {@link MotionEvent#getPointerCount()} -1 + * @throws RuntimeException + */ + public void sendPointerUp(IBinder token, int pointerId) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendPointerUp() token: " + token + + ", pointerId: " + pointerId); + try { + mRemoteServiceInput.sendPointerUp(token, pointerId); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendPointerDown : Send pointer down event for a device + * + * @param token identifier for the device + * @param pointerId Pointer id to be used. Value may be from 0 + * to {@link MotionEvent#getPointerCount()} -1 + * @param x X co-ordinates in display pixels + * @param y Y co-ordinates in display pixels + * @throws RuntimeException + */ + public void sendPointerDown(IBinder token, int pointerId, int x, int y) + throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendPointerDown() token: " + token + + ", pointerId: " + pointerId); + try { + mRemoteServiceInput.sendPointerDown(token, pointerId, x, y); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * sendPointerSync : Send pointer sync event for a device + * + * @param token identifier for the device + * @throws RuntimeException + */ + public void sendPointerSync(IBinder token) throws RuntimeException { + if (DEBUG_KEYS) Log.d(TAG, "sendPointerSync() token: " + token); + try { + mRemoteServiceInput.sendPointerSync(token); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + private final class ProviderStub extends ITvRemoteProvider.Stub { + @Override + public void setRemoteServiceInputSink(ITvRemoteServiceInput tvServiceInput) { + mHandler.obtainMessage(MSG_SET_SERVICE_INPUT, tvServiceInput).sendToTarget(); + } + + @Override + public void onInputBridgeConnected(IBinder token) { + mHandler.obtainMessage(MSG_SEND_INPUTBRIDGE_CONNECTED, 0, 0, + (IBinder) token).sendToTarget(); + } + } + + private final class ProviderHandler extends Handler { + public ProviderHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SET_SERVICE_INPUT: { + setRemoteServiceInputSink((ITvRemoteServiceInput) msg.obj); + break; + } + case MSG_SEND_INPUTBRIDGE_CONNECTED: { + onInputBridgeConnected((IBinder) msg.obj); + break; + } + } + } + } +} |