Merge "Add consumer IR framework" into klp-dev

This commit is contained in:
Alexander Ray
2013-09-11 19:05:37 +00:00
committed by Android (Google) Code Review
13 changed files with 478 additions and 0 deletions

View File

@@ -120,6 +120,7 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/ICameraServiceListener.aidl \
core/java/android/hardware/ICamera.aidl \
core/java/android/hardware/ICameraClient.aidl \
core/java/android/hardware/IConsumerIrService.aidl \
core/java/android/hardware/IProCameraUser.aidl \
core/java/android/hardware/IProCameraCallbacks.aidl \
core/java/android/hardware/camera2/ICameraDeviceUser.aidl \

View File

@@ -129,6 +129,7 @@ package android {
field public static final java.lang.String SUBSCRIBED_FEEDS_READ = "android.permission.SUBSCRIBED_FEEDS_READ";
field public static final java.lang.String SUBSCRIBED_FEEDS_WRITE = "android.permission.SUBSCRIBED_FEEDS_WRITE";
field public static final java.lang.String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
@@ -5968,6 +5969,7 @@ package android.content {
field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
field public static final int CONTEXT_RESTRICTED = 4; // 0x4
@@ -10622,6 +10624,18 @@ package android.hardware {
field public int width;
}
public final class ConsumerIrManager {
method public android.hardware.ConsumerIrManager.CarrierFrequencyRange[] getCarrierFrequencies();
method public boolean hasIrEmitter();
method public void transmit(int, int[]);
}
public final class ConsumerIrManager.CarrierFrequencyRange {
ctor public ConsumerIrManager.CarrierFrequencyRange(int, int);
method public int getMaxFrequency();
method public int getMinFrequency();
}
public abstract interface FlushCompleteListener {
method public abstract void onFlushCompleted(android.hardware.Sensor);
}

View File

@@ -47,6 +47,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.hardware.ConsumerIrManager;
import android.hardware.ISerialManager;
import android.hardware.SerialManager;
import android.hardware.SystemSensorManager;
@@ -580,6 +581,11 @@ class ContextImpl extends Context {
return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
UserHandle.getAppId(Process.myUid()));
}});
registerService(CONSUMER_IR_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new ConsumerIrManager(ctx);
}});
}
static ContextImpl getImpl(Context context) {

View File

@@ -2400,6 +2400,16 @@ public abstract class Context {
*/
public static final String PRINT_SERVICE = "print";
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.hardware.ConsumerIrManager} for transmitting infrared
* signals from the device.
*
* @see #getSystemService
* @see android.hardware.ConsumerIrManager
*/
public static final String CONSUMER_IR_SERVICE = "consumer_ir";
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2013 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;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
/**
* Class that operates consumer infrared on the device.
*
* <p>
* To obtain an instance of the system infrared transmitter, call
* {@link Context#getSystemService} with {@link Context#CONSUMER_IR} as the argument.
* </p>
*/
public final class ConsumerIrManager {
private static final String TAG = "ConsumerIr";
private final String mPackageName;
private final IConsumerIrService mService;
/**
* @hide to prevent subclassing from outside of the framework
*/
public ConsumerIrManager(Context context) {
mPackageName = context.getPackageName();
mService = IConsumerIrService.Stub.asInterface(
ServiceManager.getService(Context.CONSUMER_IR_SERVICE));
}
/**
* Check whether the device has an infrared emitter.
*
* @return true if the device has an infrared emitter, else false.
*/
public boolean hasIrEmitter() {
if (mService == null) {
Log.w(TAG, "no consumer ir service.");
return false;
}
try {
return mService.hasIrEmitter();
} catch (RemoteException e) {
}
return false;
}
/**
* Tansmit and infrared pattern
* <p>
* This method is synchronous; when it returns the pattern has
* been transmitted. Only patterns shorter than 2 seconds will
* be transmitted.
* </p>
*
* @param carrierFrequency The IR carrier frequency in Hertz.
* @param pattern The alternating on/off pattern in microseconds to transmit.
*/
public void transmit(int carrierFrequency, int[] pattern) {
if (mService == null) {
Log.w(TAG, "failed to transmit; no consumer ir service.");
return;
}
try {
mService.transmit(mPackageName, carrierFrequency, pattern);
} catch (RemoteException e) {
Log.w(TAG, "failed to transmit.", e);
}
}
/**
* Represents a range of carrier frequencies (inclusive) on which the
* infrared transmitter can transmit
*/
public final class CarrierFrequencyRange {
private final int mMinFrequency;
private final int mMaxFrequency;
/**
* Create a segment of a carrier frequency range.
*
* @param min The minimum transmittable frequency in this range segment.
* @param max The maximum transmittable frequency in this range segment.
*/
public CarrierFrequencyRange(int min, int max) {
mMinFrequency = min;
mMaxFrequency = max;
}
/**
* Get the minimum (inclusive) frequency in this range segment.
*/
public int getMinFrequency() {
return mMinFrequency;
}
/**
* Get the maximum (inclusive) frequency in this range segment.
*/
public int getMaxFrequency() {
return mMaxFrequency;
}
};
/**
* Query the infrared transmitter's supported carrier frequencies
*
* @return an array of {@link #CarrierFreqRange} objects representing
* the ranges that the transmitter can support, or null if there was
* an error communicating with the Consumer IR Service.
*/
public CarrierFrequencyRange[] getCarrierFrequencies() {
if (mService == null) {
Log.w(TAG, "no consumer ir service.");
return null;
}
try {
int[] freqs = mService.getCarrierFrequencies();
if (freqs.length % 2 != 0) {
Log.w(TAG, "consumer ir service returned an uneven number of frequencies.");
return null;
}
CarrierFrequencyRange[] range = new CarrierFrequencyRange[freqs.length / 2];
for (int i = 0; i < freqs.length; i += 2) {
range[i / 2] = new CarrierFrequencyRange(freqs[i], freqs[i+1]);
}
return range;
} catch (RemoteException e) {
}
return null;
}
}

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2013, 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;
/** {@hide} */
interface IConsumerIrService
{
boolean hasIrEmitter();
void transmit(String packageName, int carrierFrequency, in int[] pattern);
int[] getCarrierFrequencies();
}

View File

@@ -899,6 +899,13 @@
android:label="@string/permlab_wakeLock"
android:description="@string/permdesc_wakeLock" />
<!-- Allows using the device's IR transmitter, if available -->
<permission android:name="android.permission.TRANSMIT_IR"
android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
android:protectionLevel="normal"
android:label="@string/permlab_transmitIr"
android:description="@string/permdesc_transmitIr" />
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
<!-- ==================================================== -->

View File

@@ -1595,6 +1595,14 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_wakeLock" product="default">Allows the app to prevent the phone from going to sleep.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_transmitIr">transmit infrared</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_transmitIr" product="tablet">Allows the app to use the tablet\'s infrared transmitter.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_transmitIr" product="default">Allows the app to use the phone\'s infrared transmitter.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_devicePower" product="tablet">power tablet on or off</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2013 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;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.hardware.IConsumerIrService;
import android.os.Handler;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Binder;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.view.InputDevice;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
public class ConsumerIrService extends IConsumerIrService.Stub {
private static final String TAG = "ConsumerIrService";
private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
private static native int halOpen();
private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
private static native int[] halGetCarrierFrequencies(int halObject);
private final Context mContext;
private final PowerManager.WakeLock mWakeLock;
private final int mHal;
private final Object mHalLock = new Object();
ConsumerIrService(Context context) {
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(true);
mHal = halOpen();
if (mHal == 0) {
Slog.w(TAG, "No IR HAL loaded");
}
}
@Override
public boolean hasIrEmitter() {
return mHal != 0;
}
private void throwIfNoIrEmitter() {
if (mHal == 0) {
throw new UnsupportedOperationException("IR emitter not available");
}
}
@Override
public void transmit(String packageName, int carrierFrequency, int[] pattern) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires TRANSMIT_IR permission");
}
long totalXmitTime = 0;
for (int slice : pattern) {
if (slice <= 0) {
throw new IllegalArgumentException("Non-positive IR slice");
}
totalXmitTime += slice;
}
if (totalXmitTime > MAX_XMIT_TIME ) {
throw new IllegalArgumentException("IR pattern too long");
}
throwIfNoIrEmitter();
// Right now there is no mechanism to ensure fair queing of IR requests
synchronized (mHalLock) {
int err = halTransmit(mHal, carrierFrequency, pattern);
if (err < 0) {
Slog.e(TAG, "Error transmitting: " + err);
}
}
}
@Override
public int[] getCarrierFrequencies() {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires TRANSMIT_IR permission");
}
throwIfNoIrEmitter();
synchronized(mHalLock) {
return halGetCarrierFrequencies(mHal);
}
}
}

