ConsumerIrService.java revision 9158825f9c41869689d6b1786d7c7aa8bdd524ce
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.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.pm.PackageManager;
24import android.database.ContentObserver;
25import android.hardware.input.InputManager;
26import android.hardware.IConsumerIrService;
27import android.os.Handler;
28import android.os.PowerManager;
29import android.os.Process;
30import android.os.RemoteException;
31import android.os.IBinder;
32import android.os.Binder;
33import android.os.ServiceManager;
34import android.os.SystemClock;
35import android.os.UserHandle;
36import android.os.WorkSource;
37import android.provider.Settings;
38import android.provider.Settings.SettingNotFoundException;
39import android.util.Slog;
40import android.view.InputDevice;
41
42import java.lang.RuntimeException;
43import java.util.ArrayList;
44import java.util.LinkedList;
45import java.util.ListIterator;
46
47public class ConsumerIrService extends IConsumerIrService.Stub {
48    private static final String TAG = "ConsumerIrService";
49
50    private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
51
52    private static native int halOpen();
53    private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
54    private static native int[] halGetCarrierFrequencies(int halObject);
55
56    private final Context mContext;
57    private final PowerManager.WakeLock mWakeLock;
58    private final int mHal;
59    private final Object mHalLock = new Object();
60
61    ConsumerIrService(Context context) {
62        mContext = context;
63        PowerManager pm = (PowerManager)context.getSystemService(
64                Context.POWER_SERVICE);
65        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
66        mWakeLock.setReferenceCounted(true);
67
68        mHal = halOpen();
69        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
70            if (mHal == 0) {
71                throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
72            }
73        } else if (mHal != 0) {
74            throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!");
75        }
76    }
77
78    @Override
79    public boolean hasIrEmitter() {
80        return mHal != 0;
81    }
82
83    private void throwIfNoIrEmitter() {
84        if (mHal == 0) {
85            throw new UnsupportedOperationException("IR emitter not available");
86        }
87    }
88
89
90    @Override
91    public void transmit(String packageName, int carrierFrequency, int[] pattern) {
92        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
93                != PackageManager.PERMISSION_GRANTED) {
94            throw new SecurityException("Requires TRANSMIT_IR permission");
95        }
96
97        long totalXmitTime = 0;
98
99        for (int slice : pattern) {
100            if (slice <= 0) {
101                throw new IllegalArgumentException("Non-positive IR slice");
102            }
103            totalXmitTime += slice;
104        }
105
106        if (totalXmitTime > MAX_XMIT_TIME ) {
107            throw new IllegalArgumentException("IR pattern too long");
108        }
109
110        throwIfNoIrEmitter();
111
112        // Right now there is no mechanism to ensure fair queing of IR requests
113        synchronized (mHalLock) {
114            int err = halTransmit(mHal, carrierFrequency, pattern);
115
116            if (err < 0) {
117                Slog.e(TAG, "Error transmitting: " + err);
118            }
119        }
120    }
121
122    @Override
123    public int[] getCarrierFrequencies() {
124        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
125                != PackageManager.PERMISSION_GRANTED) {
126            throw new SecurityException("Requires TRANSMIT_IR permission");
127        }
128
129        throwIfNoIrEmitter();
130
131        synchronized(mHalLock) {
132            return halGetCarrierFrequencies(mHal);
133        }
134    }
135}
136