1 /* 2 * Copyright 2019 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 android.media.tv.tuner.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.ServiceConnection; 31 import android.content.pm.PackageManager; 32 import android.media.AudioPresentation; 33 import android.media.tv.tuner.DemuxCapabilities; 34 import android.media.tv.tuner.DemuxInfo; 35 import android.media.tv.tuner.Descrambler; 36 import android.media.tv.tuner.Lnb; 37 import android.media.tv.tuner.LnbCallback; 38 import android.media.tv.tuner.Tuner; 39 import android.media.tv.tuner.TunerVersionChecker; 40 import android.media.tv.tuner.dvr.DvrPlayback; 41 import android.media.tv.tuner.dvr.DvrRecorder; 42 import android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener; 43 import android.media.tv.tuner.dvr.OnRecordStatusChangedListener; 44 import android.media.tv.tuner.filter.AlpFilterConfiguration; 45 import android.media.tv.tuner.filter.AudioDescriptor; 46 import android.media.tv.tuner.filter.AvSettings; 47 import android.media.tv.tuner.filter.DownloadEvent; 48 import android.media.tv.tuner.filter.DownloadSettings; 49 import android.media.tv.tuner.filter.Filter; 50 import android.media.tv.tuner.filter.FilterCallback; 51 import android.media.tv.tuner.filter.FilterConfiguration; 52 import android.media.tv.tuner.filter.FilterEvent; 53 import android.media.tv.tuner.filter.IpCidChangeEvent; 54 import android.media.tv.tuner.filter.IpFilterConfiguration; 55 import android.media.tv.tuner.filter.IpPayloadEvent; 56 import android.media.tv.tuner.filter.MediaEvent; 57 import android.media.tv.tuner.filter.MmtpFilterConfiguration; 58 import android.media.tv.tuner.filter.MmtpRecordEvent; 59 import android.media.tv.tuner.filter.PesEvent; 60 import android.media.tv.tuner.filter.PesSettings; 61 import android.media.tv.tuner.filter.RecordSettings; 62 import android.media.tv.tuner.filter.RestartEvent; 63 import android.media.tv.tuner.filter.ScramblingStatusEvent; 64 import android.media.tv.tuner.filter.SectionEvent; 65 import android.media.tv.tuner.filter.SectionSettingsWithSectionBits; 66 import android.media.tv.tuner.filter.SectionSettingsWithTableInfo; 67 import android.media.tv.tuner.filter.Settings; 68 import android.media.tv.tuner.filter.SharedFilter; 69 import android.media.tv.tuner.filter.SharedFilterCallback; 70 import android.media.tv.tuner.filter.TemiEvent; 71 import android.media.tv.tuner.filter.TimeFilter; 72 import android.media.tv.tuner.filter.TlvFilterConfiguration; 73 import android.media.tv.tuner.filter.TsFilterConfiguration; 74 import android.media.tv.tuner.filter.TsRecordEvent; 75 import android.media.tv.tuner.frontend.AnalogFrontendCapabilities; 76 import android.media.tv.tuner.frontend.AnalogFrontendSettings; 77 import android.media.tv.tuner.frontend.Atsc3FrontendCapabilities; 78 import android.media.tv.tuner.frontend.Atsc3FrontendSettings; 79 import android.media.tv.tuner.frontend.Atsc3PlpInfo; 80 import android.media.tv.tuner.frontend.AtscFrontendCapabilities; 81 import android.media.tv.tuner.frontend.AtscFrontendSettings; 82 import android.media.tv.tuner.frontend.DtmbFrontendCapabilities; 83 import android.media.tv.tuner.frontend.DtmbFrontendSettings; 84 import android.media.tv.tuner.frontend.DvbcFrontendCapabilities; 85 import android.media.tv.tuner.frontend.DvbcFrontendSettings; 86 import android.media.tv.tuner.frontend.DvbsFrontendCapabilities; 87 import android.media.tv.tuner.frontend.DvbsFrontendSettings; 88 import android.media.tv.tuner.frontend.DvbtFrontendCapabilities; 89 import android.media.tv.tuner.frontend.DvbtFrontendSettings; 90 import android.media.tv.tuner.frontend.FrontendCapabilities; 91 import android.media.tv.tuner.frontend.FrontendInfo; 92 import android.media.tv.tuner.frontend.FrontendSettings; 93 import android.media.tv.tuner.frontend.FrontendStatus; 94 import android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo; 95 import android.media.tv.tuner.frontend.FrontendStatusReadiness; 96 import android.media.tv.tuner.frontend.IptvFrontendCapabilities; 97 import android.media.tv.tuner.frontend.IptvFrontendSettings; 98 import android.media.tv.tuner.frontend.Isdbs3FrontendCapabilities; 99 import android.media.tv.tuner.frontend.Isdbs3FrontendSettings; 100 import android.media.tv.tuner.frontend.IsdbsFrontendCapabilities; 101 import android.media.tv.tuner.frontend.IsdbsFrontendSettings; 102 import android.media.tv.tuner.frontend.IsdbtFrontendCapabilities; 103 import android.media.tv.tuner.frontend.IsdbtFrontendSettings; 104 import android.media.tv.tuner.frontend.OnTuneEventListener; 105 import android.media.tv.tuner.frontend.ScanCallback; 106 import android.media.tv.tunerresourcemanager.TunerFrontendInfo; 107 import android.media.tv.tunerresourcemanager.TunerFrontendRequest; 108 import android.media.tv.tunerresourcemanager.TunerResourceManager; 109 import android.os.ConditionVariable; 110 import android.os.Handler; 111 import android.os.IBinder; 112 import android.os.Looper; 113 import android.os.Message; 114 import android.util.SparseIntArray; 115 116 import androidx.test.InstrumentationRegistry; 117 import androidx.test.filters.SmallTest; 118 import androidx.test.runner.AndroidJUnit4; 119 120 import com.android.compatibility.common.util.RequiredFeatureRule; 121 122 import org.junit.After; 123 import org.junit.Before; 124 import org.junit.Rule; 125 import org.junit.Test; 126 import org.junit.runner.RunWith; 127 128 import java.time.Duration; 129 import java.time.Instant; 130 import java.util.ArrayList; 131 import java.util.List; 132 import java.util.concurrent.BlockingQueue; 133 import java.util.concurrent.CountDownLatch; 134 import java.util.concurrent.Executor; 135 import java.util.concurrent.LinkedBlockingQueue; 136 import java.util.concurrent.TimeUnit; 137 import java.util.concurrent.locks.ReentrantLock; 138 139 @RunWith(AndroidJUnit4.class) 140 @SmallTest 141 public class TunerTest { 142 private static final String TAG = "MediaTunerTest"; 143 144 @Rule 145 public RequiredFeatureRule featureRule = new RequiredFeatureRule( 146 PackageManager.FEATURE_TUNER); 147 148 private static final int TIMEOUT_MS = 10 * 1000; // 10 seconds 149 private static final int SCAN_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes 150 private static final long TIMEOUT_BINDER_SERVICE_SEC = 2; 151 152 private Context mContext; 153 private Tuner mTuner; 154 private CountDownLatch mLockLatch = new CountDownLatch(1); 155 private TunerResourceManager mTunerResourceManager = null; 156 private TestServiceConnection mConnection; 157 private ISharedFilterTestServer mSharedFilterTestServer; 158 159 private int mDummyResourceCount = 0; 160 private DemuxFilterTypeProcessor mDFMTProcessor = new DemuxFilterTypeProcessor(); 161 162 private final Object mResourceLostCountLock = new Object(); 163 private int mResourceLostCount = 0; 164 getFilterSubTypeForTest(int filterType)165 private int getFilterSubTypeForTest(int filterType) { 166 int subType = Filter.TYPE_UNDEFINED; 167 switch (filterType) { 168 case (Filter.TYPE_TS): 169 subType = Filter.SUBTYPE_SECTION; 170 break; 171 case (Filter.TYPE_MMTP): 172 subType = Filter.SUBTYPE_PES; 173 break; 174 case (Filter.TYPE_IP): 175 subType = Filter.SUBTYPE_IP; 176 break; 177 case (Filter.TYPE_TLV): 178 subType = Filter.SUBTYPE_TLV; 179 break; 180 case (Filter.TYPE_ALP): 181 subType = Filter.SUBTYPE_SECTION; 182 break; 183 default: 184 break; 185 } 186 return subType; 187 } 188 189 private class DemuxFilterTypeProcessor { 190 // number of the emuxes on the system 191 int mNumOfDemuxes; 192 193 // the bitwise OR of all the DemuxFilterTypes on the system 194 int mCombinedCaps; 195 196 // the cap (singular) that are supported by the least # of demuxes on the system 197 int mLeastFrequentCap; 198 int mRunningMinCount; 199 200 // the cap with the least # of bits that are not singular 201 // e.g. if there are 4 demuxes with b111, b1011, b1000, b1010 --> b1010 202 int mSmallestMultiBitsCap; 203 int mRunningSmallestNumOfBits; 204 205 // for storing # of demux resources supporting each cap 206 SparseIntArray mCapCounts = new SparseIntArray(); 207 getNumOfDemuxes()208 public int getNumOfDemuxes() { 209 return mNumOfDemuxes; 210 } 211 getSmallestMultiBitsCap()212 public int getSmallestMultiBitsCap() { 213 return mSmallestMultiBitsCap; 214 } 215 getCapCount(int cap)216 public int getCapCount(int cap) { 217 if (cap >= Integer.SIZE) { 218 return 0; 219 } 220 return mCapCounts.get(cap, -1); 221 } 222 getLeastFrequentCap()223 public int getLeastFrequentCap() { 224 return mLeastFrequentCap; 225 } 226 227 // e.g. getPartialCap(b101) --> b1 getPartialCap(int baseCap)228 public int getPartialCap(int baseCap) { 229 int cap = 1; 230 for (int i = 0; i < Integer.SIZE; i++) { 231 if ((cap & baseCap) == cap) { 232 return cap; 233 } 234 cap = cap << 1; 235 } 236 return baseCap; 237 } 238 239 // e.g. getFirstSupportedCap(b0) -> b1, when mCombinedCaps is b10101 240 // getFirstSupportedCap(b1) -> b100, when mCombinedCaps is b10101 getFirstSupportedCap(int excludeCaps)241 public int getFirstSupportedCap(int excludeCaps) { 242 int cap = 1; 243 for (int i = 0; i < Integer.SIZE; i++) { 244 if ((excludeCaps & cap) == 0 245 && (mCombinedCaps & cap) == cap) { 246 return cap; 247 } 248 cap = cap << 1; 249 } 250 return 0; 251 } 252 253 // e.g. getFirstNonSupportedCap() -> b01, when mCombinedCaps is b10101 getFirstNonSupportedCap()254 public int getFirstNonSupportedCap() { 255 int cap = 1; 256 for (int i = 0; i < Integer.SIZE; i++) { 257 if ((cap & mCombinedCaps) != cap) { 258 return cap; 259 } 260 cap = cap << 1; 261 } 262 return 0; 263 } 264 reset()265 public void reset() { 266 mNumOfDemuxes = 0; 267 mSmallestMultiBitsCap = 0; 268 mRunningSmallestNumOfBits = Integer.SIZE; 269 mCombinedCaps = 0; 270 mCapCounts.clear(); 271 mLeastFrequentCap = 0; 272 mRunningMinCount = Integer.MAX_VALUE; 273 } 274 DemuxFilterTypeProcessor()275 DemuxFilterTypeProcessor() { 276 reset(); 277 } 278 updateCapCounts(int caps)279 private void updateCapCounts(int caps) { 280 int mask = 1; 281 for (int i = 0; i < Integer.SIZE - 1; i++) { 282 if (mask > caps) { 283 break; 284 } 285 if ((caps & mask) == mask) { 286 int newCount = mCapCounts.get(mask, 0) + 1; 287 mCapCounts.put(mask, newCount); 288 if (newCount < mRunningMinCount) { 289 mRunningMinCount = newCount; 290 mLeastFrequentCap = mask; 291 } 292 } 293 mask = mask << 1; 294 } 295 } 296 processEntry(DemuxFilterTypeInfo entry)297 public void processEntry(DemuxFilterTypeInfo entry) { 298 int caps = entry.getCaps(); 299 int numOfCaps = entry.getNumOfCaps(); 300 301 // update mSmallestMultiBitsCap 302 if (numOfCaps > 1 && numOfCaps < mRunningSmallestNumOfBits) { 303 mRunningSmallestNumOfBits = numOfCaps; 304 mSmallestMultiBitsCap = caps; 305 } 306 mCombinedCaps = mCombinedCaps | caps; 307 updateCapCounts(caps); 308 mNumOfDemuxes++; 309 } 310 } 311 312 private class DemuxFilterTypeInfo { 313 int mFilterTypes; 314 int mNumOfCaps; 315 DemuxFilterTypeInfo(int filterTypes)316 DemuxFilterTypeInfo(int filterTypes) { 317 mFilterTypes = filterTypes; 318 mNumOfCaps = Integer.bitCount(filterTypes); 319 } getCaps()320 public int getCaps() { 321 return mFilterTypes; 322 } getNumOfCaps()323 public int getNumOfCaps() { 324 return mNumOfCaps; 325 } 326 } 327 328 329 private class TestServiceConnection implements ServiceConnection { 330 private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>(); 331 onServiceConnected(ComponentName componentName, IBinder service)332 public void onServiceConnected(ComponentName componentName, IBinder service) { 333 mBlockingQueue.offer(service); 334 } 335 onServiceDisconnected(ComponentName componentName)336 public void onServiceDisconnected(ComponentName componentName) {} 337 getService()338 public IBinder getService() throws Exception { 339 final IBinder service = 340 mBlockingQueue.poll(TIMEOUT_BINDER_SERVICE_SEC, TimeUnit.SECONDS); 341 return service; 342 } 343 } 344 345 private class TunerResourceTestServiceConnection implements ServiceConnection { 346 private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>(); 347 348 @Override onServiceConnected(ComponentName componentName, IBinder service)349 public void onServiceConnected(ComponentName componentName, IBinder service) { 350 mBlockingQueue.offer(service); 351 } 352 353 @Override onServiceDisconnected(ComponentName componentName)354 public void onServiceDisconnected(ComponentName componentName){} 355 getService()356 public ITunerResourceTestServer getService() throws Exception { 357 final IBinder service = 358 mBlockingQueue.poll(TIMEOUT_BINDER_SERVICE_SEC, TimeUnit.SECONDS); 359 return ITunerResourceTestServer.Stub.asInterface(service); 360 } 361 } 362 363 private class TunerTestOnTuneEventListener implements OnTuneEventListener { 364 public static final int INVALID_TUNE_EVENT = -1; 365 private static final int SLEEP_TIME_MS = 3000; 366 private static final int TIMEOUT_MS = 3000; 367 private final ReentrantLock mLock = new ReentrantLock(); 368 private final ConditionVariable mCV = new ConditionVariable(); 369 private int mLastTuneEvent = INVALID_TUNE_EVENT; 370 371 @Override onTuneEvent(int tuneEvent)372 public void onTuneEvent(int tuneEvent) { 373 synchronized (mLock) { 374 mLastTuneEvent = tuneEvent; 375 mCV.open(); 376 } 377 } 378 resetLastTuneEvent()379 public void resetLastTuneEvent() { 380 synchronized (mLock) { 381 mLastTuneEvent = INVALID_TUNE_EVENT; 382 } 383 } 384 getLastTuneEvent()385 public int getLastTuneEvent() { 386 try { 387 // yield to let the callback handling execute 388 Thread.sleep(SLEEP_TIME_MS); 389 } catch (Exception e) { 390 // ignore exception 391 } 392 synchronized (mLock) { 393 mCV.block(TIMEOUT_MS); 394 mCV.close(); 395 return mLastTuneEvent; 396 } 397 } 398 } 399 400 private class TunerTestLnbCallback implements LnbCallback { 401 public static final int INVALID_LNB_EVENT = -1; 402 private static final int SLEEP_TIME_MS = 100; 403 private static final int TIMEOUT_MS = 500; 404 private final ReentrantLock mDMLock = new ReentrantLock(); 405 private final ConditionVariable mDMCV = new ConditionVariable(); 406 private boolean mOnDiseqcMessageCalled = false; 407 408 // will not test this as there is no good way to trigger this 409 @Override onEvent(int lnbEventType)410 public void onEvent(int lnbEventType) {} 411 412 // will test this instead 413 @Override onDiseqcMessage(byte[] diseqcMessage)414 public void onDiseqcMessage(byte[] diseqcMessage) { 415 synchronized (mDMLock) { 416 mOnDiseqcMessageCalled = true; 417 mDMCV.open(); 418 } 419 } 420 resetOnDiseqcMessageCalled()421 public void resetOnDiseqcMessageCalled() { 422 synchronized (mDMLock) { 423 mOnDiseqcMessageCalled = false; 424 } 425 } 426 getOnDiseqcMessageCalled()427 public boolean getOnDiseqcMessageCalled() { 428 try { 429 // yield to let the callback handling execute 430 Thread.sleep(SLEEP_TIME_MS); 431 } catch (Exception e) { 432 // ignore exception 433 } 434 435 synchronized (mDMLock) { 436 mDMCV.block(TIMEOUT_MS); 437 mDMCV.close(); 438 return mOnDiseqcMessageCalled; 439 } 440 } 441 } 442 443 @Before setUp()444 public void setUp() throws Exception { 445 mContext = InstrumentationRegistry.getTargetContext(); 446 InstrumentationRegistry 447 .getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); 448 mTuner = new Tuner(mContext, null, 100); 449 } 450 451 @After tearDown()452 public void tearDown() { 453 if (mTuner != null) { 454 mTuner.close(); 455 mTuner = null; 456 } 457 } 458 459 @Test testTunerConstructor()460 public void testTunerConstructor() throws Exception { 461 assertNotNull(mTuner); 462 } 463 464 @Test testTunerVersion()465 public void testTunerVersion() { 466 assertNotNull(mTuner); 467 int version = TunerVersionChecker.getTunerVersion(); 468 assertTrue(version >= TunerVersionChecker.TUNER_VERSION_1_0); 469 assertTrue(version <= TunerVersionChecker.TUNER_VERSION_3_0); 470 } 471 472 @Test testFrontendHardwareInfo()473 public void testFrontendHardwareInfo() throws Exception { 474 String hwInfo = null; 475 try { 476 hwInfo = mTuner.getCurrentFrontendHardwareInfo(); 477 if (TunerVersionChecker.isHigherOrEqualVersionTo( 478 TunerVersionChecker.TUNER_VERSION_2_0)) { 479 fail("Get Frontend hardware info should throw IllegalStateException."); 480 } else { 481 assertNull(hwInfo); 482 } 483 } catch (IllegalStateException e) { 484 // pass 485 } 486 487 List<Integer> ids = mTuner.getFrontendIds(); 488 if (ids == null) return; 489 assertFalse(ids.isEmpty()); 490 491 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 492 int res = mTuner.tune(createFrontendSettings(info)); 493 hwInfo = mTuner.getCurrentFrontendHardwareInfo(); 494 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 495 assertNotNull(hwInfo); 496 assertFalse(hwInfo.isEmpty()); 497 } else { 498 assertNull(hwInfo); 499 } 500 res = mTuner.cancelTuning(); 501 assertEquals(Tuner.RESULT_SUCCESS, res); 502 } 503 504 @Test testTuning()505 public void testTuning() throws Exception { 506 List<Integer> ids = mTuner.getFrontendIds(); 507 if (ids == null) return; 508 assertFalse(ids.isEmpty()); 509 510 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 511 int res = mTuner.tune(createFrontendSettings(info)); 512 assertEquals(Tuner.RESULT_SUCCESS, res); 513 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_3_0)) { 514 if (mTuner.isLnaSupported()) { 515 res = mTuner.setLnaEnabled(false); 516 assertEquals(Tuner.RESULT_SUCCESS, res); 517 } else { 518 res = mTuner.setLnaEnabled(false); 519 assertEquals(Tuner.RESULT_UNAVAILABLE, res); 520 } 521 } else { 522 res = mTuner.setLnaEnabled(false); 523 assertTrue((res == Tuner.RESULT_SUCCESS) || (res == Tuner.RESULT_UNAVAILABLE)); 524 } 525 res = mTuner.cancelTuning(); 526 assertEquals(Tuner.RESULT_SUCCESS, res); 527 } 528 529 @Test testIsLnaSupported()530 public void testIsLnaSupported() throws Exception { 531 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_3_0)) { 532 mTuner.isLnaSupported(); 533 // no exception thrown 534 } else { 535 try { 536 mTuner.isLnaSupported(); 537 fail("Is LNA Supported should throw UnsupportedOperationException."); 538 } catch (UnsupportedOperationException uoe) { 539 // pass 540 } 541 } 542 } 543 544 @Test testMultiTuning()545 public void testMultiTuning() throws Exception { 546 List<Integer> ids = mTuner.getFrontendIds(); 547 if (ids == null) return; 548 assertFalse(ids.isEmpty()); 549 550 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 551 int res = mTuner.tune(createFrontendSettings(info)); 552 assertEquals(Tuner.RESULT_SUCCESS, res); 553 res = mTuner.cancelTuning(); 554 assertEquals(Tuner.RESULT_SUCCESS, res); 555 556 // Tune again with the same frontend. 557 mTuner.tune(createFrontendSettings(info)); 558 assertEquals(Tuner.RESULT_SUCCESS, res); 559 res = mTuner.cancelTuning(); 560 assertEquals(Tuner.RESULT_SUCCESS, res); 561 562 for (int i = 1; i < ids.size(); i++) { 563 FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(i)); 564 if (info2.getType() != info.getType()) { 565 res = mTuner.tune(createFrontendSettings(info2)); 566 assertEquals(Tuner.RESULT_INVALID_STATE, res); 567 } 568 } 569 } 570 571 @Test testRequestFrontendThenTune()572 public void testRequestFrontendThenTune() throws Exception { 573 List<FrontendInfo> frontendInfos = mTuner.getAvailableFrontendInfos(); 574 if (frontendInfos == null) return; 575 assertFalse(frontendInfos.isEmpty()); 576 577 FrontendInfo frontendInfo = frontendInfos.get(0); 578 int result = mTuner.applyFrontend(frontendInfo); 579 assertEquals(Tuner.RESULT_SUCCESS, result); 580 581 result = mTuner.tune(createFrontendSettings(frontendInfo)); 582 assertEquals(Tuner.RESULT_SUCCESS, result); 583 584 for (FrontendInfo info2: frontendInfos) { 585 if (info2.getType() != frontendInfo.getType()) { 586 result = mTuner.tune(createFrontendSettings(info2)); 587 assertEquals(Tuner.RESULT_INVALID_STATE, result); 588 } 589 } 590 591 // After tune(), the frontend assigned by applyFrontend should still be used. 592 FrontendInfo currentFrontendInfo = mTuner.getFrontendInfo(); 593 assertEquals(frontendInfo.getId(), currentFrontendInfo.getId()); 594 } 595 596 @Test testScanning()597 public void testScanning() throws Exception { 598 // Use the same test approach as testTune since it is not possible to test all frontends on 599 // one signal source 600 List<Integer> ids = mTuner.getFrontendIds(); 601 if (ids == null) return; 602 assertFalse(ids.isEmpty()); 603 604 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 605 int res = mTuner.scan( 606 createFrontendSettings(info), 607 Tuner.SCAN_TYPE_AUTO, 608 getExecutor(), 609 getScanCallback()); 610 assertEquals(Tuner.RESULT_SUCCESS, res); 611 res = mTuner.cancelScanning(); 612 assertEquals(Tuner.RESULT_SUCCESS, res); 613 } 614 615 @Test testFrontendStatus()616 public void testFrontendStatus() throws Exception { 617 List<Integer> ids = mTuner.getFrontendIds(); 618 if (ids == null) return; 619 assertFalse(ids.isEmpty()); 620 621 for (int id : ids) { 622 Tuner tuner = new Tuner(mContext, null, 100); 623 FrontendInfo info = tuner.getFrontendInfoById(id); 624 int res = tuner.tune(createFrontendSettings(info)); 625 626 int[] statusCapabilities = info.getStatusCapabilities(); 627 assertNotNull(statusCapabilities); 628 FrontendStatus status = tuner.getFrontendStatus(statusCapabilities); 629 assertNotNull(status); 630 631 for (int i = 0; i < statusCapabilities.length; i++) { 632 switch (statusCapabilities[i]) { 633 case FrontendStatus.FRONTEND_STATUS_TYPE_DEMOD_LOCK: 634 status.isDemodLocked(); 635 break; 636 case FrontendStatus.FRONTEND_STATUS_TYPE_SNR: 637 status.getSnr(); 638 break; 639 case FrontendStatus.FRONTEND_STATUS_TYPE_BER: 640 status.getBer(); 641 break; 642 case FrontendStatus.FRONTEND_STATUS_TYPE_PER: 643 status.getPer(); 644 break; 645 case FrontendStatus.FRONTEND_STATUS_TYPE_PRE_BER: 646 status.getPerBer(); 647 break; 648 case FrontendStatus.FRONTEND_STATUS_TYPE_SIGNAL_QUALITY: 649 status.getSignalQuality(); 650 break; 651 case FrontendStatus.FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH: 652 status.getSignalStrength(); 653 break; 654 case FrontendStatus.FRONTEND_STATUS_TYPE_SYMBOL_RATE: 655 status.getSymbolRate(); 656 break; 657 case FrontendStatus.FRONTEND_STATUS_TYPE_FEC: 658 status.getInnerFec(); 659 break; 660 case FrontendStatus.FRONTEND_STATUS_TYPE_MODULATION: 661 if (info.getType() != FrontendSettings.TYPE_DVBT && 662 info.getType() != FrontendSettings.TYPE_ANALOG) 663 status.getModulation(); 664 break; 665 case FrontendStatus.FRONTEND_STATUS_TYPE_SPECTRAL: 666 status.getSpectralInversion(); 667 break; 668 case FrontendStatus.FRONTEND_STATUS_TYPE_LNB_VOLTAGE: 669 status.getLnbVoltage(); 670 break; 671 case FrontendStatus.FRONTEND_STATUS_TYPE_PLP_ID: 672 status.getPlpId(); 673 break; 674 case FrontendStatus.FRONTEND_STATUS_TYPE_EWBS: 675 status.isEwbs(); 676 break; 677 case FrontendStatus.FRONTEND_STATUS_TYPE_AGC: 678 status.getAgc(); 679 break; 680 case FrontendStatus.FRONTEND_STATUS_TYPE_LNA: 681 status.isLnaOn(); 682 break; 683 case FrontendStatus.FRONTEND_STATUS_TYPE_LAYER_ERROR: 684 boolean[] r = status.getLayerErrors(); 685 assertNotNull(r); 686 break; 687 case FrontendStatus.FRONTEND_STATUS_TYPE_MER: 688 status.getMer(); 689 break; 690 case FrontendStatus.FRONTEND_STATUS_TYPE_FREQ_OFFSET: 691 status.getFreqOffsetLong(); 692 status.getFreqOffset(); 693 break; 694 case FrontendStatus.FRONTEND_STATUS_TYPE_HIERARCHY: 695 status.getHierarchy(); 696 break; 697 case FrontendStatus.FRONTEND_STATUS_TYPE_RF_LOCK: 698 status.isRfLocked(); 699 break; 700 case FrontendStatus.FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO: 701 Atsc3PlpTuningInfo[] tuningInfos = status.getAtsc3PlpTuningInfo(); 702 if (tuningInfos != null) { 703 for (Atsc3PlpTuningInfo tuningInfo : tuningInfos) { 704 tuningInfo.getPlpId(); 705 tuningInfo.isLocked(); 706 tuningInfo.getUec(); 707 } 708 } 709 break; 710 case FrontendStatus.FRONTEND_STATUS_TYPE_BERS: 711 int[] b = status.getBers(); 712 assertNotNull(b); 713 break; 714 case FrontendStatus.FRONTEND_STATUS_TYPE_CODERATES: 715 int[] c = status.getCodeRates(); 716 assertNotNull(c); 717 break; 718 case FrontendStatus.FRONTEND_STATUS_TYPE_BANDWIDTH: 719 status.getBandwidth(); 720 break; 721 case FrontendStatus.FRONTEND_STATUS_TYPE_GUARD_INTERVAL: 722 status.getGuardInterval(); 723 break; 724 case FrontendStatus.FRONTEND_STATUS_TYPE_TRANSMISSION_MODE: 725 status.getTransmissionMode(); 726 break; 727 case FrontendStatus.FRONTEND_STATUS_TYPE_UEC: 728 status.getUec(); 729 break; 730 case FrontendStatus.FRONTEND_STATUS_TYPE_T2_SYSTEM_ID: 731 status.getSystemId(); 732 break; 733 case FrontendStatus.FRONTEND_STATUS_TYPE_INTERLEAVINGS: 734 int[] l = status.getInterleaving(); 735 assertNotNull(l); 736 break; 737 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS: 738 int[] segment = status.getIsdbtSegment(); 739 assertNotNull(segment); 740 break; 741 case FrontendStatus.FRONTEND_STATUS_TYPE_TS_DATA_RATES: 742 int[] rates = status.getTsDataRate(); 743 assertNotNull(rates); 744 break; 745 case FrontendStatus.FRONTEND_STATUS_TYPE_MODULATIONS_EXT: 746 int[] modulations = status.getExtendedModulations(); 747 assertNotNull(modulations); 748 break; 749 case FrontendStatus.FRONTEND_STATUS_TYPE_ROLL_OFF: 750 status.getRollOff(); 751 break; 752 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_MISO_ENABLED: 753 status.isMisoEnabled(); 754 break; 755 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_LINEAR: 756 status.isLinear(); 757 break; 758 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED: 759 status.isShortFramesEnabled(); 760 break; 761 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_MODE: 762 status.getIsdbtMode(); 763 break; 764 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_PARTIAL_RECEPTION_FLAG: 765 status.getIsdbtPartialReceptionFlag(); 766 break; 767 case FrontendStatus.FRONTEND_STATUS_TYPE_STREAM_IDS: 768 int[] streamIds = status.getStreamIds(); 769 assertNotNull(streamIds); 770 break; 771 case FrontendStatus.FRONTEND_STATUS_TYPE_DVBT_CELL_IDS: 772 int[] cellIds = status.getDvbtCellIds(); 773 assertNotNull(cellIds); 774 break; 775 case FrontendStatus.FRONTEND_STATUS_TYPE_ATSC3_ALL_PLP_INFO: 776 List<Atsc3PlpInfo> plps = status.getAllAtsc3PlpInfo(); 777 assertFalse(plps.isEmpty()); 778 break; 779 case FrontendStatus.FRONTEND_STATUS_TYPE_IPTV_CONTENT_URL: 780 String iptvContentUrl = status.getIptvContentUrl(); 781 assertNotNull(iptvContentUrl); 782 break; 783 case FrontendStatus.FRONTEND_STATUS_TYPE_IPTV_PACKETS_LOST: 784 status.getIptvPacketsLost(); 785 break; 786 case FrontendStatus.FRONTEND_STATUS_TYPE_IPTV_PACKETS_RECEIVED: 787 status.getIptvPacketsReceived(); 788 break; 789 case FrontendStatus.FRONTEND_STATUS_TYPE_IPTV_WORST_JITTER_MS: 790 status.getIptvWorstJitterMillis(); 791 break; 792 case FrontendStatus.FRONTEND_STATUS_TYPE_IPTV_AVERAGE_JITTER_MS: 793 status.getIptvAverageJitterMillis(); 794 break; 795 } 796 } 797 tuner.close(); 798 tuner = null; 799 } 800 } 801 802 @Test testFrontendStatusReadiness()803 public void testFrontendStatusReadiness() throws Exception { 804 // Test w/o active frontend 805 try { 806 int[] caps = {0}; 807 List<FrontendStatusReadiness> readiness = mTuner.getFrontendStatusReadiness(caps); 808 if (TunerVersionChecker.isHigherOrEqualVersionTo( 809 TunerVersionChecker.TUNER_VERSION_2_0)) { 810 fail("Get Frontend Status Readiness should throw IllegalStateException."); 811 } else { 812 assertTrue(readiness.isEmpty()); 813 } 814 } catch (IllegalStateException e) { 815 // pass 816 } 817 818 List<Integer> ids = mTuner.getFrontendIds(); 819 if (ids == null) 820 return; 821 assertFalse(ids.isEmpty()); 822 823 for (int id : ids) { 824 Tuner tuner = new Tuner(mContext, null, 100); 825 FrontendInfo info = tuner.getFrontendInfoById(id); 826 int res = tuner.tune(createFrontendSettings(info)); 827 828 int[] statusCapabilities = info.getStatusCapabilities(); 829 assertNotNull(statusCapabilities); 830 List<FrontendStatusReadiness> readiness = 831 tuner.getFrontendStatusReadiness(statusCapabilities); 832 if (TunerVersionChecker.isHigherOrEqualVersionTo( 833 TunerVersionChecker.TUNER_VERSION_2_0)) { 834 assertEquals(readiness.size(), statusCapabilities.length); 835 for (int i = 0; i < readiness.size(); i++) { 836 assertEquals(readiness.get(i).getStatusType(), statusCapabilities[i]); 837 int r = readiness.get(i).getStatusReadiness(); 838 if (r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_UNAVAILABLE 839 || r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_UNSTABLE 840 || r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_STABLE) { 841 // pass 842 } else { 843 fail("Get Frontend Status Readiness returned wrong readiness " + r); 844 } 845 } 846 } else { 847 assertTrue(readiness.isEmpty()); 848 } 849 tuner.cancelTuning(); 850 tuner.close(); 851 tuner = null; 852 } 853 } 854 855 @Test testConfigureDemux()856 public void testConfigureDemux() throws Exception { 857 DemuxCapabilities dc = mTuner.getDemuxCapabilities(); 858 if (dc == null || dc.getFilterTypeCapabilityList().length <= 0) { 859 return; 860 } 861 862 // Test configureDemux with all the valid capabilities and set up the demux info processor 863 mDFMTProcessor.reset(); 864 DemuxInfo di = new DemuxInfo(Filter.TYPE_UNDEFINED); 865 866 for (int caps : dc.getFilterTypeCapabilityList()) { 867 di.setFilterTypes(caps); 868 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 869 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 870 mDFMTProcessor.processEntry(new DemuxFilterTypeInfo(caps)); 871 } 872 873 // Test configureDemux with TYPE_UNDEFINED 874 di.setFilterTypes(Filter.TYPE_UNDEFINED); 875 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 876 assertEquals(Filter.TYPE_UNDEFINED, mTuner.getDesiredDemuxInfo().getFilterTypes()); 877 878 // Validate getCurrentDemuxInfo() returns null 879 assertNull(mTuner.getCurrentDemuxInfo()); 880 881 // Test configureDemux with unsupported cap 882 int nonSupportedCap = mDFMTProcessor.getFirstNonSupportedCap(); 883 di.setFilterTypes(nonSupportedCap); 884 assertEquals(Tuner.RESULT_UNAVAILABLE, mTuner.configureDemux(di)); 885 886 // Now confirm the demux release related behavior 887 // first get any demux resource 888 assertNotNull(mTuner.openDescrambler()); 889 assertNotNull(mTuner.getCurrentDemuxInfo()); 890 // configureDemux with TYPE_UNDEFINED and expect no release 891 di.setFilterTypes(Filter.TYPE_UNDEFINED); 892 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 893 assertEquals(Filter.TYPE_UNDEFINED, mTuner.getDesiredDemuxInfo().getFilterTypes()); 894 assertNotNull(mTuner.getCurrentDemuxInfo()); 895 // configureDemux with null to invoke demux release 896 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(null)); 897 assertEquals(Filter.TYPE_UNDEFINED, mTuner.getDesiredDemuxInfo().getFilterTypes()); 898 assertNull(mTuner.getCurrentDemuxInfo()); 899 900 901 // now through openFilter 902 int cap = mDFMTProcessor.getFirstSupportedCap(0); 903 assertNotEquals(0, cap); 904 Filter f = mTuner.openFilter( 905 cap, getFilterSubTypeForTest(cap), 1000, getExecutor(), getFilterCallback()); 906 assertEquals(cap, mTuner.getDesiredDemuxInfo().getFilterTypes()); 907 assertNotNull(f); 908 assertEquals(cap, mTuner.getCurrentDemuxInfo().getFilterTypes() & cap); 909 910 // configureDemux with TYPE_UNDEFINED and expect no release 911 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 912 assertEquals(Filter.TYPE_UNDEFINED, mTuner.getDesiredDemuxInfo().getFilterTypes()); 913 assertNotNull(mTuner.getCurrentDemuxInfo()); 914 915 // now configureDemux with null to invoke demux release 916 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(null)); 917 assertEquals(Filter.TYPE_UNDEFINED, mTuner.getDesiredDemuxInfo().getFilterTypes()); 918 assertNull(mTuner.getCurrentDemuxInfo()); 919 920 // do additional test if multi bits caps is available 921 int caps = mDFMTProcessor.getSmallestMultiBitsCap(); 922 if (caps != 0) { 923 // configureDemux with multi bits caps and allocate demux 924 di.setFilterTypes(caps); 925 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 926 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 927 assertNotNull(mTuner.openDescrambler()); 928 assertEquals(caps, mTuner.getCurrentDemuxInfo().getFilterTypes()); 929 930 // configure with the same caps - everything should stay the same 931 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 932 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 933 assertEquals(caps, mTuner.getCurrentDemuxInfo().getFilterTypes()); 934 935 // configure with the subset - everything except for the desired cap should stay the 936 // same 937 int partialCap = mDFMTProcessor.getPartialCap(caps); 938 di.setFilterTypes(partialCap); 939 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 940 assertEquals(partialCap, mTuner.getDesiredDemuxInfo().getFilterTypes()); 941 assertEquals(caps, mTuner.getCurrentDemuxInfo().getFilterTypes()); 942 943 // configure with another subset - everything except for the desired cap should stay the 944 // same 945 partialCap = partialCap ^ caps; 946 di.setFilterTypes(partialCap); 947 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 948 assertEquals(partialCap, mTuner.getDesiredDemuxInfo().getFilterTypes()); 949 assertEquals(caps, mTuner.getCurrentDemuxInfo().getFilterTypes()); 950 951 // configure with different cap - should trigger demux relesase 952 int exclusiveCap = mDFMTProcessor.getFirstSupportedCap(caps); 953 di.setFilterTypes(exclusiveCap); 954 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 955 assertEquals(exclusiveCap, mTuner.getDesiredDemuxInfo().getFilterTypes()); 956 assertNull(mTuner.getCurrentDemuxInfo()); 957 958 // now confirm that the openFilter() won't change the desired filter types when it's 959 // called with a type that is a subset of previously set desired filter types. 960 di.setFilterTypes(caps); 961 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 962 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 963 f = mTuner.openFilter( 964 partialCap, getFilterSubTypeForTest(partialCap), 1000, getExecutor(), 965 getFilterCallback()); 966 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 967 assertEquals(caps, mTuner.getCurrentDemuxInfo().getFilterTypes()); 968 assertNotNull(f); 969 } 970 } 971 972 @Test testDemuxReclaim()973 public void testDemuxReclaim() throws Exception { 974 DemuxCapabilities dc = mTuner.getDemuxCapabilities(); 975 if (dc == null || dc.getFilterTypeCapabilityList().length <= 0) { 976 return; 977 } 978 979 // Test configureDemux with all the valid capabilities and set up the demux info processor 980 mDFMTProcessor.reset(); 981 DemuxInfo di = new DemuxInfo(Filter.TYPE_UNDEFINED); 982 for (int caps : dc.getFilterTypeCapabilityList()) { 983 di.setFilterTypes(caps); 984 assertEquals(Tuner.RESULT_SUCCESS, mTuner.configureDemux(di)); 985 assertEquals(caps, mTuner.getDesiredDemuxInfo().getFilterTypes()); 986 mDFMTProcessor.processEntry(new DemuxFilterTypeInfo(caps)); 987 } 988 989 // get the cap that is supported by least number of Demux 990 int cap = mDFMTProcessor.getLeastFrequentCap(); 991 int subType = getFilterSubTypeForTest(cap); 992 assertNotEquals(0, cap); 993 994 List<Tuner> lowerPrioTuners = new ArrayList<Tuner>(); 995 List<Filter> filters = new ArrayList<Filter>(); 996 int numOfCompatibleDemuxes = mDFMTProcessor.getCapCount(cap); 997 mResourceLostCount = 0; 998 Filter filter; 999 for (int i = 0; i < numOfCompatibleDemuxes; i++) { 1000 Tuner tuner = new Tuner(mContext, null, 100); 1001 tuner.setResourceLostListener(getExecutor(), new Tuner.OnResourceLostListener() { 1002 @Override 1003 public void onResourceLost(Tuner tuner) { 1004 synchronized (mResourceLostCountLock) { 1005 mResourceLostCount++; 1006 } 1007 } 1008 }); 1009 filter = tuner.openFilter( 1010 cap, subType, 1000, getExecutor(), getFilterCallback()); 1011 assertNotNull(filter); 1012 assertEquals(cap, tuner.getCurrentDemuxInfo().getFilterTypes() & cap); 1013 1014 filters.add(filter); 1015 lowerPrioTuners.add(tuner); 1016 } 1017 1018 // now claim another demux with higher priority 1019 Tuner highPrioTuner = new Tuner(mContext, null, 200); 1020 filter = highPrioTuner.openFilter( 1021 cap, subType, 1000, getExecutor(), getFilterCallback()); 1022 assertNotNull(filter); 1023 assertEquals(cap, highPrioTuner.getCurrentDemuxInfo().getFilterTypes() & cap); 1024 Thread.sleep(1); 1025 assertEquals(1, mResourceLostCount); 1026 highPrioTuner.close(); 1027 1028 // clean up the resource 1029 for (Tuner t : lowerPrioTuners) { 1030 t.close(); 1031 } 1032 } 1033 1034 @Test testLnb()1035 public void testLnb() throws Exception { 1036 Lnb lnb = mTuner.openLnb(getExecutor(), getLnbCallback()); 1037 if (lnb == null) return; 1038 assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS); 1039 assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS); 1040 assertEquals( 1041 lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS); 1042 lnb.sendDiseqcMessage(new byte[] {1, 2}); 1043 lnb.close(); 1044 } 1045 1046 @Test testLnbAddAndRemoveCallback()1047 public void testLnbAddAndRemoveCallback() throws Exception { 1048 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 1049 Lnb lnb = mTuner.openLnb(getExecutor(), lnbCB1); 1050 if (lnb == null) { 1051 return; 1052 } 1053 1054 assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS); 1055 assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS); 1056 assertEquals( 1057 lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS); 1058 lnb.sendDiseqcMessage(new byte[] {1, 2}); 1059 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1060 lnbCB1.resetOnDiseqcMessageCalled(); 1061 1062 List<Integer> ids = mTuner.getFrontendIds(); 1063 assertFalse(ids.isEmpty()); 1064 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1065 FrontendSettings feSettings = createFrontendSettings(info); 1066 int res = mTuner.tune(feSettings); 1067 assertEquals(Tuner.RESULT_SUCCESS, res); 1068 1069 // create sharee 1070 Tuner sharee = new Tuner(mContext, null, 100); 1071 sharee.shareFrontendFromTuner(mTuner); 1072 TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback(); 1073 1074 // add it as sharee 1075 lnb.addCallback(getExecutor(), lnbCB2); 1076 1077 // check callback 1078 lnb.sendDiseqcMessage(new byte[] {1, 2}); 1079 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1080 lnbCB1.resetOnDiseqcMessageCalled(); 1081 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 1082 lnbCB2.resetOnDiseqcMessageCalled(); 1083 1084 // remove sharee the sharee (should succeed) 1085 assertTrue(lnb.removeCallback(lnbCB2)); 1086 1087 // check callback (only the original owner gets callback 1088 lnb.sendDiseqcMessage(new byte[] {1, 2}); 1089 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1090 lnbCB1.resetOnDiseqcMessageCalled(); 1091 assertFalse(lnbCB2.getOnDiseqcMessageCalled()); 1092 lnbCB2.resetOnDiseqcMessageCalled(); 1093 1094 sharee.close(); 1095 } 1096 1097 @Test testOpenLnbByname()1098 public void testOpenLnbByname() throws Exception { 1099 Lnb lnb = mTuner.openLnbByName("default", getExecutor(), getLnbCallback()); 1100 if (lnb != null) { 1101 lnb.close(); 1102 } 1103 } 1104 1105 @Test testCiCam()1106 public void testCiCam() throws Exception { 1107 // open filter to get demux resource 1108 mTuner.openFilter( 1109 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1110 1111 mTuner.connectCiCam(1); 1112 mTuner.disconnectCiCam(); 1113 } 1114 1115 @Test testFrontendToCiCam()1116 public void testFrontendToCiCam() throws Exception { 1117 // tune to get frontend resource 1118 List<Integer> ids = mTuner.getFrontendIds(); 1119 if (ids == null) return; 1120 assertFalse(ids.isEmpty()); 1121 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1122 int res = mTuner.tune(createFrontendSettings(info)); 1123 assertEquals(Tuner.RESULT_SUCCESS, res); 1124 1125 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1126 // TODO: get real CiCam id from MediaCas 1127 // only tuner hal1.1 support CiCam 1128 res = mTuner.connectFrontendToCiCam(0); 1129 if (res != Tuner.INVALID_LTS_ID) 1130 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_SUCCESS); 1131 } 1132 } 1133 1134 @Test testRemoveOutputPid()1135 public void testRemoveOutputPid() throws Exception { 1136 // Test w/o active frontend 1137 try { 1138 int status = mTuner.removeOutputPid(10); 1139 if (TunerVersionChecker.isHigherOrEqualVersionTo( 1140 TunerVersionChecker.TUNER_VERSION_2_0)) { 1141 fail("Remove output PID should throw IllegalStateException."); 1142 } else { 1143 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 1144 } 1145 } catch (IllegalStateException e) { 1146 // pass 1147 } 1148 1149 // tune to get frontend resource 1150 List<Integer> ids = mTuner.getFrontendIds(); 1151 if (ids == null) 1152 return; 1153 assertFalse(ids.isEmpty()); 1154 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1155 int res = mTuner.tune(createFrontendSettings(info)); 1156 assertEquals(Tuner.RESULT_SUCCESS, res); 1157 1158 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1159 // TODO: get real CiCam id from MediaCas 1160 res = mTuner.connectFrontendToCiCam(0); 1161 } else { 1162 assertEquals(Tuner.INVALID_LTS_ID, mTuner.connectFrontendToCiCam(0)); 1163 } 1164 1165 int status = mTuner.removeOutputPid(10); 1166 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 1167 if (status != Tuner.RESULT_SUCCESS) { 1168 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 1169 } 1170 } else { 1171 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 1172 } 1173 1174 if (res != Tuner.INVALID_LTS_ID) { 1175 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_SUCCESS); 1176 } else { 1177 // Make sure the connectFrontendToCiCam only fails because the current device 1178 // does not support connecting frontend to cicam 1179 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_UNAVAILABLE); 1180 } 1181 } 1182 1183 @Test testAvSyncId()1184 public void testAvSyncId() throws Exception { 1185 // open filter to get demux resource 1186 Filter f = mTuner.openFilter( 1187 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 1188 assertNotNull(f); 1189 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1190 Settings settings = AvSettings 1191 .builder(Filter.TYPE_TS, true) 1192 .setPassthrough(false) 1193 .setUseSecureMemory(false) 1194 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 1195 .build(); 1196 FilterConfiguration config = TsFilterConfiguration 1197 .builder() 1198 .setTpid(10) 1199 .setSettings(settings) 1200 .build(); 1201 f.configure(config); 1202 int id = mTuner.getAvSyncHwId(f); 1203 if (id != Tuner.INVALID_AV_SYNC_ID) { 1204 assertNotEquals(Tuner.INVALID_TIMESTAMP, mTuner.getAvSyncTime(id)); 1205 } 1206 } 1207 1208 @Test testReadFilter()1209 public void testReadFilter() throws Exception { 1210 Filter f = mTuner.openFilter( 1211 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1212 assertNotNull(f); 1213 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1214 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1215 assertNotEquals(Tuner.INVALID_FILTER_ID_LONG, f.getIdLong()); 1216 } else { 1217 assertEquals(Tuner.INVALID_FILTER_ID_LONG, f.getIdLong()); 1218 } 1219 1220 Settings settings = SectionSettingsWithTableInfo 1221 .builder(Filter.TYPE_TS) 1222 .setTableId(2) 1223 .setVersion(1) 1224 .setCrcEnabled(true) 1225 .setRaw(false) 1226 .setRepeat(false) 1227 .build(); 1228 FilterConfiguration config = TsFilterConfiguration 1229 .builder() 1230 .setTpid(10) 1231 .setSettings(settings) 1232 .build(); 1233 f.configure(config); 1234 f.setMonitorEventMask( 1235 Filter.MONITOR_EVENT_SCRAMBLING_STATUS | Filter.MONITOR_EVENT_IP_CID_CHANGE); 1236 1237 // Tune a frontend before start the filter 1238 List<Integer> ids = mTuner.getFrontendIds(); 1239 if (ids == null) return; 1240 assertFalse(ids.isEmpty()); 1241 1242 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1243 int res = mTuner.tune(createFrontendSettings(info)); 1244 assertEquals(Tuner.RESULT_SUCCESS, res); 1245 1246 f.start(); 1247 f.flush(); 1248 f.read(new byte[3], 0, 3); 1249 f.stop(); 1250 f.close(); 1251 1252 res = mTuner.cancelTuning(); 1253 assertEquals(Tuner.RESULT_SUCCESS, res); 1254 } 1255 1256 @Test testAudioFilterStreamTypeConfig()1257 public void testAudioFilterStreamTypeConfig() throws Exception { 1258 Filter f = mTuner.openFilter( 1259 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 1260 assertNotNull(f); 1261 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1262 1263 Settings settings = AvSettings 1264 .builder(Filter.TYPE_TS, true) 1265 .setPassthrough(false) 1266 .setUseSecureMemory(false) 1267 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 1268 .build(); 1269 FilterConfiguration config = TsFilterConfiguration 1270 .builder() 1271 .setTpid(10) 1272 .setSettings(settings) 1273 .build(); 1274 f.configure(config); 1275 1276 // Tune a frontend before start the filter 1277 List<Integer> ids = mTuner.getFrontendIds(); 1278 if (ids == null) return; 1279 assertFalse(ids.isEmpty()); 1280 1281 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1282 int res = mTuner.tune(createFrontendSettings(info)); 1283 assertEquals(Tuner.RESULT_SUCCESS, res); 1284 1285 f.start(); 1286 f.flush(); 1287 f.stop(); 1288 f.close(); 1289 1290 res = mTuner.cancelTuning(); 1291 assertEquals(Tuner.RESULT_SUCCESS, res); 1292 } 1293 1294 @Test testTimeFilter()1295 public void testTimeFilter() throws Exception { 1296 if (!mTuner.getDemuxCapabilities().isTimeFilterSupported()) return; 1297 TimeFilter f = mTuner.openTimeFilter(); 1298 assertNotNull(f); 1299 f.setCurrentTimestamp(0); 1300 assertNotEquals(Tuner.INVALID_TIMESTAMP, f.getTimeStamp()); 1301 assertNotEquals(Tuner.INVALID_TIMESTAMP, f.getSourceTime()); 1302 f.clearTimestamp(); 1303 f.close(); 1304 } 1305 1306 @Test testIpFilter()1307 public void testIpFilter() throws Exception { 1308 Filter f = mTuner.openFilter( 1309 Filter.TYPE_IP, Filter.SUBTYPE_IP, 1000, getExecutor(), getFilterCallback()); 1310 if (f == null) return; 1311 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1312 1313 FilterConfiguration config = IpFilterConfiguration 1314 .builder() 1315 .setSrcIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 0, 1}) 1316 .setDstIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 3, 4}) 1317 .setSrcPort(33) 1318 .setDstPort(23) 1319 .setPassthrough(false) 1320 .setSettings(null) 1321 .setIpFilterContextId(1) 1322 .build(); 1323 f.configure(config); 1324 1325 // Tune a frontend before start the filter 1326 List<Integer> ids = mTuner.getFrontendIds(); 1327 if (ids == null) return; 1328 assertFalse(ids.isEmpty()); 1329 1330 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1331 int res = mTuner.tune(createFrontendSettings(info)); 1332 assertEquals(Tuner.RESULT_SUCCESS, res); 1333 1334 f.start(); 1335 f.stop(); 1336 f.close(); 1337 1338 res = mTuner.cancelTuning(); 1339 assertEquals(Tuner.RESULT_SUCCESS, res); 1340 } 1341 1342 @Test testAlpSectionFilterConfig()1343 public void testAlpSectionFilterConfig() throws Exception { 1344 Filter f = mTuner.openFilter( 1345 Filter.TYPE_ALP, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1346 if (f == null) return; 1347 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1348 1349 SectionSettingsWithSectionBits settings = 1350 SectionSettingsWithSectionBits 1351 .builder(Filter.TYPE_TS) 1352 .setCrcEnabled(true) 1353 .setRepeat(false) 1354 .setRaw(false) 1355 .setFilter(new byte[]{2, 3, 4}) 1356 .setMask(new byte[]{7, 6, 5, 4}) 1357 .setMode(new byte[]{22, 55, 33}) 1358 .build(); 1359 AlpFilterConfiguration config = 1360 AlpFilterConfiguration 1361 .builder() 1362 .setPacketType(AlpFilterConfiguration.PACKET_TYPE_COMPRESSED) 1363 .setLengthType(AlpFilterConfiguration.LENGTH_TYPE_WITH_ADDITIONAL_HEADER) 1364 .setSettings(settings) 1365 .build(); 1366 f.configure(config); 1367 f.start(); 1368 f.stop(); 1369 f.close(); 1370 } 1371 1372 @Test testMmtpPesFilterConfig()1373 public void testMmtpPesFilterConfig() throws Exception { 1374 Filter f = mTuner.openFilter( 1375 Filter.TYPE_MMTP, Filter.SUBTYPE_PES, 1000, getExecutor(), getFilterCallback()); 1376 if (f == null) return; 1377 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1378 1379 PesSettings settings = 1380 PesSettings 1381 .builder(Filter.TYPE_TS) 1382 .setStreamId(3) 1383 .setRaw(false) 1384 .build(); 1385 MmtpFilterConfiguration config = 1386 MmtpFilterConfiguration 1387 .builder() 1388 .setMmtpPacketId(3) 1389 .setSettings(settings) 1390 .build(); 1391 f.configure(config); 1392 f.start(); 1393 f.stop(); 1394 f.close(); 1395 } 1396 1397 @Test testMmtpDownloadFilterConfig()1398 public void testMmtpDownloadFilterConfig() throws Exception { 1399 Filter f = mTuner.openFilter( 1400 Filter.TYPE_MMTP, Filter.SUBTYPE_DOWNLOAD, 1401 1000, getExecutor(), getFilterCallback()); 1402 if (f == null) return; 1403 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1404 1405 DownloadSettings.Builder builder = DownloadSettings.builder(Filter.TYPE_MMTP); 1406 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1407 builder.setUseDownloadId(true); 1408 } 1409 builder.setDownloadId(2); 1410 DownloadSettings settings = builder.build(); 1411 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1412 assertEquals(settings.useDownloadId(), true); 1413 } else { 1414 assertEquals(settings.useDownloadId(), false); 1415 } 1416 assertEquals(settings.getDownloadId(), 2); 1417 1418 MmtpFilterConfiguration config = 1419 MmtpFilterConfiguration 1420 .builder() 1421 .setMmtpPacketId(3) 1422 .setSettings(settings) 1423 .build(); 1424 f.configure(config); 1425 f.start(); 1426 f.stop(); 1427 f.close(); 1428 } 1429 1430 @Test testTsAvFilterConfig()1431 public void testTsAvFilterConfig() throws Exception { 1432 Filter f = mTuner.openFilter( 1433 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 1434 assertNotNull(f); 1435 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1436 1437 AvSettings settings = 1438 AvSettings 1439 .builder(Filter.TYPE_TS, true) // is Audio 1440 .setPassthrough(false) 1441 .setUseSecureMemory(false) 1442 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 1443 .build(); 1444 TsFilterConfiguration config = 1445 TsFilterConfiguration 1446 .builder() 1447 .setTpid(521) 1448 .setSettings(settings) 1449 .build(); 1450 f.configure(config); 1451 f.start(); 1452 f.stop(); 1453 f.close(); 1454 } 1455 1456 @Test testTsRecordFilterConfig()1457 public void testTsRecordFilterConfig() throws Exception { 1458 Filter f = mTuner.openFilter( 1459 Filter.TYPE_TS, Filter.SUBTYPE_RECORD, 1000, getExecutor(), getFilterCallback()); 1460 assertNotNull(f); 1461 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1462 1463 RecordSettings settings = 1464 RecordSettings 1465 .builder(Filter.TYPE_TS) 1466 .setTsIndexMask( 1467 RecordSettings.TS_INDEX_FIRST_PACKET 1468 | RecordSettings.TS_INDEX_PRIVATE_DATA) 1469 .setScIndexType(RecordSettings.INDEX_TYPE_SC) 1470 .setScIndexMask(RecordSettings.SC_INDEX_B_SLICE) 1471 .build(); 1472 TsFilterConfiguration config = 1473 TsFilterConfiguration 1474 .builder() 1475 .setTpid(521) 1476 .setSettings(settings) 1477 .build(); 1478 f.configure(config); 1479 f.start(); 1480 f.stop(); 1481 f.close(); 1482 } 1483 1484 @Test testTlvTlvFilterConfig()1485 public void testTlvTlvFilterConfig() throws Exception { 1486 Filter f = mTuner.openFilter( 1487 Filter.TYPE_TLV, Filter.SUBTYPE_TLV, 1000, getExecutor(), getFilterCallback()); 1488 if (f == null) return; 1489 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1490 1491 TlvFilterConfiguration config = 1492 TlvFilterConfiguration 1493 .builder() 1494 .setPacketType(TlvFilterConfiguration.PACKET_TYPE_IPV4) 1495 .setCompressedIpPacket(true) 1496 .setPassthrough(false) 1497 .setSettings(null) 1498 .build(); 1499 f.configure(config); 1500 f.start(); 1501 f.stop(); 1502 f.close(); 1503 } 1504 1505 @Test testDescrambler()1506 public void testDescrambler() throws Exception { 1507 Descrambler d = mTuner.openDescrambler(); 1508 byte[] keyToken = new byte[] {1, 3, 2}; 1509 assertNotNull(d); 1510 Filter f = mTuner.openFilter( 1511 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1512 assertTrue(d.isValidKeyToken(keyToken)); 1513 d.setKeyToken(keyToken); 1514 d.addPid(Descrambler.PID_TYPE_T, 1, f); 1515 d.removePid(Descrambler.PID_TYPE_T, 1, f); 1516 f.close(); 1517 d.close(); 1518 } 1519 1520 @Test testDescramblerKeyTokenValidator()1521 public void testDescramblerKeyTokenValidator() throws Exception { 1522 byte[] invalidToken = new byte[17]; 1523 byte[] validToken = new byte[] {1, 3, 2}; 1524 assertTrue(Descrambler.isValidKeyToken(validToken)); 1525 assertTrue(Descrambler.isValidKeyToken(Tuner.VOID_KEYTOKEN)); 1526 assertFalse(Descrambler.isValidKeyToken(invalidToken)); 1527 } 1528 1529 @Test testOpenDvrRecorder()1530 public void testOpenDvrRecorder() throws Exception { 1531 DvrRecorder d = mTuner.openDvrRecorder(100, getExecutor(), getRecordListener()); 1532 assertNotNull(d); 1533 d.close(); 1534 } 1535 1536 @Test testOpenDvPlayback()1537 public void testOpenDvPlayback() throws Exception { 1538 DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener()); 1539 assertNotNull(d); 1540 d.close(); 1541 } 1542 1543 @Test testDemuxCapabilities()1544 public void testDemuxCapabilities() throws Exception { 1545 DemuxCapabilities d = mTuner.getDemuxCapabilities(); 1546 assertNotNull(d); 1547 1548 d.getDemuxCount(); 1549 d.getRecordCount(); 1550 d.getPlaybackCount(); 1551 d.getTsFilterCount(); 1552 d.getSectionFilterCount(); 1553 d.getAudioFilterCount(); 1554 d.getVideoFilterCount(); 1555 d.getPesFilterCount(); 1556 d.getPcrFilterCount(); 1557 d.getSectionFilterLength(); 1558 d.getFilterCapabilities(); 1559 d.getLinkCapabilities(); 1560 d.isTimeFilterSupported(); 1561 d.getFilterTypeCapabilityList(); 1562 } 1563 1564 @Test testResourceLostListener()1565 public void testResourceLostListener() throws Exception { 1566 mTuner.setResourceLostListener(getExecutor(), new Tuner.OnResourceLostListener() { 1567 @Override 1568 public void onResourceLost(Tuner tuner) { 1569 } 1570 }); 1571 mTuner.clearResourceLostListener(); 1572 } 1573 1574 @Test testOnTuneEventListener()1575 public void testOnTuneEventListener() throws Exception { 1576 mTuner.setOnTuneEventListener(getExecutor(), new OnTuneEventListener() { 1577 @Override 1578 public void onTuneEvent(int tuneEvent) { 1579 } 1580 }); 1581 mTuner.clearOnTuneEventListener(); 1582 } 1583 1584 @Test testUpdateResourcePriority()1585 public void testUpdateResourcePriority() throws Exception { 1586 mTuner.updateResourcePriority(100, 20); 1587 } 1588 1589 @Test testResourceReclaimed()1590 public void testResourceReclaimed() throws Exception { 1591 List<Integer> ids = mTuner.getFrontendIds(); 1592 assertFalse(ids.isEmpty()); 1593 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1594 FrontendSettings feSettings = createFrontendSettings(info); 1595 1596 // first tune with mTuner to acquire resource 1597 int res = mTuner.tune(feSettings); 1598 assertEquals(Tuner.RESULT_SUCCESS, res); 1599 assertNotNull(mTuner.getFrontendInfo()); 1600 1601 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1602 Tuner higherPrioTuner = new Tuner(mContext, null, 200); 1603 res = higherPrioTuner.tune(feSettings); 1604 assertEquals(Tuner.RESULT_SUCCESS, res); 1605 assertNotNull(higherPrioTuner.getFrontendInfo()); 1606 1607 higherPrioTuner.close(); 1608 } 1609 1610 // TODO: change this to use ITunerResourceTestServer 1611 @Test testResourceReclaimedDifferentThread()1612 public void testResourceReclaimedDifferentThread() throws Exception { 1613 List<Integer> ids = mTuner.getFrontendIds(); 1614 assertFalse(ids.isEmpty()); 1615 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1616 FrontendSettings feSettings = createFrontendSettings(info); 1617 1618 // first tune with mTuner to acquire resource 1619 int res = mTuner.tune(feSettings); 1620 assertEquals(Tuner.RESULT_SUCCESS, res); 1621 assertNotNull(mTuner.getFrontendInfo()); 1622 1623 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1624 TunerHandler tunerHandler = createTunerHandler(null); 1625 Message msgCreate = new Message(); 1626 msgCreate.what = MSG_TUNER_HANDLER_CREATE; 1627 msgCreate.arg1 = 200; 1628 tunerHandler.sendMessage(msgCreate); 1629 mTunerHandlerTaskComplete.block(); 1630 mTunerHandlerTaskComplete.close(); 1631 1632 Message msgTune = new Message(); 1633 msgTune.what = MSG_TUNER_HANDLER_TUNE; 1634 msgTune.obj = (Object) feSettings; 1635 tunerHandler.sendMessage(msgTune); 1636 1637 // call mTuner.close in parallel 1638 int sleepMS = 1; 1639 //int sleepMS = (int) (Math.random() * 3.); 1640 try { 1641 Thread.sleep(sleepMS); 1642 } catch (Exception e) { } // ignore 1643 mTuner.close(); 1644 mTuner = null; 1645 1646 mTunerHandlerTaskComplete.block(); 1647 mTunerHandlerTaskComplete.close(); 1648 res = tunerHandler.getResult(); 1649 assertEquals(Tuner.RESULT_SUCCESS, res); 1650 1651 Tuner higherPrioTuner = tunerHandler.getTuner(); 1652 assertNotNull(higherPrioTuner.getFrontendInfo()); 1653 1654 Message msgClose = new Message(); 1655 msgClose.what = MSG_TUNER_HANDLER_CLOSE; 1656 tunerHandler.sendMessage(msgClose); 1657 1658 } 1659 1660 @Test testResourceReclaimedDifferentProcess()1661 public void testResourceReclaimedDifferentProcess() throws Exception { 1662 List<Integer> ids = mTuner.getFrontendIds(); 1663 int frontendIndex = 0; 1664 assertFalse(ids.isEmpty()); 1665 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(frontendIndex)); 1666 FrontendSettings feSettings = createFrontendSettings(info); 1667 1668 // set up the test server 1669 TunerResourceTestServiceConnection connection = new TunerResourceTestServiceConnection(); 1670 ITunerResourceTestServer tunerResourceTestServer = null; 1671 Intent intent = new Intent(mContext, TunerResourceTestService.class); 1672 1673 // get the TunerResourceTestService 1674 mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE); 1675 tunerResourceTestServer = connection.getService(); 1676 1677 // CASE1 - normal reclaim 1678 // 1679 // first tune with mTuner to acquire resource 1680 int res = mTuner.tune(feSettings); 1681 boolean tunerReclaimed = false; 1682 assertEquals(Tuner.RESULT_SUCCESS, res); 1683 assertNotNull(mTuner.getFrontendInfo()); 1684 1685 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1686 1687 // create higher priority tuner 1688 tunerResourceTestServer.createTuner(200); 1689 1690 // now tune on higher priority tuner to get mTuner reclaimed 1691 res = tunerResourceTestServer.tune(frontendIndex); 1692 assertEquals(Tuner.RESULT_SUCCESS, res); 1693 1694 try { 1695 int[] statusCapabilities = info.getStatusCapabilities(); 1696 mTuner.getFrontendStatus(statusCapabilities); 1697 1698 } catch (IllegalStateException e) { 1699 tunerReclaimed = true; 1700 mTuner.close(); 1701 mTuner = null; 1702 } 1703 1704 // confirm if the mTuner is reclaimed 1705 assertTrue(tunerReclaimed); 1706 1707 tunerResourceTestServer.closeTuner(); 1708 assertTrue(tunerResourceTestServer.verifyTunerIsNull()); 1709 1710 1711 // CASE2 - race between Tuner#close() and reclaim 1712 mTuner = new Tuner(mContext, null, 100); 1713 res = mTuner.tune(feSettings); 1714 assertEquals(Tuner.RESULT_SUCCESS, res); 1715 assertNotNull(mTuner.getFrontendInfo()); 1716 1717 tunerResourceTestServer.createTuner(200); 1718 tunerResourceTestServer.tuneAsync(frontendIndex); 1719 1720 // adjust timing to induce race/deadlock 1721 int sleepMS = 4; 1722 //int sleepMS = (int) (Math.random() * 5.); 1723 try { 1724 Thread.sleep(sleepMS); 1725 } catch (Exception e) { } // ignore 1726 mTuner.close(); 1727 mTuner = null; 1728 1729 tunerResourceTestServer.closeTuner(); 1730 1731 // unbind 1732 mContext.unbindService(connection); 1733 } 1734 1735 @Test testApplyFrontend()1736 public void testApplyFrontend() throws Exception { 1737 List<FrontendInfo> frontendInfos = mTuner.getAvailableFrontendInfos(); 1738 if (frontendInfos == null) return; 1739 assertFalse(frontendInfos.isEmpty()); 1740 1741 FrontendInfo frontendInfo = frontendInfos.get(0); 1742 int result = mTuner.applyFrontend(frontendInfo); 1743 assertEquals(Tuner.RESULT_SUCCESS, result); 1744 1745 // Request a frontend again cases 1746 FrontendInfo secondFrontend = null; 1747 for (FrontendInfo info: frontendInfos) { 1748 result = mTuner.applyFrontend(info); 1749 assertEquals(Tuner.RESULT_INVALID_STATE, result); 1750 } 1751 } 1752 1753 @Test testShareFrontendFromTuner()1754 public void testShareFrontendFromTuner() throws Exception { 1755 Tuner tuner100 = new Tuner(mContext, null, 100); 1756 List<Integer> ids = tuner100.getFrontendIds(); 1757 assertFalse(ids.isEmpty()); 1758 FrontendInfo info = tuner100.getFrontendInfoById(ids.get(0)); 1759 FrontendSettings feSettings = createFrontendSettings(info); 1760 int[] statusTypes = {1}; 1761 boolean exceptionThrown = false; 1762 int res; 1763 1764 // CASE1: check resource reclaim while sharee's priority < owner's priority 1765 // let tuner100 share from tuner200 1766 Tuner tuner200 = new Tuner(mContext, null, 200); 1767 res = tuner200.tune(feSettings); 1768 assertEquals(Tuner.RESULT_SUCCESS, res); 1769 1770 info = tuner200.getFrontendInfoById(ids.get(0)); 1771 res = tuner200.tune(feSettings); 1772 assertEquals(Tuner.RESULT_SUCCESS, res); 1773 1774 tuner100.shareFrontendFromTuner(tuner200); 1775 // call openFilter to trigger ITunerDemux.setFrontendDataSourceById() 1776 Filter f = tuner100.openFilter( 1777 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1778 assertNotNull(f); 1779 1780 // setup onTuneCallback 1781 TunerTestOnTuneEventListener cb100 = new TunerTestOnTuneEventListener(); 1782 TunerTestOnTuneEventListener cb200 = new TunerTestOnTuneEventListener(); 1783 1784 // tune again on the owner 1785 info = tuner200.getFrontendInfoById(ids.get(1)); 1786 tuner100.setOnTuneEventListener(getExecutor(), cb100); 1787 tuner200.setOnTuneEventListener(getExecutor(), cb200); 1788 res = tuner200.tune(feSettings); 1789 assertEquals(Tuner.RESULT_SUCCESS, res); 1790 assertEquals(OnTuneEventListener.SIGNAL_LOCKED, cb100.getLastTuneEvent()); 1791 assertEquals(OnTuneEventListener.SIGNAL_LOCKED, cb200.getLastTuneEvent()); 1792 tuner100.clearOnTuneEventListener(); 1793 tuner200.clearOnTuneEventListener(); 1794 1795 // now let the higher priority tuner steal the resource 1796 Tuner tuner300 = new Tuner(mContext, null, 300); 1797 res = tuner300.tune(feSettings); 1798 assertEquals(Tuner.RESULT_SUCCESS, res); 1799 1800 // confirm owner & sharee's resource gets reclaimed by confirming an exception is thrown 1801 exceptionThrown = false; 1802 try { 1803 tuner200.getFrontendStatus(statusTypes); 1804 } catch (Exception e) { 1805 exceptionThrown = true; 1806 } 1807 assertTrue(exceptionThrown); 1808 1809 exceptionThrown = false; 1810 try { 1811 tuner100.getFrontendStatus(statusTypes); 1812 } catch (Exception e) { 1813 exceptionThrown = true; 1814 } 1815 assertTrue(exceptionThrown); 1816 1817 tuner100.close(); 1818 tuner200.close(); 1819 tuner300.close(); 1820 1821 1822 // CASE2: check resource reclaim fail when sharee's priority > new requester 1823 tuner100 = new Tuner(mContext, null, 100); 1824 res = tuner100.tune(feSettings); 1825 assertEquals(Tuner.RESULT_SUCCESS, res); 1826 1827 tuner300 = new Tuner(mContext, null, 300); 1828 tuner300.shareFrontendFromTuner(tuner100); 1829 f = tuner100.openFilter( 1830 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1831 assertNotNull(f); 1832 1833 tuner200 = new Tuner(mContext, null, 200); 1834 res = tuner200.tune(feSettings); 1835 assertNotEquals(Tuner.RESULT_SUCCESS, res); 1836 1837 // confirm the original tuner is still intact 1838 res = tuner100.tune(feSettings); 1839 assertEquals(Tuner.RESULT_SUCCESS, res); 1840 1841 tuner100.close(); 1842 tuner200.close(); 1843 tuner300.close(); 1844 } 1845 testTransferFeOwnershipSingleTuner()1846 private void testTransferFeOwnershipSingleTuner() { 1847 List<Integer> ids = mTuner.getFrontendIds(); 1848 if (ids == null) { 1849 return; 1850 } 1851 assertFalse(ids.isEmpty()); 1852 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1853 FrontendSettings feSettings = createFrontendSettings(info); 1854 1855 // SCENARIO 1 - transfer and close the previous owner 1856 1857 // First create a tuner and tune() to acquire frontend resource 1858 Tuner tunerA = new Tuner(mContext, null, 100); 1859 int res = tunerA.tune(feSettings); 1860 assertEquals(Tuner.RESULT_SUCCESS, res); 1861 1862 // Create another tuner and share frontend from tunerA 1863 Tuner tunerB = new Tuner(mContext, null, 500); 1864 tunerB.shareFrontendFromTuner(tunerA); 1865 DvrRecorder d = tunerB.openDvrRecorder(100, getExecutor(), getRecordListener()); 1866 assertNotNull(d); 1867 1868 // Call transferOwner in the wrong configurations and confirm it fails 1869 assertEquals(Tuner.RESULT_INVALID_STATE, tunerB.transferOwner(tunerA)); 1870 Tuner nonSharee = new Tuner(mContext, null, 300); 1871 assertEquals(Tuner.RESULT_INVALID_STATE, tunerA.transferOwner(nonSharee)); 1872 nonSharee.close(); 1873 1874 // Now call it correctly to transfer ownership from tunerA to tunerB 1875 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1876 1877 // Close the original owner (tunerA) 1878 tunerA.close(); 1879 1880 // Confirm the new owner (tunerB) is still functional 1881 assertNotNull(tunerB.getFrontendInfo()); 1882 1883 // Close the new owner (tunerB) 1884 d.close(); 1885 tunerB.close(); 1886 1887 // SCENARIO 2 - transfer and closeFrontend and tune on the previous owner 1888 1889 // First create a tuner and tune() to acquire frontend resource 1890 tunerA = new Tuner(mContext, null, 200); 1891 res = tunerA.tune(feSettings); 1892 assertEquals(Tuner.RESULT_SUCCESS, res); 1893 1894 // Create another tuner and share frontend from tunerA 1895 tunerB = new Tuner(mContext, null, 100); 1896 tunerB.shareFrontendFromTuner(tunerA); 1897 assertNotNull(tunerB.getFrontendInfo()); 1898 1899 // Transfer ownership from tunerA to tunerB 1900 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1901 1902 // Close frontend for the original owner (tunerA) 1903 tunerA.closeFrontend(); 1904 1905 // Confirm tune works without going through Tuner.close() even after transferOwner() 1906 // The purpose isn't to get tunerB's frontend revoked, but doing so as singletuner 1907 // based test has wider coverage 1908 res = tunerA.tune(feSettings); // this should reclaim tunerB 1909 assertEquals(Tuner.RESULT_SUCCESS, res); 1910 1911 // Confirm tuberB is revoked 1912 assertNull(tunerB.getFrontendInfo()); 1913 1914 // Close tunerA 1915 tunerA.close(); 1916 1917 // close TunerB just in case 1918 tunerB.close(); 1919 } 1920 testTransferFeAndCiCamOwnership()1921 private void testTransferFeAndCiCamOwnership() { 1922 List<Integer> ids = mTuner.getFrontendIds(); 1923 assertNotNull(ids); 1924 assertFalse(ids.isEmpty()); 1925 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1926 FrontendSettings feSettings = createFrontendSettings(info); 1927 1928 // Create tuner and tune to get frontend resource 1929 Tuner tunerA = new Tuner(mContext, null, 100); 1930 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1931 1932 int ciCamId = 0; 1933 boolean linkCiCamToFrontendSupported = false; 1934 1935 // connect CiCam to Frontend 1936 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1937 // TODO: get real CiCam id from MediaCas 1938 assertEquals(Tuner.RESULT_SUCCESS, tunerA.connectFrontendToCiCam(ciCamId)); 1939 linkCiCamToFrontendSupported = true; 1940 } else { 1941 assertEquals(Tuner.INVALID_LTS_ID, tunerA.connectFrontendToCiCam(ciCamId)); 1942 } 1943 1944 // connect CiCam to Demux 1945 assertEquals(Tuner.RESULT_SUCCESS, tunerA.connectCiCam(ciCamId)); 1946 1947 // start another tuner and connect the same CiCam to its own demux 1948 Tuner tunerB = new Tuner(mContext, null, 400); 1949 tunerB.shareFrontendFromTuner(tunerA); 1950 assertNotNull(tunerB.getFrontendInfo()); 1951 assertEquals(Tuner.RESULT_SUCCESS, tunerB.connectCiCam(ciCamId)); 1952 1953 // unlink CiCam to Demux in tunerA and transfer ownership 1954 assertEquals(Tuner.RESULT_SUCCESS, tunerA.disconnectCiCam()); 1955 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1956 1957 // close the original owner 1958 tunerA.close(); 1959 1960 // disconnect CiCam from demux 1961 assertEquals(Tuner.RESULT_SUCCESS, tunerB.disconnectCiCam()); 1962 1963 // let Tuner.close() handle the release of CiCam 1964 tunerB.close(); 1965 1966 // now that the CiCam is released, disconnectFrontendToCiCam() should fail 1967 assertEquals(Tuner.RESULT_INVALID_STATE, tunerB.disconnectFrontendToCiCam(ciCamId)); 1968 1969 // see if tune still works just in case 1970 tunerA = new Tuner(mContext, null, 100); 1971 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1972 tunerA.close(); 1973 } 1974 testTransferFeAndLnbOwnership()1975 private void testTransferFeAndLnbOwnership() { 1976 List<Integer> ids = mTuner.getFrontendIds(); 1977 assertNotNull(ids); 1978 assertFalse(ids.isEmpty()); 1979 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1980 FrontendSettings feSettings = createFrontendSettings(info); 1981 1982 // Create tuner and tune to acquire frontend resource 1983 Tuner tunerA = new Tuner(mContext, null, 100); 1984 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1985 1986 // Open Lnb and check the callback 1987 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 1988 Lnb lnbA = tunerA.openLnb(getExecutor(), lnbCB1); 1989 assertNotNull(lnbA); 1990 lnbA.setVoltage(Lnb.VOLTAGE_5V); 1991 lnbA.setTone(Lnb.TONE_CONTINUOUS); 1992 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 1993 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1994 lnbCB1.resetOnDiseqcMessageCalled(); 1995 1996 // Create another tuner and share from tunerB 1997 Tuner tunerB = new Tuner(mContext, null, 300); 1998 tunerB.shareFrontendFromTuner(tunerA); 1999 2000 // add sharee and check the callback 2001 TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback(); 2002 lnbA.addCallback(getExecutor(), lnbCB2); 2003 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 2004 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 2005 lnbCB1.resetOnDiseqcMessageCalled(); 2006 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 2007 lnbCB2.resetOnDiseqcMessageCalled(); 2008 2009 // transfer owner and check callback 2010 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 2011 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 2012 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 2013 lnbCB1.resetOnDiseqcMessageCalled(); 2014 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 2015 lnbCB2.resetOnDiseqcMessageCalled(); 2016 2017 // remove the owner callback (just for testing) 2018 assertTrue(lnbA.removeCallback(lnbCB2)); 2019 2020 // remove sharee and check callback 2021 assertTrue(lnbA.removeCallback(lnbCB1)); 2022 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 2023 assertFalse(lnbCB1.getOnDiseqcMessageCalled()); 2024 lnbCB1.resetOnDiseqcMessageCalled(); 2025 assertFalse(lnbCB2.getOnDiseqcMessageCalled()); 2026 lnbCB2.resetOnDiseqcMessageCalled(); 2027 2028 // close the original owner 2029 tunerA.close(); 2030 2031 // confirm the new owner is still intact 2032 int[] statusCapabilities = info.getStatusCapabilities(); 2033 assertNotNull(statusCapabilities); 2034 FrontendStatus status = tunerB.getFrontendStatus(statusCapabilities); 2035 assertNotNull(status); 2036 2037 tunerB.close(); 2038 } 2039 2040 @Test testTransferOwner()2041 public void testTransferOwner() throws Exception { 2042 testTransferFeOwnershipSingleTuner(); 2043 testTransferFeAndCiCamOwnership(); 2044 testTransferFeAndLnbOwnership(); 2045 } 2046 2047 @Test testClose()2048 public void testClose() throws Exception { 2049 Tuner other = new Tuner(mContext, null, 100); 2050 2051 List<Integer> ids = other.getFrontendIds(); 2052 if (ids == null) return; 2053 assertFalse(ids.isEmpty()); 2054 FrontendInfo info = other.getFrontendInfoById(ids.get(0)); 2055 2056 FrontendSettings feSettings = createFrontendSettings(info); 2057 int res = other.tune(feSettings); 2058 assertEquals(Tuner.RESULT_SUCCESS, res); 2059 assertNotNull(other.getFrontendInfo()); 2060 2061 other.close(); 2062 2063 // make sure pre-existing tuner is still functional 2064 res = mTuner.applyFrontend(info); 2065 assertEquals(Tuner.RESULT_SUCCESS, res); 2066 assertNotNull(mTuner.getFrontendInfo()); 2067 mTuner.closeFrontend(); 2068 res = mTuner.tune(feSettings); 2069 assertEquals(Tuner.RESULT_SUCCESS, res); 2070 assertNotNull(mTuner.getFrontendInfo()); 2071 2072 // Frontend sharing scenario 1: close owner first 2073 // create sharee 2074 Tuner sharee = new Tuner(mContext, null, 100); 2075 sharee.shareFrontendFromTuner(mTuner); 2076 2077 // close the owner 2078 mTuner.close(); 2079 mTuner = null; 2080 2081 // check the frontend of sharee is also released 2082 assertNull(sharee.getFrontendInfo()); 2083 2084 sharee.close(); 2085 2086 // Frontend sharing scenario 2: close sharee first 2087 // create owner first 2088 mTuner = new Tuner(mContext, null, 100); 2089 res = mTuner.tune(feSettings); 2090 assertEquals(Tuner.RESULT_SUCCESS, res); 2091 2092 // create sharee 2093 sharee = new Tuner(mContext, null, 100); 2094 sharee.shareFrontendFromTuner(mTuner); 2095 2096 // close sharee 2097 sharee.close(); 2098 2099 // confirm owner is still intact 2100 int[] statusCapabilities = info.getStatusCapabilities(); 2101 assertNotNull(statusCapabilities); 2102 FrontendStatus status = mTuner.getFrontendStatus(statusCapabilities); 2103 assertNotNull(status); 2104 } 2105 2106 @Test testCloseFrontend()2107 public void testCloseFrontend() throws Exception { 2108 List<Integer> ids = mTuner.getFrontendIds(); 2109 if (ids == null) { 2110 return; 2111 } 2112 2113 // SCENARIO 1 - without Lnb 2114 assertFalse(ids.isEmpty()); 2115 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2116 FrontendSettings feSettings = createFrontendSettings(info); 2117 int res = mTuner.tune(feSettings); 2118 assertEquals(Tuner.RESULT_SUCCESS, res); 2119 assertNotNull(mTuner.getFrontendInfo()); 2120 2121 // now close frontend 2122 mTuner.closeFrontend(); 2123 2124 // confirm frontend is closed 2125 int[] statusCapabilities = info.getStatusCapabilities(); 2126 boolean frontendClosed = false; 2127 try { 2128 mTuner.getFrontendStatus(statusCapabilities); 2129 2130 } catch (IllegalStateException e) { 2131 frontendClosed = true; 2132 } 2133 assertTrue(frontendClosed); 2134 2135 // now tune to a different setting 2136 info = mTuner.getFrontendInfoById(ids.get(1)); 2137 feSettings = createFrontendSettings(info); 2138 mTuner.tune(feSettings); 2139 assertEquals(Tuner.RESULT_SUCCESS, res); 2140 assertNotNull(mTuner.getFrontendInfo()); 2141 FrontendStatus status = mTuner.getFrontendStatus(statusCapabilities); 2142 assertNotNull(status); 2143 2144 // SCENARIO 2 - with Lnb 2145 2146 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 2147 Lnb lnb = mTuner.openLnb(getExecutor(), lnbCB1); 2148 if (lnb == null) { 2149 return; 2150 } 2151 2152 mTuner.closeFrontend(); 2153 // confirm frontend is closed 2154 statusCapabilities = info.getStatusCapabilities(); 2155 frontendClosed = false; 2156 try { 2157 mTuner.getFrontendStatus(statusCapabilities); 2158 2159 } catch (IllegalStateException e) { 2160 frontendClosed = true; 2161 } 2162 assertTrue(frontendClosed); 2163 2164 info = mTuner.getFrontendInfoById(ids.get(0)); 2165 feSettings = createFrontendSettings(info); 2166 mTuner.tune(feSettings); 2167 assertEquals(Tuner.RESULT_SUCCESS, res); 2168 assertNotNull(mTuner.getFrontendInfo()); 2169 status = mTuner.getFrontendStatus(statusCapabilities); 2170 assertNotNull(status); 2171 } 2172 2173 @Test testHasUnusedFrontend1()2174 public void testHasUnusedFrontend1() throws Exception { 2175 prepTRMCustomFeResourceMapTest(); 2176 2177 // Use try block to ensure restoring the TunerResourceManager 2178 // Note: the handles will be changed from the original value, but should be OK 2179 try { 2180 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 2181 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2182 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2183 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2184 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2185 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 2186 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 2187 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 2188 2189 mTunerResourceManager.setFrontendInfoList(infos); 2190 2191 Tuner A = new Tuner(mContext, null, 100); 2192 Tuner B = new Tuner(mContext, null, 100); 2193 Tuner C = new Tuner(mContext, null, 100); 2194 2195 // check before anyone holds resource 2196 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_UNDEFINED)); 2197 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_ATSC)); 2198 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2199 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2200 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2201 2202 // let B hold resource 2203 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 2204 true /* expectedResult */, 1 /* expectedHandle */); 2205 2206 // check when one of the two exclusive groups are held 2207 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2208 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2209 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2210 2211 assertTrue(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2212 2213 // let C hold the resource 2214 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 2215 true /* expectedResult */, 5 /* expectedHandle */); 2216 2217 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2218 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2219 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2220 2221 assertFalse(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2222 assertFalse(C.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2223 2224 // let go of B's resource 2225 B.close(); 2226 2227 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2228 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2229 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2230 2231 assertTrue(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2232 assertTrue(C.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2233 2234 C.close(); 2235 A.close(); 2236 } catch (Exception e) { 2237 throw (e); 2238 } finally { 2239 cleanupTRMCustomFeResourceMapTest(); 2240 } 2241 } 2242 2243 @Test testHasUnusedFrontend2()2244 public void testHasUnusedFrontend2() throws Exception { 2245 prepTRMCustomFeResourceMapTest(); 2246 2247 // Use try block to ensure restoring the TunerResourceManager 2248 // Note: the handles will be changed from the original value, but should be OK 2249 try { 2250 TunerFrontendInfo[] infos = new TunerFrontendInfo[5]; 2251 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2252 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2253 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2254 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBT, 2); 2255 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBC, 2); 2256 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBS, 3); 2257 2258 mTunerResourceManager.setFrontendInfoList(infos); 2259 2260 Tuner A = new Tuner(mContext, null, 100); 2261 Tuner B = new Tuner(mContext, null, 100); 2262 Tuner C = new Tuner(mContext, null, 100); 2263 2264 // let B hold resource 2265 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 2266 true /* expectedResult */, 1 /* expectedHandle */); 2267 2268 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2269 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2270 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2271 2272 // let C hold the resource 2273 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 2274 true /* expectedResult */, 4 /* expectedHandle */); 2275 2276 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2277 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2278 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2279 2280 B.close(); 2281 C.close(); 2282 } catch (Exception e) { 2283 throw (e); 2284 } finally { 2285 cleanupTRMCustomFeResourceMapTest(); 2286 } 2287 } 2288 2289 @Test testHasUnusedFrontend3()2290 public void testHasUnusedFrontend3() throws Exception { 2291 prepTRMCustomFeResourceMapTest(); 2292 2293 // Use try block to ensure restoring the TunerResourceManager 2294 // Note: the handles will be changed from the original value, but should be OK 2295 try { 2296 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 2297 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2298 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2299 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2300 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2301 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 2302 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 2303 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 2304 2305 mTunerResourceManager.setFrontendInfoList(infos); 2306 2307 Tuner A = new Tuner(mContext, null, 100); 2308 Tuner B = new Tuner(mContext, null, 100); 2309 Tuner C = new Tuner(mContext, null, 100); 2310 2311 // let B hold resource 2312 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 2313 true /* expectedResult */, 1 /* expectedHandle */); 2314 2315 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2316 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2317 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2318 2319 // let C share from B 2320 mTunerResourceManager.shareFrontend(C.getClientId(), B.getClientId()); 2321 2322 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 2323 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 2324 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 2325 2326 A.close(); 2327 C.close(); 2328 B.close(); 2329 } catch (Exception e) { 2330 throw (e); 2331 } finally { 2332 cleanupTRMCustomFeResourceMapTest(); 2333 } 2334 } 2335 2336 @Test testIsLowestPriorityCornerCases()2337 public void testIsLowestPriorityCornerCases() throws Exception { 2338 prepTRMCustomFeResourceMapTest(); 2339 2340 // Use try block to ensure restoring the TunerResourceManager 2341 // Note: the handles will be changed from the original value, but should be OK 2342 try { 2343 setupSingleTunerSetupForIsLowestPriority(); 2344 2345 // must return true when non existing frontend type is specified 2346 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_UNDEFINED)); 2347 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_ATSC)); 2348 2349 // must return true when no one is holding the resource 2350 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2351 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2352 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2353 2354 // must return true when the callee is the only one holding the resource 2355 assignFeResource(mTuner.getClientId(), FrontendSettings.TYPE_DVBT, 2356 true /* expectedResult */, 1 /* expectedHandle */); 2357 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2358 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2359 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2360 2361 } catch (Exception e) { 2362 throw (e); 2363 } finally { 2364 cleanupTRMCustomFeResourceMapTest(); 2365 } 2366 } 2367 2368 @Test testIsLowestPriorityTwoClients()2369 public void testIsLowestPriorityTwoClients() throws Exception { 2370 prepTRMCustomFeResourceMapTest(); 2371 2372 // Use try block to ensure restoring the TunerResourceManager 2373 // Note: the handles will be changed from the original value, but should be OK 2374 try { 2375 setupSingleTunerSetupForIsLowestPriority(); 2376 testTwoClientsForIsLowestPriority(200, 100); // A > B 2377 testTwoClientsForIsLowestPriority(100, 200); // A < B 2378 testTwoClientsForIsLowestPriority(100, 100); // A = B 2379 2380 setupDualTunerSetupForIsLowestPriority(); 2381 testTwoClientsForIsLowestPriority(200, 100); // A > B 2382 testTwoClientsForIsLowestPriority(100, 200); // A < B 2383 testTwoClientsForIsLowestPriority(100, 100); // A = B 2384 } catch (Exception e) { 2385 throw (e); 2386 } finally { 2387 cleanupTRMCustomFeResourceMapTest(); 2388 } 2389 } 2390 2391 @Test testIsLowestPriorityThreeClients()2392 public void testIsLowestPriorityThreeClients() throws Exception { 2393 prepTRMCustomFeResourceMapTest(); 2394 2395 // Use try block to ensure restoring the TunerResourceManager 2396 // Note: the handles will be changed from the original value, but should be OK 2397 try { 2398 setupDualTunerSetupForIsLowestPriority(); 2399 testThreeClientsForIsLowestPriority(300, 200, 100); // A > B > C 2400 testThreeClientsForIsLowestPriority(300, 100, 200); // A > C > B 2401 testThreeClientsForIsLowestPriority(200, 300, 100); // B > A > C 2402 testThreeClientsForIsLowestPriority(200, 100, 300); // C > A > B 2403 testThreeClientsForIsLowestPriority(100, 300, 200); // B > C > A 2404 testThreeClientsForIsLowestPriority(100, 200, 300); // C > B > A 2405 testThreeClientsForIsLowestPriority(100, 100, 100); // A = B = C 2406 testThreeClientsForIsLowestPriority(200, 200, 100); // A = B > C 2407 testThreeClientsForIsLowestPriority(200, 100, 100); // A > B = C 2408 testThreeClientsForIsLowestPriority(200, 100, 200); // A = C > B 2409 testThreeClientsForIsLowestPriority(200, 300, 200); // B > A = C 2410 testThreeClientsForIsLowestPriority(100, 100, 200); // C > A = B 2411 testThreeClientsForIsLowestPriority(100, 200, 200); // B = C > A 2412 } catch (Exception e) { 2413 throw (e); 2414 } finally { 2415 cleanupTRMCustomFeResourceMapTest(); 2416 } 2417 } 2418 tunerFrontendInfo( int handle, int frontendType, int exclusiveGroupId)2419 private TunerFrontendInfo tunerFrontendInfo( 2420 int handle, int frontendType, int exclusiveGroupId) { 2421 TunerFrontendInfo info = new TunerFrontendInfo(); 2422 info.handle = handle; 2423 info.type = frontendType; 2424 info.exclusiveGroupId = exclusiveGroupId; 2425 return info; 2426 } 2427 2428 /** 2429 * Prep function for TunerTest that requires custom frontend resource map 2430 */ prepTRMCustomFeResourceMapTest()2431 private void prepTRMCustomFeResourceMapTest() { 2432 if (mTunerResourceManager == null) { 2433 mTunerResourceManager = (TunerResourceManager) 2434 mContext.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE); 2435 } 2436 mTunerResourceManager.storeResourceMap(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2437 mTunerResourceManager.clearResourceMap(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2438 } 2439 2440 /** 2441 * Clean up function for TunerTest that requires custom frontend resource map 2442 */ cleanupTRMCustomFeResourceMapTest()2443 private void cleanupTRMCustomFeResourceMapTest() { 2444 // first close mTuner in case a frontend resource is opened 2445 if (mTuner != null) { 2446 mTuner.close(); 2447 mTuner = null; 2448 } 2449 2450 // now restore the original frontend resource map 2451 if (mTunerResourceManager != null) { 2452 mTunerResourceManager.restoreResourceMap( 2453 TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2454 } 2455 } 2456 clearFrontendInfoList()2457 private void clearFrontendInfoList() { 2458 if (mTunerResourceManager != null) { 2459 mTunerResourceManager.clearResourceMap( 2460 TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2461 } 2462 } 2463 assignFeResource(int clientId, int frontendType, boolean expectedResult, int expectedHandle)2464 private void assignFeResource(int clientId, int frontendType, 2465 boolean expectedResult, int expectedHandle) { 2466 int[] feHandle = new int[1]; 2467 TunerFrontendRequest request = new TunerFrontendRequest(); 2468 request.clientId = clientId; 2469 request.frontendType = frontendType; 2470 boolean granted = mTunerResourceManager.requestFrontend(request, feHandle); 2471 assertEquals(granted, expectedResult); 2472 assertEquals(feHandle[0], expectedHandle); 2473 } 2474 setupSingleTunerSetupForIsLowestPriority()2475 private void setupSingleTunerSetupForIsLowestPriority() { 2476 // first clear the frontend resource to register new set of resources 2477 clearFrontendInfoList(); 2478 2479 TunerFrontendInfo[] infos = new TunerFrontendInfo[3]; 2480 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2481 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2482 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2483 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2484 2485 mTunerResourceManager.setFrontendInfoList(infos); 2486 } 2487 setupDualTunerSetupForIsLowestPriority()2488 private void setupDualTunerSetupForIsLowestPriority() { 2489 // first clear the frontend resource to register new set of resources 2490 clearFrontendInfoList(); 2491 2492 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 2493 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2494 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2495 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2496 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2497 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 2498 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 2499 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 2500 2501 mTunerResourceManager.setFrontendInfoList(infos); 2502 } 2503 2504 testTwoClientsForIsLowestPriority(int prioA, int prioB)2505 private void testTwoClientsForIsLowestPriority(int prioA, int prioB) { 2506 2507 Tuner A = new Tuner(mContext, null, prioA); 2508 Tuner B = new Tuner(mContext, null, prioB); 2509 2510 // all should return true 2511 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2512 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2513 2514 // let A hold resource 2515 assignFeResource(A.getClientId(), FrontendSettings.TYPE_DVBT, 2516 true /* expectedResult */, 1 /* expectedHandle */); 2517 2518 // should return true for A as A is the sole holder 2519 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2520 // should return false for B only if A < B 2521 if ( prioA < prioB ) { 2522 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2523 } else { 2524 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2525 } 2526 2527 A.close(); 2528 B.close(); 2529 } 2530 testThreeClientsForIsLowestPriority(int prioA, int prioB, int prioC)2531 private void testThreeClientsForIsLowestPriority(int prioA, int prioB, int prioC) { 2532 2533 Tuner A = new Tuner(mContext, null, prioA); 2534 Tuner B = new Tuner(mContext, null, prioB); 2535 Tuner C = new Tuner(mContext, null, prioC); 2536 2537 // all should return true 2538 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2539 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2540 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2541 2542 // let A & C hold resource 2543 assignFeResource(A.getClientId(), FrontendSettings.TYPE_DVBT, 2544 true /* expectedResult */, 1 /* expectedHandle */); 2545 2546 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 2547 true /* expectedResult */, 5 /* expectedHandle */); 2548 2549 // should return false for B only if A < B 2550 if (prioA > prioB && prioB > prioC) { 2551 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2552 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2553 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2554 } else if (prioA > prioC && prioC > prioB) { 2555 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2556 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2557 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2558 } else if (prioA > prioC && prioC > prioB) { 2559 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2560 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2561 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2562 } else if (prioB > prioA && prioA > prioC) { 2563 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2564 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2565 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2566 } else if (prioC > prioA && prioA > prioB) { 2567 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2568 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2569 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2570 } else if (prioB > prioC && prioC > prioA) { 2571 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2572 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2573 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2574 } else if (prioC > prioB && prioB > prioA) { 2575 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2576 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2577 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2578 } else if (prioA == prioB && prioB == prioC) { 2579 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2580 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2581 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2582 } else if (prioA == prioB && prioB > prioC) { 2583 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2584 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2585 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2586 } else if (prioA > prioB && prioB == prioC) { 2587 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2588 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2589 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2590 } else if (prioA == prioC && prioC > prioB) { 2591 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2592 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2593 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2594 } else if (prioB > prioA && prioA == prioC) { 2595 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2596 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2597 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2598 } else if (prioC > prioA && prioA == prioB) { 2599 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2600 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2601 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2602 } else if (prioB == prioC && prioC > prioA) { 2603 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2604 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2605 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2606 } 2607 2608 A.close(); 2609 B.close(); 2610 C.close(); 2611 } 2612 2613 @Test testSharedFilterOneProcess()2614 public void testSharedFilterOneProcess() throws Exception { 2615 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2616 assertTrue(f != null); 2617 2618 String token1 = f.acquireSharedFilterToken(); 2619 assertTrue(token1 != null); 2620 2621 String token2 = f.acquireSharedFilterToken(); 2622 assertTrue(token2 == null); 2623 2624 // Tune a frontend before start the filter 2625 List<Integer> ids = mTuner.getFrontendIds(); 2626 assertFalse(ids.isEmpty()); 2627 2628 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2629 int res = mTuner.tune(createFrontendSettings(info)); 2630 assertEquals(Tuner.RESULT_SUCCESS, res); 2631 2632 Settings settings = SectionSettingsWithTableInfo 2633 .builder(Filter.TYPE_TS) 2634 .setTableId(2) 2635 .setVersion(1) 2636 .setCrcEnabled(true) 2637 .setRaw(false) 2638 .setRepeat(false) 2639 .build(); 2640 FilterConfiguration config = TsFilterConfiguration 2641 .builder() 2642 .setTpid(10) 2643 .setSettings(settings) 2644 .build(); 2645 2646 assertEquals(f.configure(config), Tuner.RESULT_INVALID_STATE); 2647 assertEquals(f.setMonitorEventMask(Filter.MONITOR_EVENT_SCRAMBLING_STATUS), 2648 Tuner.RESULT_INVALID_STATE); 2649 assertEquals(f.setDataSource(null), Tuner.RESULT_INVALID_STATE); 2650 assertEquals(f.start(), Tuner.RESULT_INVALID_STATE); 2651 assertEquals(f.flush(), Tuner.RESULT_INVALID_STATE); 2652 assertEquals(f.read(new byte[3], 0, 3), 0); 2653 assertEquals(f.stop(), Tuner.RESULT_INVALID_STATE); 2654 2655 res = mTuner.cancelTuning(); 2656 assertEquals(Tuner.RESULT_SUCCESS, res); 2657 2658 f.freeSharedFilterToken(token1); 2659 f.close(); 2660 f = null; 2661 } 2662 2663 @Test testSharedFilterTwoProcessesCloseInSharedFilter()2664 public void testSharedFilterTwoProcessesCloseInSharedFilter() throws Exception { 2665 mConnection = new TestServiceConnection(); 2666 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2667 Context.BIND_AUTO_CREATE); 2668 mSharedFilterTestServer = 2669 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2670 2671 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2672 assertTrue(token != null); 2673 SharedFilter f = 2674 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2675 assertTrue(f != null); 2676 2677 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2678 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2679 int size = f.read(new byte[3], 0, 3); 2680 assertTrue(size >= 0 && size <= 3); 2681 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2682 2683 mLockLatch = new CountDownLatch(1); 2684 f.close(); 2685 f = null; 2686 mSharedFilterTestServer.closeFilter(); 2687 Thread.sleep(2000); 2688 assertEquals(mLockLatch.getCount(), 1); 2689 mLockLatch = null; 2690 2691 mContext.unbindService(mConnection); 2692 } 2693 2694 @Test testSharedFilterTwoProcessesCloseInFilter()2695 public void testSharedFilterTwoProcessesCloseInFilter() throws Exception { 2696 mConnection = new TestServiceConnection(); 2697 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2698 Context.BIND_AUTO_CREATE); 2699 mSharedFilterTestServer = 2700 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2701 2702 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2703 assertTrue(token != null); 2704 2705 SharedFilter f = 2706 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2707 assertTrue(f != null); 2708 2709 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2710 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2711 int size = f.read(new byte[3], 0, 3); 2712 assertTrue(size >= 0 && size <= 3); 2713 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2714 2715 mLockLatch = new CountDownLatch(1); 2716 mSharedFilterTestServer.closeFilter(); 2717 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2718 mLockLatch = null; 2719 f.close(); 2720 f = null; 2721 2722 mContext.unbindService(mConnection); 2723 } 2724 2725 @Test testSharedFilterTwoProcessesReleaseInFilter()2726 public void testSharedFilterTwoProcessesReleaseInFilter() throws Exception { 2727 mConnection = new TestServiceConnection(); 2728 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2729 Context.BIND_AUTO_CREATE); 2730 mSharedFilterTestServer = 2731 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2732 2733 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2734 assertTrue(token != null); 2735 2736 SharedFilter f = 2737 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2738 assertTrue(f != null); 2739 2740 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2741 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2742 int size = f.read(new byte[3], 0, 3); 2743 assertTrue(size >= 0 && size <= 3); 2744 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2745 2746 mLockLatch = new CountDownLatch(1); 2747 mSharedFilterTestServer.freeSharedFilterToken(token); 2748 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2749 mLockLatch = null; 2750 2751 mSharedFilterTestServer.closeFilter(); 2752 f.close(); 2753 f = null; 2754 2755 mContext.unbindService(mConnection); 2756 } 2757 2758 @Test testSharedFilterTwoProcessesVerifySharedFilter()2759 public void testSharedFilterTwoProcessesVerifySharedFilter() throws Exception { 2760 mConnection = new TestServiceConnection(); 2761 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2762 Context.BIND_AUTO_CREATE); 2763 mSharedFilterTestServer = 2764 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2765 2766 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2767 assertTrue(f != null); 2768 2769 String token = f.acquireSharedFilterToken(); 2770 assertTrue(token != null); 2771 2772 // Tune a frontend before start the shared filter 2773 List<Integer> ids = mTuner.getFrontendIds(); 2774 assertFalse(ids.isEmpty()); 2775 2776 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2777 int res = mTuner.tune(createFrontendSettings(info)); 2778 assertEquals(Tuner.RESULT_SUCCESS, res); 2779 assertTrue(mSharedFilterTestServer.verifySharedFilter(token)); 2780 2781 res = mTuner.cancelTuning(); 2782 assertEquals(Tuner.RESULT_SUCCESS, res); 2783 2784 f.freeSharedFilterToken(token); 2785 f.close(); 2786 f = null; 2787 2788 mContext.unbindService(mConnection); 2789 } 2790 2791 @Test testFilterTimeDelay()2792 public void testFilterTimeDelay() throws Exception { 2793 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2794 2795 int timeDelayInMs = 5000; 2796 Instant start = Instant.now(); 2797 int status = f.delayCallbackForDurationMillis(timeDelayInMs); 2798 2799 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 2800 // Configure filter setting for receiving PAT 2801 Settings settings = SectionSettingsWithTableInfo 2802 .builder(Filter.TYPE_TS) 2803 .setTableId(0) 2804 .setCrcEnabled(true) 2805 .setRaw(false) 2806 .setRepeat(false) 2807 .build(); 2808 FilterConfiguration config = TsFilterConfiguration 2809 .builder() 2810 .setTpid(0) 2811 .setSettings(settings) 2812 .build(); 2813 2814 f.configure(config); 2815 2816 // Tune a frontend before starting the filter 2817 List<Integer> ids = mTuner.getFrontendIds(); 2818 assertFalse(ids.isEmpty()); 2819 2820 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2821 int res = mTuner.tune(createFrontendSettings(info)); 2822 assertEquals(Tuner.RESULT_SUCCESS, res); 2823 2824 // start / stop prevents initial race condition after first setting the time delay. 2825 f.start(); 2826 f.stop(); 2827 2828 mLockLatch = new CountDownLatch(1); 2829 f.start(); 2830 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2831 2832 Instant finish = Instant.now(); 2833 Duration timeElapsed = Duration.between(start, finish); 2834 assertTrue(timeElapsed.toMillis() >= timeDelayInMs); 2835 2836 res = mTuner.cancelTuning(); 2837 assertEquals(Tuner.RESULT_SUCCESS, res); 2838 } else { 2839 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2840 } 2841 f.close(); 2842 f = null; 2843 } 2844 2845 @Test testFilterDataSizeDelay()2846 public void testFilterDataSizeDelay() throws Exception { 2847 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2848 int status = f.delayCallbackUntilBytesAccumulated(5000); 2849 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 2850 assertEquals(Tuner.RESULT_SUCCESS, status); 2851 } else { 2852 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2853 } 2854 f.close(); 2855 } 2856 2857 @Test testMaxNumberOfFrontends()2858 public void testMaxNumberOfFrontends() throws Exception { 2859 List<Integer> ids = mTuner.getFrontendIds(); 2860 assertFalse(ids.isEmpty()); 2861 for (int i = 0; i < ids.size(); i++) { 2862 int type = mTuner.getFrontendInfoById(ids.get(i)).getType(); 2863 if (TunerVersionChecker.isHigherOrEqualVersionTo( 2864 TunerVersionChecker.TUNER_VERSION_2_0)) { 2865 int defaultMax = -1; 2866 int status; 2867 // Check default value 2868 defaultMax = mTuner.getMaxNumberOfFrontends(type); 2869 assertTrue(defaultMax > 0); 2870 // Set to -1 2871 status = mTuner.setMaxNumberOfFrontends(type, -1); 2872 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status); 2873 // Set to defaultMax + 1 2874 status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1); 2875 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status); 2876 // Set to 0 2877 status = mTuner.setMaxNumberOfFrontends(type, 0); 2878 assertEquals(Tuner.RESULT_SUCCESS, status); 2879 // Check after set 2880 int currentMax = -1; 2881 currentMax = mTuner.getMaxNumberOfFrontends(type); 2882 assertEquals(currentMax, 0); 2883 // Reset to default 2884 status = mTuner.setMaxNumberOfFrontends(type, defaultMax); 2885 assertEquals(Tuner.RESULT_SUCCESS, status); 2886 currentMax = mTuner.getMaxNumberOfFrontends(type); 2887 assertEquals(defaultMax, currentMax); 2888 } else { 2889 int defaultMax = mTuner.getMaxNumberOfFrontends(type); 2890 assertEquals(defaultMax, -1); 2891 int status = mTuner.setMaxNumberOfFrontends(type, 0); 2892 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2893 } 2894 } 2895 // validate the behavior of tune 2896 FrontendInfo info1 = mTuner.getFrontendInfoById(ids.get(0)); 2897 FrontendSettings feSettings1 = createFrontendSettings(info1); 2898 int type1 = info1.getType(); 2899 if (TunerVersionChecker.isHigherOrEqualVersionTo( 2900 TunerVersionChecker.TUNER_VERSION_2_0)) { 2901 if (ids.size() >= 1) { 2902 int originalMax1 = mTuner.getMaxNumberOfFrontends(type1); 2903 assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1)); 2904 assertNotNull(mTuner.getFrontendInfo()); 2905 2906 // validate that set max cannot be set to lower value than current usage 2907 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, 2908 mTuner.setMaxNumberOfFrontends(type1, 0)); 2909 2910 // validate max value is reflected in the tune behavior 2911 mTuner.closeFrontend(); 2912 assertEquals(Tuner.RESULT_SUCCESS, 2913 mTuner.setMaxNumberOfFrontends(type1, 0)); 2914 assertEquals(Tuner.RESULT_UNAVAILABLE, 2915 mTuner.tune(feSettings1)); 2916 2917 assertEquals(Tuner.RESULT_SUCCESS, 2918 mTuner.setMaxNumberOfFrontends(type1, originalMax1)); 2919 assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1)); 2920 assertNotNull(mTuner.getFrontendInfo()); 2921 mTuner.closeFrontend(); 2922 } 2923 2924 // validate max number on one frontend type has no impact on other 2925 if (ids.size() >= 2) { 2926 FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(1)); 2927 int type2 = info2.getType(); 2928 int originalMax2 = mTuner.getMaxNumberOfFrontends(type2); 2929 2930 assertEquals(Tuner.RESULT_SUCCESS, 2931 mTuner.setMaxNumberOfFrontends(type2, 0)); 2932 assertEquals(Tuner.RESULT_SUCCESS, 2933 mTuner.tune(feSettings1)); 2934 assertNotNull(mTuner.getFrontendInfo()); 2935 2936 // set it back to the original max 2937 assertEquals(Tuner.RESULT_SUCCESS, 2938 mTuner.setMaxNumberOfFrontends(type2, originalMax2)); 2939 mTuner.closeFrontend(); 2940 2941 } 2942 } 2943 } 2944 createTsSectionFilter( Tuner tuner, Executor e, FilterCallback cb)2945 public static Filter createTsSectionFilter( 2946 Tuner tuner, Executor e, FilterCallback cb) { 2947 Filter f = tuner.openFilter(Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, e, cb); 2948 Settings settings = SectionSettingsWithTableInfo 2949 .builder(Filter.TYPE_TS) 2950 .setTableId(2) 2951 .setVersion(1) 2952 .setCrcEnabled(true) 2953 .setRaw(false) 2954 .setRepeat(false) 2955 .build(); 2956 FilterConfiguration config = TsFilterConfiguration 2957 .builder() 2958 .setTpid(10) 2959 .setSettings(settings) 2960 .build(); 2961 f.configure(config); 2962 f.setMonitorEventMask( 2963 Filter.MONITOR_EVENT_SCRAMBLING_STATUS | Filter.MONITOR_EVENT_IP_CID_CHANGE); 2964 2965 return f; 2966 } 2967 hasTuner()2968 private boolean hasTuner() { 2969 return mContext.getPackageManager().hasSystemFeature("android.hardware.tv.tuner"); 2970 } 2971 getExecutor()2972 private Executor getExecutor() { 2973 return Runnable::run; 2974 } 2975 getLnbCallback()2976 private LnbCallback getLnbCallback() { 2977 return new LnbCallback() { 2978 @Override 2979 public void onEvent(int lnbEventType) {} 2980 @Override 2981 public void onDiseqcMessage(byte[] diseqcMessage) {} 2982 }; 2983 } 2984 getFilterCallback()2985 private FilterCallback getFilterCallback() { 2986 return new FilterCallback() { 2987 @Override 2988 public void onFilterEvent(Filter filter, FilterEvent[] events) { 2989 for (FilterEvent e : events) { 2990 if (e instanceof DownloadEvent) { 2991 testDownloadEvent(filter, (DownloadEvent) e); 2992 } else if (e instanceof IpPayloadEvent) { 2993 testIpPayloadEvent(filter, (IpPayloadEvent) e); 2994 } else if (e instanceof MediaEvent) { 2995 testMediaEvent(filter, (MediaEvent) e); 2996 } else if (e instanceof MmtpRecordEvent) { 2997 testMmtpRecordEvent(filter, (MmtpRecordEvent) e); 2998 } else if (e instanceof PesEvent) { 2999 testPesEvent(filter, (PesEvent) e); 3000 } else if (e instanceof SectionEvent) { 3001 testSectionEvent(filter, (SectionEvent) e); 3002 } else if (e instanceof TemiEvent) { 3003 testTemiEvent(filter, (TemiEvent) e); 3004 } else if (e instanceof TsRecordEvent) { 3005 testTsRecordEvent(filter, (TsRecordEvent) e); 3006 } else if (e instanceof ScramblingStatusEvent) { 3007 testScramblingStatusEvent(filter, (ScramblingStatusEvent) e); 3008 } else if (e instanceof IpCidChangeEvent) { 3009 testIpCidChangeEvent(filter, (IpCidChangeEvent) e); 3010 } else if (e instanceof RestartEvent) { 3011 testRestartEvent(filter, (RestartEvent) e); 3012 } 3013 } 3014 if (mLockLatch != null) { 3015 mLockLatch.countDown(); 3016 } 3017 } 3018 @Override 3019 public void onFilterStatusChanged(Filter filter, int status) {} 3020 }; 3021 } 3022 3023 private SharedFilterCallback getSharedFilterCallback() { 3024 return new SharedFilterCallback() { 3025 @Override 3026 public void onFilterEvent(SharedFilter filter, FilterEvent[] events) {} 3027 @Override 3028 public void onFilterStatusChanged(SharedFilter filter, int status) { 3029 if (status == SharedFilter.STATUS_INACCESSIBLE) { 3030 if (mLockLatch != null) { 3031 mLockLatch.countDown(); 3032 } 3033 } 3034 } 3035 }; 3036 } 3037 3038 private void testDownloadEvent(Filter filter, DownloadEvent e) { 3039 e.getItemId(); 3040 e.getDownloadId(); 3041 e.getMpuSequenceNumber(); 3042 e.getItemFragmentIndex(); 3043 e.getLastItemFragmentIndex(); 3044 long length = e.getDataLength(); 3045 if (length > 0) { 3046 byte[] buffer = new byte[(int) length]; 3047 assertNotEquals(0, filter.read(buffer, 0, length)); 3048 } 3049 } 3050 3051 private void testIpPayloadEvent(Filter filter, IpPayloadEvent e) { 3052 long length = e.getDataLength(); 3053 if (length > 0) { 3054 byte[] buffer = new byte[(int) length]; 3055 assertNotEquals(0, filter.read(buffer, 0, length)); 3056 } 3057 } 3058 3059 private void testMediaEvent(Filter filter, MediaEvent e) { 3060 e.getStreamId(); 3061 e.isPtsPresent(); 3062 e.getPts(); 3063 e.isDtsPresent(); 3064 e.getDts(); 3065 e.getDataLength(); 3066 e.getOffset(); 3067 e.getLinearBlock(); 3068 e.isSecureMemory(); 3069 e.getAvDataId(); 3070 e.getAudioHandle(); 3071 e.getMpuSequenceNumber(); 3072 e.isPrivateData(); 3073 e.getScIndexMask(); 3074 AudioDescriptor ad = e.getExtraMetaData(); 3075 if (ad != null) { 3076 ad.getAdFade(); 3077 ad.getAdPan(); 3078 ad.getAdVersionTextTag(); 3079 ad.getAdGainCenter(); 3080 ad.getAdGainFront(); 3081 ad.getAdGainSurround(); 3082 } 3083 List<AudioPresentation> aps = e.getAudioPresentations(); 3084 for (AudioPresentation ap : aps) { 3085 ap.getPresentationId(); 3086 ap.getProgramId(); 3087 ap.getLabels(); 3088 ap.getLocale(); 3089 ap.getMasteringIndication(); 3090 ap.hasAudioDescription(); 3091 ap.hasDialogueEnhancement(); 3092 ap.hasSpokenSubtitles(); 3093 } 3094 e.release(); 3095 } 3096 3097 private void testMmtpRecordEvent(Filter filter, MmtpRecordEvent e) { 3098 e.getScHevcIndexMask(); 3099 e.getDataLength(); 3100 int mpuSequenceNumber = e.getMpuSequenceNumber(); 3101 long pts = e.getPts(); 3102 int firstMbInSlice = e.getFirstMacroblockInSlice(); 3103 int tsIndexMask = e.getTsIndexMask(); 3104 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 3105 assertEquals(mpuSequenceNumber, Tuner.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM); 3106 assertEquals(pts, Tuner.INVALID_TIMESTAMP); 3107 assertEquals(firstMbInSlice, Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE); 3108 assertEquals(tsIndexMask, 0); 3109 } 3110 } 3111 3112 private void testPesEvent(Filter filter, PesEvent e) { 3113 e.getStreamId(); 3114 e.getMpuSequenceNumber(); 3115 long length = e.getDataLength(); 3116 if (length > 0) { 3117 byte[] buffer = new byte[(int) length]; 3118 assertNotEquals(0, filter.read(buffer, 0, length)); 3119 } 3120 } 3121 3122 private void testSectionEvent(Filter filter, SectionEvent e) { 3123 e.getTableId(); 3124 e.getVersion(); 3125 e.getSectionNumber(); 3126 e.getDataLength(); 3127 long length = e.getDataLengthLong(); 3128 if (length > 0) { 3129 byte[] buffer = new byte[(int) length]; 3130 assertNotEquals(0, filter.read(buffer, 0, length)); 3131 } 3132 } 3133 3134 private void testTemiEvent(Filter filter, TemiEvent e) { 3135 e.getPts(); 3136 e.getDescriptorTag(); 3137 e.getDescriptorData(); 3138 } 3139 3140 private void testTsRecordEvent(Filter filter, TsRecordEvent e) { 3141 e.getPacketId(); 3142 e.getTsIndexMask(); 3143 e.getScIndexMask(); 3144 e.getDataLength(); 3145 long pts = e.getPts(); 3146 int firstMbInSlice = e.getFirstMacroblockInSlice(); 3147 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 3148 assertEquals(pts, Tuner.INVALID_TIMESTAMP); 3149 assertEquals(firstMbInSlice, Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE); 3150 } 3151 } 3152 3153 private void testScramblingStatusEvent(Filter filter, ScramblingStatusEvent e) { 3154 e.getScramblingStatus(); 3155 } 3156 3157 private void testIpCidChangeEvent(Filter filter, IpCidChangeEvent e) { 3158 e.getIpCid(); 3159 } 3160 3161 private void testRestartEvent(Filter filter, RestartEvent e) { 3162 e.getStartId(); 3163 } 3164 3165 private OnRecordStatusChangedListener getRecordListener() { 3166 return new OnRecordStatusChangedListener() { 3167 @Override 3168 public void onRecordStatusChanged(int status) {} 3169 }; 3170 } 3171 3172 private OnPlaybackStatusChangedListener getPlaybackListener() { 3173 return new OnPlaybackStatusChangedListener() { 3174 @Override 3175 public void onPlaybackStatusChanged(int status) {} 3176 }; 3177 } 3178 3179 static public FrontendSettings createFrontendSettings(FrontendInfo info) { 3180 FrontendCapabilities caps = info.getFrontendCapabilities(); 3181 long minFreq = info.getFrequencyRangeLong().getLower(); 3182 long maxFreq = info.getFrequencyRangeLong().getUpper(); 3183 FrontendCapabilities feCaps = info.getFrontendCapabilities(); 3184 switch(info.getType()) { 3185 case FrontendSettings.TYPE_ANALOG: { 3186 AnalogFrontendCapabilities analogCaps = (AnalogFrontendCapabilities) caps; 3187 int signalType = getFirstCapable(analogCaps.getSignalTypeCapability()); 3188 int sif = getFirstCapable(analogCaps.getSifStandardCapability()); 3189 return AnalogFrontendSettings 3190 .builder() 3191 .setFrequencyLong(55250000) //2nd freq of VHF 3192 .setSignalType(signalType) 3193 .setSifStandard(sif) 3194 .build(); 3195 } 3196 case FrontendSettings.TYPE_ATSC3: { 3197 Atsc3FrontendCapabilities atsc3Caps = (Atsc3FrontendCapabilities) caps; 3198 int bandwidth = getFirstCapable(atsc3Caps.getBandwidthCapability()); 3199 int demod = getFirstCapable(atsc3Caps.getDemodOutputFormatCapability()); 3200 Atsc3FrontendSettings settings = 3201 Atsc3FrontendSettings 3202 .builder() 3203 .setFrequencyLong(473000000) // 1st freq of UHF 3204 .setBandwidth(bandwidth) 3205 .setDemodOutputFormat(demod) 3206 .build(); 3207 settings.setEndFrequencyLong(maxFreq); 3208 return settings; 3209 } 3210 case FrontendSettings.TYPE_ATSC: { 3211 AtscFrontendCapabilities atscCaps = (AtscFrontendCapabilities) caps; 3212 int modulation = getFirstCapable(atscCaps.getModulationCapability()); 3213 return AtscFrontendSettings 3214 .builder() 3215 .setFrequencyLong(479000000) // 2nd freq of UHF 3216 .setModulation(modulation) 3217 .build(); 3218 } 3219 case FrontendSettings.TYPE_DVBC: { 3220 DvbcFrontendCapabilities dvbcCaps = (DvbcFrontendCapabilities) caps; 3221 int modulation = getFirstCapable(dvbcCaps.getModulationCapability()); 3222 int fec = getFirstCapable(dvbcCaps.getFecCapability()); 3223 int annex = getFirstCapable(dvbcCaps.getAnnexCapability()); 3224 DvbcFrontendSettings settings = 3225 DvbcFrontendSettings 3226 .builder() 3227 .setFrequencyLong(490000000) 3228 .setModulation(modulation) 3229 .setInnerFec(fec) 3230 .setAnnex(annex) 3231 .build(); 3232 settings.setEndFrequencyLong(maxFreq); 3233 return settings; 3234 } 3235 case FrontendSettings.TYPE_DVBS: { 3236 DvbsFrontendCapabilities dvbsCaps = (DvbsFrontendCapabilities) caps; 3237 int modulation = getFirstCapable(dvbsCaps.getModulationCapability()); 3238 int standard = getFirstCapable(dvbsCaps.getStandardCapability()); 3239 DvbsFrontendSettings settings = 3240 DvbsFrontendSettings 3241 .builder() 3242 .setFrequencyLong(950000000) //950Mhz 3243 .setModulation(modulation) 3244 .setStandard(standard) 3245 .build(); 3246 settings.setEndFrequencyLong(maxFreq); 3247 return settings; 3248 } 3249 case FrontendSettings.TYPE_DVBT: { 3250 DvbtFrontendCapabilities dvbtCaps = (DvbtFrontendCapabilities) caps; 3251 int transmission = getFirstCapable(dvbtCaps.getTransmissionModeCapability()); 3252 int bandwidth = getFirstCapable(dvbtCaps.getBandwidthCapability()); 3253 int constellation = getFirstCapable(dvbtCaps.getConstellationCapability()); 3254 int codeRate = getFirstCapable(dvbtCaps.getCodeRateCapability()); 3255 int hierarchy = getFirstCapable(dvbtCaps.getHierarchyCapability()); 3256 int guardInterval = getFirstCapable(dvbtCaps.getGuardIntervalCapability()); 3257 DvbtFrontendSettings settings = DvbtFrontendSettings 3258 .builder() 3259 .setFrequencyLong(498000000) 3260 .setTransmissionMode(transmission) 3261 .setBandwidth(bandwidth) 3262 .setConstellation(constellation) 3263 .setHierarchy(hierarchy) 3264 .setHighPriorityCodeRate(codeRate) 3265 .setLowPriorityCodeRate(codeRate) 3266 .setGuardInterval(guardInterval) 3267 .setStandard(DvbtFrontendSettings.STANDARD_T) 3268 .setMiso(false) 3269 .build(); 3270 settings.setEndFrequencyLong(maxFreq); 3271 return settings; 3272 } 3273 case FrontendSettings.TYPE_ISDBS3: { 3274 Isdbs3FrontendCapabilities isdbs3Caps = (Isdbs3FrontendCapabilities) caps; 3275 int modulation = getFirstCapable(isdbs3Caps.getModulationCapability()); 3276 int codeRate = getFirstCapable(isdbs3Caps.getCodeRateCapability()); 3277 Isdbs3FrontendSettings settings = Isdbs3FrontendSettings 3278 .builder() 3279 .setFrequencyLong(1000000000) //1000 Mhz 3280 .setModulation(modulation) 3281 .setCodeRate(codeRate) 3282 .build(); 3283 settings.setEndFrequencyLong(maxFreq); 3284 return settings; 3285 } 3286 case FrontendSettings.TYPE_ISDBS: { 3287 IsdbsFrontendCapabilities isdbsCaps = (IsdbsFrontendCapabilities) caps; 3288 int modulation = getFirstCapable(isdbsCaps.getModulationCapability()); 3289 int codeRate = getFirstCapable(isdbsCaps.getCodeRateCapability()); 3290 IsdbsFrontendSettings settings = IsdbsFrontendSettings 3291 .builder() 3292 .setFrequencyLong(1050000000) //1050 Mhz 3293 .setModulation(modulation) 3294 .setCodeRate(codeRate) 3295 .build(); 3296 settings.setEndFrequencyLong(maxFreq); 3297 return settings; 3298 } 3299 case FrontendSettings.TYPE_ISDBT: { 3300 IsdbtFrontendCapabilities isdbtCaps = (IsdbtFrontendCapabilities) caps; 3301 int mode = getFirstCapable(isdbtCaps.getModeCapability()); 3302 int bandwidth = getFirstCapable(isdbtCaps.getBandwidthCapability()); 3303 int modulation = getFirstCapable(isdbtCaps.getModulationCapability()); 3304 int codeRate = getFirstCapable(isdbtCaps.getCodeRateCapability()); 3305 int guardInterval = getFirstCapable(isdbtCaps.getGuardIntervalCapability()); 3306 int timeInterleaveMode = 3307 getFirstCapable(isdbtCaps.getTimeInterleaveModeCapability()); 3308 boolean isSegmentAutoSupported = isdbtCaps.isSegmentAutoSupported(); 3309 boolean isFullSegmentSupported = isdbtCaps.isFullSegmentSupported(); 3310 3311 IsdbtFrontendSettings.Builder builder = IsdbtFrontendSettings.builder(); 3312 builder.setFrequencyLong(527143000); //22 ch 527.143 MHz 3313 builder.setBandwidth(bandwidth); 3314 builder.setMode(mode); 3315 builder.setGuardInterval(guardInterval); 3316 3317 if (!TunerVersionChecker.isHigherOrEqualVersionTo( 3318 TunerVersionChecker.TUNER_VERSION_2_0)) { 3319 builder.setModulation(modulation); 3320 builder.setCodeRate(codeRate); 3321 } else { 3322 IsdbtFrontendSettings.IsdbtLayerSettings.Builder layerBuilder = 3323 IsdbtFrontendSettings.IsdbtLayerSettings.builder(); 3324 layerBuilder.setTimeInterleaveMode(timeInterleaveMode); 3325 layerBuilder.setModulation(modulation); 3326 layerBuilder.setCodeRate(codeRate); 3327 if (isSegmentAutoSupported) { 3328 layerBuilder.setNumberOfSegments(0xFF); 3329 } else { 3330 if (isFullSegmentSupported) { 3331 layerBuilder.setNumberOfSegments(13); 3332 } else { 3333 layerBuilder.setNumberOfSegments(1); 3334 } 3335 } 3336 IsdbtFrontendSettings.IsdbtLayerSettings layer = layerBuilder.build(); 3337 builder.setLayerSettings( 3338 new IsdbtFrontendSettings.IsdbtLayerSettings[] {layer}); 3339 builder.setPartialReceptionFlag( 3340 IsdbtFrontendSettings.PARTIAL_RECEPTION_FLAG_TRUE); 3341 } 3342 IsdbtFrontendSettings settings = builder.build(); 3343 settings.setEndFrequencyLong(maxFreq); 3344 return settings; 3345 } 3346 case FrontendSettings.TYPE_DTMB: { 3347 DtmbFrontendCapabilities dtmbCaps = (DtmbFrontendCapabilities) caps; 3348 int modulation = getFirstCapable(dtmbCaps.getModulationCapability()); 3349 int transmissionMode = getFirstCapable( 3350 dtmbCaps.getTransmissionModeCapability()); 3351 int guardInterval = getFirstCapable(dtmbCaps.getGuardIntervalCapability()); 3352 int timeInterleaveMode = getFirstCapable( 3353 dtmbCaps.getTimeInterleaveModeCapability()); 3354 int codeRate = getFirstCapable(dtmbCaps.getCodeRateCapability()); 3355 int bandwidth = getFirstCapable(dtmbCaps.getBandwidthCapability()); 3356 DtmbFrontendSettings settings = 3357 DtmbFrontendSettings 3358 .builder() 3359 .setFrequencyLong(506000000) 3360 .setModulation(modulation) 3361 .setTransmissionMode(transmissionMode) 3362 .setBandwidth(bandwidth) 3363 .setCodeRate(codeRate) 3364 .setGuardInterval(guardInterval) 3365 .setTimeInterleaveMode(timeInterleaveMode) 3366 .build(); 3367 settings.setEndFrequencyLong(maxFreq); 3368 return settings; 3369 } 3370 case FrontendSettings.TYPE_IPTV: { 3371 IptvFrontendCapabilities iptvCaps = (IptvFrontendCapabilities) caps; 3372 int protocol = getFirstCapable(iptvCaps.getProtocolCapability()); 3373 IptvFrontendSettings settings = 3374 new IptvFrontendSettings 3375 .Builder() 3376 .setProtocol(protocol) 3377 .build(); 3378 return settings; 3379 } 3380 default: 3381 break; 3382 } 3383 return null; 3384 } 3385 3386 static public int getFirstCapable(int caps) { 3387 if (caps == 0) return 0; 3388 int mask = 1; 3389 while ((mask & caps) == 0) { 3390 mask = mask << 1; 3391 } 3392 return (mask & caps); 3393 } 3394 3395 static public long getFirstCapable(long caps) { 3396 if (caps == 0) return 0; 3397 long mask = 1; 3398 while ((mask & caps) == 0) { 3399 mask = mask << 1; 3400 } 3401 return (mask & caps); 3402 } 3403 3404 private ScanCallback getScanCallback() { 3405 return new ScanCallback() { 3406 @Override 3407 public void onLocked() { 3408 if (mLockLatch != null) { 3409 mLockLatch.countDown(); 3410 } 3411 } 3412 3413 @Override 3414 public void onUnlocked() { 3415 ScanCallback.super.onUnlocked(); 3416 if (mLockLatch != null) { 3417 mLockLatch.countDown(); 3418 } 3419 } 3420 3421 @Override 3422 public void onScanStopped() {} 3423 3424 @Override 3425 public void onProgress(int percent) {} 3426 3427 @Override 3428 public void onFrequenciesReported(int[] frequency) {} 3429 3430 @Override 3431 public void onFrequenciesLongReported(long[] frequencies) { 3432 ScanCallback.super.onFrequenciesLongReported(frequencies); 3433 } 3434 3435 @Override 3436 public void onSymbolRatesReported(int[] rate) {} 3437 3438 @Override 3439 public void onPlpIdsReported(int[] plpIds) {} 3440 3441 @Override 3442 public void onGroupIdsReported(int[] groupIds) {} 3443 3444 @Override 3445 public void onInputStreamIdsReported(int[] inputStreamIds) {} 3446 3447 @Override 3448 public void onDvbsStandardReported(int dvbsStandard) {} 3449 3450 @Override 3451 public void onDvbtStandardReported(int dvbtStandard) {} 3452 3453 @Override 3454 public void onAnalogSifStandardReported(int sif) {} 3455 3456 @Override 3457 public void onAtsc3PlpInfosReported(Atsc3PlpInfo[] atsc3PlpInfos) { 3458 for (Atsc3PlpInfo info : atsc3PlpInfos) { 3459 if (info != null) { 3460 info.getPlpId(); 3461 info.getLlsFlag(); 3462 } 3463 } 3464 } 3465 3466 @Override 3467 public void onHierarchyReported(int hierarchy) {} 3468 3469 @Override 3470 public void onSignalTypeReported(int signalType) {} 3471 3472 @Override 3473 public void onModulationReported(int modulation) { 3474 ScanCallback.super.onModulationReported(modulation); 3475 } 3476 3477 @Override 3478 public void onPriorityReported(boolean isHighPriority) { 3479 ScanCallback.super.onPriorityReported(isHighPriority); 3480 } 3481 3482 @Override 3483 public void onDvbcAnnexReported(int dvbcAnnext) { 3484 ScanCallback.super.onDvbcAnnexReported(dvbcAnnext); 3485 } 3486 3487 @Override 3488 public void onDvbtCellIdsReported(int[] dvbtCellIds) { 3489 ScanCallback.super.onDvbtCellIdsReported(dvbtCellIds); 3490 } 3491 }; 3492 } 3493 3494 // TunerHandler utility for testing Tuner api calls in a different thread 3495 private static final int MSG_TUNER_HANDLER_CREATE = 1; 3496 private static final int MSG_TUNER_HANDLER_TUNE = 2; 3497 private static final int MSG_TUNER_HANDLER_CLOSE = 3; 3498 3499 private ConditionVariable mTunerHandlerTaskComplete = new ConditionVariable(); 3500 3501 private TunerHandler createTunerHandler(Looper looper) { 3502 if (looper != null) { 3503 return new TunerHandler(looper); 3504 } else if ((looper = Looper.myLooper()) != null) { 3505 return new TunerHandler(looper); 3506 } else if ((looper = Looper.getMainLooper()) != null) { 3507 return new TunerHandler(looper); 3508 } 3509 return null; 3510 } 3511 3512 private class TunerHandler extends Handler { 3513 Object mLock = new Object(); 3514 Tuner mHandlersTuner; 3515 int mResult; 3516 3517 private TunerHandler(Looper looper) { 3518 super(looper); 3519 } 3520 3521 public Tuner getTuner() { 3522 synchronized (mLock) { 3523 return mHandlersTuner; 3524 } 3525 } 3526 3527 public int getResult() { 3528 synchronized (mLock) { 3529 return mResult; 3530 } 3531 } 3532 3533 @Override 3534 public void handleMessage(Message msg) { 3535 switch (msg.what) { 3536 case MSG_TUNER_HANDLER_CREATE: { 3537 synchronized (mLock) { 3538 int useCase = msg.arg1; 3539 mHandlersTuner = new Tuner(mContext, null, useCase); 3540 } 3541 break; 3542 } 3543 case MSG_TUNER_HANDLER_TUNE: { 3544 synchronized (mLock) { 3545 FrontendSettings feSettings = (FrontendSettings) msg.obj; 3546 mResult = mHandlersTuner.tune(feSettings); 3547 } 3548 break; 3549 } 3550 case MSG_TUNER_HANDLER_CLOSE: { 3551 synchronized (mLock) { 3552 mHandlersTuner.close(); 3553 } 3554 break; 3555 } 3556 default: 3557 break; 3558 } 3559 mTunerHandlerTaskComplete.open(); 3560 } 3561 } 3562 } 3563