View File

@@ -154,6 +154,7 @@ class ServerThread {
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
// Create a handler thread just for the window manager to enjoy.
HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
@@ -284,6 +285,10 @@ class ServerThread {
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
Slog.i(TAG, "Consumer IR Service");
consumerIr = new ConsumerIrService(context);
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
power.init(context, lights, ActivityManagerService.self(), battery,

View File

@@ -4,6 +4,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
com_android_server_AlarmManagerService.cpp \
com_android_server_AssetAtlasService.cpp \
com_android_server_ConsumerIrService.cpp \
com_android_server_input_InputApplicationHandle.cpp \
com_android_server_input_InputManagerService.cpp \
com_android_server_input_InputWindowHandle.cpp \

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2013 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 "ConsumerIrService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <stdlib.h>
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/consumerir.h>
#include <ScopedPrimitiveArray.h>
namespace android {
static jint halOpen(JNIEnv *env, jobject obj) {
hw_module_t const* module;
consumerir_device_t *dev;
int err;
err = hw_get_module(CONSUMERIR_HARDWARE_MODULE_ID, &module);
if (err != 0) {
ALOGE("Can't open consumer IR HW Module, error: %d", err);
return 0;
}
err = module->methods->open(module, CONSUMERIR_TRANSMITTER,
(hw_device_t **) &dev);
if (err < 0) {
ALOGE("Can't open consumer IR transmitter, error: %d", err);
return 0;
}
return reinterpret_cast<jint>(dev);
}
static jint halTransmit(JNIEnv *env, jobject obj, jint halObject,
jint carrierFrequency, jintArray pattern) {
int ret;
consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject);
ScopedIntArrayRO cPattern(env, pattern);
if (cPattern.get() == NULL) {
return -EINVAL;
}
jsize patternLength = cPattern.size();
ret = dev->transmit(dev, carrierFrequency, cPattern.get(), patternLength);
return reinterpret_cast<jint>(ret);
}
static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj,
jint halObject) {
consumerir_device_t *dev = (consumerir_device_t *) halObject;
consumerir_freq_range_t *ranges;
int len;
len = dev->get_num_carrier_freqs(dev);
if (len <= 0)
return NULL;
ranges = new consumerir_freq_range_t[len];
len = dev->get_carrier_freqs(dev, ranges);
if (len <= 0) {
delete[] ranges;
return NULL;
}
int i;
ScopedIntArrayRW freqsOut(env, env->NewIntArray(len*2));
jint *arr = freqsOut.get();
if (arr == NULL) {
delete[] ranges;
return NULL;
}
for (i = 0; i < len; i++) {
arr[i*2] = ranges[i].min;
arr[i*2+1] = ranges[i].max;
}
delete[] ranges;
return freqsOut.getJavaArray();
}
static JNINativeMethod method_table[] = {
{ "halOpen", "()I", (void *)halOpen },
{ "halTransmit", "(II[I)I", (void *)halTransmit },
{ "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies},
};
int register_android_server_ConsumerIrService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/ConsumerIrService",
method_table, NELEM(method_table));
}
};

View File

@@ -21,6 +21,7 @@
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_ConsumerIrService(JNIEnv *env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
@@ -65,6 +66,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
register_android_server_location_FlpHardwareProvider(env);
register_android_server_connectivity_Vpn(env);
register_android_server_AssetAtlasService(env);
register_android_server_ConsumerIrService(env);
return JNI_VERSION_1_4;
}