• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.companion.cts.multidevice
18 
19 import android.companion.AssociationInfo
20 import android.companion.CompanionDeviceManager
21 import android.companion.CompanionException
22 import android.content.IntentSender
23 import android.os.OutcomeReceiver
24 import android.security.attestationverification.VerificationToken
25 import java.util.concurrent.CountDownLatch
26 import java.util.concurrent.TimeUnit.SECONDS
27 import java.util.concurrent.TimeoutException
28 import java.util.concurrent.atomic.AtomicBoolean
29 import java.util.function.BiConsumer
30 
31 /** Blocking callbacks for CDM callbacks. */
32 object CallbackUtils {
33     private const val TAG = "CDM_CallbackUtils"
34     private const val CALLBACK_TIMEOUT_SEC = 30L
35 
36     class AssociationCallback : CompanionDeviceManager.Callback() {
37         private val pending = CountDownLatch(1)
38         private val created = CountDownLatch(1)
39 
40         private var pendingIntent: IntentSender? = null
41         private var associationInfo: AssociationInfo? = null
42         private var error: String? = null
43 
onAssociationPendingnull44         override fun onAssociationPending(intentSender: IntentSender) {
45             this.pendingIntent = intentSender
46             pending.countDown()
47         }
48 
onAssociationCreatednull49         override fun onAssociationCreated(associationInfo: AssociationInfo) {
50             this.associationInfo = associationInfo
51             created.countDown()
52         }
53 
onFailurenull54         override fun onFailure(error: CharSequence?) {
55             this.error = error?.toString() ?: "There was an unexpected failure."
56             pending.countDown()
57             created.countDown()
58         }
59 
waitForPendingIntentnull60         fun waitForPendingIntent(): IntentSender? {
61             if (!pending.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
62                 throw TimeoutException("Pending association request timed out.")
63             }
64 
65             error?.let {
66                 throw RuntimeException(it)
67             }
68 
69             return pendingIntent
70         }
71 
waitForAssociationnull72         fun waitForAssociation(): AssociationInfo? {
73             if (!created.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
74                 throw TimeoutException("Association request timed out.")
75             }
76 
77             error?.let {
78                 throw RuntimeException(it)
79             }
80 
81             return associationInfo
82         }
83     }
84 
85     class SystemDataTransferCallback : OutcomeReceiver<Void, CompanionException> {
86         private val completed = CountDownLatch(1)
87 
88         private var error: CompanionException? = null
89 
onResultnull90         override fun onResult(result: Void?) {
91             completed.countDown()
92         }
93 
onErrornull94         override fun onError(error: CompanionException) {
95             this.error = error
96             completed.countDown()
97         }
98 
waitForCompletionnull99         fun waitForCompletion() {
100             if (!completed.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
101                 throw TimeoutException("System data transfer timed out.")
102             }
103 
104             error?.let {
105                 throw it
106             }
107         }
108     }
109 
110     class AttestationVerificationCallback : BiConsumer<Int, VerificationToken?> {
111         private val completed = CountDownLatch(1)
112         private val result = AtomicBoolean(false)
113 
acceptnull114         override fun accept(resultCode: Int, token: VerificationToken?) {
115             result.set(resultCode == 0)
116             completed.countDown()
117         }
118 
waitForResultnull119         fun waitForResult(): Boolean {
120             if (!completed.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
121                 throw TimeoutException("Attestation verification timed out.")
122             }
123 
124             return result.get()
125         }
126     }
127 }
128