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
17package com.android.server;
18
19import android.content.Context;
20import android.content.pm.PackageManager;
21import android.hardware.IConsumerIrService;
22import android.os.PowerManager;
23import android.util.Slog;
24
25import java.lang.RuntimeException;
26
27public 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
32    private static native long halOpen();
33    private static native int halTransmit(long halObject, int carrierFrequency, int[] pattern);
34    private static native int[] halGetCarrierFrequencies(long halObject);
35
36    private final Context mContext;
37    private final PowerManager.WakeLock mWakeLock;
38    private final long mNativeHal;
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
48        mNativeHal = halOpen();
49        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
50            if (mNativeHal == 0) {
51                throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
52            }
53        } else if (mNativeHal != 0) {
54            throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!");
55        }
56    }
57
58    @Override
59    public boolean hasIrEmitter() {
60        return mNativeHal != 0;
61    }
62
63    private void throwIfNoIrEmitter() {
64        if (mNativeHal == 0) {
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) {
94            int err = halTransmit(mNativeHal, carrierFrequency, pattern);
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) {
112            return halGetCarrierFrequencies(mNativeHal);
113        }
114    }
115}
116