1 /* 2 * Copyright (C) 2015 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.tv.tuner; 18 19 import android.content.Context; 20 import android.os.ParcelFileDescriptor; 21 import android.util.Log; 22 import com.android.tv.tuner.DvbDeviceAccessor.DvbDeviceInfoWrapper; 23 24 import java.util.List; 25 import java.util.SortedSet; 26 import java.util.TreeSet; 27 28 /** 29 * A class to handle a hardware USB tuner device. 30 */ 31 public class UsbTunerHal extends TunerHal { 32 33 private static final Object sLock = new Object(); 34 // @GuardedBy("sLock") 35 private static final SortedSet<DvbDeviceInfoWrapper> sUsedDvbDevices = new TreeSet<>(); 36 37 private final DvbDeviceAccessor mDvbDeviceAccessor; 38 private DvbDeviceInfoWrapper mDvbDeviceInfo; 39 UsbTunerHal(Context context)40 protected UsbTunerHal(Context context) { 41 super(context); 42 mDvbDeviceAccessor = new DvbDeviceAccessor(context); 43 } 44 45 @Override openFirstAvailable()46 protected boolean openFirstAvailable() { 47 List<DvbDeviceInfoWrapper> deviceInfoList = mDvbDeviceAccessor.getDvbDeviceList(); 48 if (deviceInfoList == null || deviceInfoList.isEmpty()) { 49 Log.e(TAG, "There's no dvb device attached"); 50 return false; 51 } 52 synchronized (sLock) { 53 for (DvbDeviceInfoWrapper deviceInfo : deviceInfoList) { 54 if (!sUsedDvbDevices.contains(deviceInfo)) { 55 if (DEBUG) Log.d(TAG, "Available device info: " + deviceInfo); 56 mDvbDeviceInfo = deviceInfo; 57 sUsedDvbDevices.add(deviceInfo); 58 return true; 59 } 60 } 61 } 62 Log.e(TAG, "There's no available dvb devices"); 63 return false; 64 } 65 66 /** 67 * Acquires the tuner device. The requested device will be locked to the current instance if 68 * it's not acquired by others. 69 * 70 * @param deviceInfo a tuner device to open 71 * @return {@code true} if the operation was successful, {@code false} otherwise 72 */ open(DvbDeviceInfoWrapper deviceInfo)73 protected boolean open(DvbDeviceInfoWrapper deviceInfo) { 74 if (deviceInfo == null) { 75 Log.e(TAG, "Device info should not be null"); 76 return false; 77 } 78 if (mDvbDeviceInfo != null) { 79 Log.e(TAG, "Already acquired"); 80 return false; 81 } 82 List<DvbDeviceInfoWrapper> deviceInfoList = mDvbDeviceAccessor.getDvbDeviceList(); 83 if (deviceInfoList == null || deviceInfoList.isEmpty()) { 84 Log.e(TAG, "There's no dvb device attached"); 85 return false; 86 } 87 for (DvbDeviceInfoWrapper deviceInfoWrapper : deviceInfoList) { 88 if (deviceInfoWrapper.compareTo(deviceInfo) == 0) { 89 synchronized (sLock) { 90 if (sUsedDvbDevices.contains(deviceInfo)) { 91 Log.e(TAG, deviceInfo + " is already taken"); 92 return false; 93 } 94 sUsedDvbDevices.add(deviceInfo); 95 } 96 if (DEBUG) Log.d(TAG, "Available device info: " + deviceInfo); 97 mDvbDeviceInfo = deviceInfo; 98 return true; 99 } 100 } 101 Log.e(TAG, "There's no such dvb device attached"); 102 return false; 103 } 104 105 @Override close()106 public void close() { 107 if (mDvbDeviceInfo != null) { 108 if (isStreaming()) { 109 stopTune(); 110 } 111 nativeFinalize(mDvbDeviceInfo.getId()); 112 synchronized (sLock) { 113 sUsedDvbDevices.remove(mDvbDeviceInfo); 114 } 115 mDvbDeviceInfo = null; 116 } 117 } 118 119 @Override isDeviceOpen()120 protected boolean isDeviceOpen() { 121 return (mDvbDeviceInfo != null); 122 } 123 124 @Override getDeviceId()125 protected long getDeviceId() { 126 if (mDvbDeviceInfo != null) { 127 return mDvbDeviceInfo.getId(); 128 } 129 return -1; 130 } 131 132 @Override openDvbFrontEndFd()133 protected int openDvbFrontEndFd() { 134 if (mDvbDeviceInfo != null) { 135 ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice( 136 mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_FRONTEND); 137 if (descriptor != null) { 138 return descriptor.detachFd(); 139 } 140 } 141 return -1; 142 } 143 144 @Override openDvbDemuxFd()145 protected int openDvbDemuxFd() { 146 if (mDvbDeviceInfo != null) { 147 ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice( 148 mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_DEMUX); 149 if (descriptor != null) { 150 return descriptor.detachFd(); 151 } 152 } 153 return -1; 154 } 155 156 @Override openDvbDvrFd()157 protected int openDvbDvrFd() { 158 if (mDvbDeviceInfo != null) { 159 ParcelFileDescriptor descriptor = mDvbDeviceAccessor.openDvbDevice( 160 mDvbDeviceInfo, DvbDeviceAccessor.DVB_DEVICE_DVR); 161 if (descriptor != null) { 162 return descriptor.detachFd(); 163 } 164 } 165 return -1; 166 } 167 168 /** 169 * Gets the number of USB tuner devices currently present. 170 */ getNumberOfDevices(Context context)171 public static int getNumberOfDevices(Context context) { 172 return (new DvbDeviceAccessor(context)).getNumOfDvbDevices(); 173 } 174 } 175