1ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko/*
2ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
4ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * you may not use this file except in compliance with the License.
6ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * You may obtain a copy of the License at
7ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
8ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
10ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Unless required by applicable law or agreed to in writing, software
11ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * See the License for the specific language governing permissions and
14ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * limitations under the License.
15ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */
16ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
17ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkopackage com.android.usbtuner;
18ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
19ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.content.Context;
20ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.os.ParcelFileDescriptor;
21ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.IntDef;
22ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.util.Log;
23ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.usbtuner.DvbDeviceAccessor.DvbDeviceInfoWrapper;
24ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
25ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport java.util.List;
26ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport java.util.SortedSet;
27ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport java.util.TreeSet;
28ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
29ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko/**
30ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * A class to handle a hardware USB tuner device.
31ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */
32ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkopublic class UsbTunerHal extends TunerHal {
33ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
34ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private static final Object sLock = new Object();
35ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    // @GuardedBy("sLock")
36ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private static final SortedSet<DvbDeviceInfoWrapper> sUsedDvbDevices = new TreeSet<>();
37ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
38ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private final DvbDeviceAccessor mDvbDeviceAccessor;
39ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private DvbDeviceInfoWrapper mDvbDeviceInfo;
40ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
41ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected UsbTunerHal(Context context) {
42ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        super(context);
43ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        mDvbDeviceAccessor = new DvbDeviceAccessor(context);
44ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
45ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
46ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
47ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected boolean openFirstAvailable() {
48ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        List<DvbDeviceInfoWrapper> deviceInfoList = mDvbDeviceAccessor.getDvbDeviceList();
49ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (deviceInfoList == null || deviceInfoList.isEmpty()) {
50ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.e(TAG, "There's no dvb device attached");
51ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return false;
52ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
53ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        synchronized (sLock) {
54ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            for (DvbDeviceInfoWrapper deviceInfo : deviceInfoList) {
55ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                if (!sUsedDvbDevices.contains(deviceInfo)) {
56ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    if (DEBUG) Log.d(TAG, "Available device info: " + deviceInfo);
57ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    mDvbDeviceInfo = deviceInfo;
58ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    sUsedDvbDevices.add(deviceInfo);
59ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    return true;
60ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                }
61ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
62ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
63ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        Log.e(TAG, "There's no available dvb devices");
64ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return false;
65ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
66ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
67ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    /**
68ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * Acquires the tuner device. The requested device will be locked to the current instance if
69ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * it's not acquired by others.
70ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     *
71ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * @param deviceInfo a tuner device to open
72ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * @return {@code true} if the operation was successful, {@code false} otherwise
73ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     */
74ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected boolean open(DvbDeviceInfoWrapper deviceInfo) {
75ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (deviceInfo == null) {
76ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.e(TAG, "Device info should not be null");
77ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return false;
78ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
79ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
80ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.e(TAG, "Already acquired");
81ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return false;
82ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
83ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        List<DvbDeviceInfoWrapper> deviceInfoList = mDvbDeviceAccessor.getDvbDeviceList();
84ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (deviceInfoList == null || deviceInfoList.isEmpty()) {
85ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.e(TAG, "There's no dvb device attached");
86ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return false;
87ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
88ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        for (DvbDeviceInfoWrapper deviceInfoWrapper : deviceInfoList) {
89ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (deviceInfoWrapper.compareTo(deviceInfo) == 0) {
90ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                synchronized (sLock) {
91ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    if (sUsedDvbDevices.contains(deviceInfo)) {
92ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                        Log.e(TAG, deviceInfo + " is already taken");
93ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                        return false;
94ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    }
95ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    sUsedDvbDevices.add(deviceInfo);
96ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                }
97ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                if (DEBUG) Log.d(TAG, "Available device info: " + deviceInfo);
98ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                mDvbDeviceInfo = deviceInfo;
99ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                return true;
100ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
101ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
102ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        Log.e(TAG, "There's no such dvb device attached");
103ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return false;
104ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
105ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
106ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
107ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    public void close() {
108ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
109ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (isStreaming()) {
110ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                stopTune();
111ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
112ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            nativeFinalize(mDvbDeviceInfo.getId());
113ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            synchronized (sLock) {
114ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                sUsedDvbDevices.remove(mDvbDeviceInfo);
115ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
116ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            mDvbDeviceInfo = null;
117ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
118ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
119ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
120ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
121ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected boolean isDeviceOpen() {
122ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return (mDvbDeviceInfo != null);
123ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
124ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
125ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
126ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected long getDeviceId() {
127ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
128ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return mDvbDeviceInfo.getId();
129ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
130ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return -1;
131ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
132ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
133ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
134ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected int openDvbFrontEndFd() {
135ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
136ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice(
137ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_FRONTEND);
138ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (descriptor != null) {
139ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                return descriptor.detachFd();
140ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
141ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
142ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return -1;
143ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
144ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
145ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
146ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected int openDvbDemuxFd() {
147ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
148ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice(
149ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_DEMUX);
150ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (descriptor != null) {
151ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                return descriptor.detachFd();
152ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
153ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
154ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return -1;
155ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
156ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
157ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
158ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    protected int openDvbDvrFd() {
159ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (mDvbDeviceInfo != null) {
160ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice(
161ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                    mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_DVR);
162ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (descriptor != null) {
163ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                return descriptor.detachFd();
164ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
165ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
166ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return -1;
167ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
168ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko}
169