Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.server; |
| 18 | |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 19 | import android.content.Context; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 20 | import android.content.pm.PackageManager; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 21 | import android.hardware.IConsumerIrService; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 22 | import android.os.PowerManager; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 23 | import android.util.Slog; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 24 | |
Alex Ray | 0c9d61f | 2013-10-03 12:17:54 -0700 | [diff] [blame] | 25 | import java.lang.RuntimeException; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 26 | |
| 27 | public class ConsumerIrService extends IConsumerIrService.Stub { |
| 28 | private static final String TAG = "ConsumerIrService"; |
| 29 | |
| 30 | private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */ |
| 31 | |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 32 | private static native boolean halOpen(); |
| 33 | private static native int halTransmit(int carrierFrequency, int[] pattern); |
| 34 | private static native int[] halGetCarrierFrequencies(); |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 35 | |
| 36 | private final Context mContext; |
| 37 | private final PowerManager.WakeLock mWakeLock; |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 38 | private final boolean mHasNativeHal; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 39 | private final Object mHalLock = new Object(); |
| 40 | |
| 41 | ConsumerIrService(Context context) { |
| 42 | mContext = context; |
| 43 | PowerManager pm = (PowerManager)context.getSystemService( |
| 44 | Context.POWER_SERVICE); |
| 45 | mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); |
| 46 | mWakeLock.setReferenceCounted(true); |
| 47 | |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 48 | mHasNativeHal = halOpen(); |
Alex Ray | 0c9d61f | 2013-10-03 12:17:54 -0700 | [diff] [blame] | 49 | if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) { |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 50 | if (!mHasNativeHal) { |
Alex Ray | 0c9d61f | 2013-10-03 12:17:54 -0700 | [diff] [blame] | 51 | throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!"); |
| 52 | } |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 53 | } else if (mHasNativeHal) { |
Alex Ray | 0c9d61f | 2013-10-03 12:17:54 -0700 | [diff] [blame] | 54 | throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!"); |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 55 | } |
| 56 | } |
| 57 | |
| 58 | @Override |
| 59 | public boolean hasIrEmitter() { |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 60 | return mHasNativeHal; |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | private void throwIfNoIrEmitter() { |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 64 | if (!mHasNativeHal) { |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 65 | throw new UnsupportedOperationException("IR emitter not available"); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | |
| 70 | @Override |
| 71 | public void transmit(String packageName, int carrierFrequency, int[] pattern) { |
| 72 | if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR) |
| 73 | != PackageManager.PERMISSION_GRANTED) { |
| 74 | throw new SecurityException("Requires TRANSMIT_IR permission"); |
| 75 | } |
| 76 | |
| 77 | long totalXmitTime = 0; |
| 78 | |
| 79 | for (int slice : pattern) { |
| 80 | if (slice <= 0) { |
| 81 | throw new IllegalArgumentException("Non-positive IR slice"); |
| 82 | } |
| 83 | totalXmitTime += slice; |
| 84 | } |
| 85 | |
| 86 | if (totalXmitTime > MAX_XMIT_TIME ) { |
| 87 | throw new IllegalArgumentException("IR pattern too long"); |
| 88 | } |
| 89 | |
| 90 | throwIfNoIrEmitter(); |
| 91 | |
| 92 | // Right now there is no mechanism to ensure fair queing of IR requests |
| 93 | synchronized (mHalLock) { |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 94 | int err = halTransmit(carrierFrequency, pattern); |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 95 | |
| 96 | if (err < 0) { |
| 97 | Slog.e(TAG, "Error transmitting: " + err); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | @Override |
| 103 | public int[] getCarrierFrequencies() { |
| 104 | if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR) |
| 105 | != PackageManager.PERMISSION_GRANTED) { |
| 106 | throw new SecurityException("Requires TRANSMIT_IR permission"); |
| 107 | } |
| 108 | |
| 109 | throwIfNoIrEmitter(); |
| 110 | |
| 111 | synchronized(mHalLock) { |
Connor O'Brien | 6a24ab1 | 2016-12-09 15:42:35 -0800 | [diff] [blame^] | 112 | return halGetCarrierFrequencies(); |
Erik Gilling | 51e95df | 2013-06-26 11:06:51 -0700 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | } |