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