1 /*
2  * Copyright (C) 2022 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.multidevices
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 java.util.concurrent.CountDownLatch
25 import java.util.concurrent.TimeUnit.SECONDS
26 import java.util.concurrent.TimeoutException
27 
28 /** Blocking callbacks for Wi-Fi Aware and Connectivity Manager. */
29 object CallbackUtils {
30     private const val TAG = "CDM_CallbackUtils"
31     private const val CALLBACK_TIMEOUT_SEC = 30L
32     private const val MESSAGE_CALLBACK_TIMEOUT_SEC = 5L
33 
34     class AssociationCallback : CompanionDeviceManager.Callback() {
35         private val pending = CountDownLatch(1)
36         private val created = CountDownLatch(1)
37 
38         private var pendingIntent: IntentSender? = null
39         private var associationInfo: AssociationInfo? = null
40         private var error: String? = null
41 
onAssociationPendingnull42         override fun onAssociationPending(intentSender: IntentSender) {
43             this.pendingIntent = intentSender
44             pending.countDown()
45         }
46 
onAssociationCreatednull47         override fun onAssociationCreated(associationInfo: AssociationInfo) {
48             this.associationInfo = associationInfo
49             created.countDown()
50         }
51 
onFailurenull52         override fun onFailure(error: CharSequence?) {
53             this.error = error?.toString() ?: "There was an unexpected failure."
54             pending.countDown()
55             created.countDown()
56         }
57 
waitForPendingIntentnull58         fun waitForPendingIntent(): IntentSender? {
59             if (!pending.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
60                 throw TimeoutException("Pending association request timed out.")
61             }
62 
63             error?.let {
64                 throw CompanionException(it)
65             }
66 
67             return pendingIntent
68         }
69 
waitForAssociationnull70         fun waitForAssociation(): AssociationInfo? {
71             if (!created.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
72                 throw TimeoutException("Association request timed out.")
73             }
74 
75             error?.let {
76                 throw CompanionException(it)
77             }
78 
79             return associationInfo
80         }
81     }
82 
83     class SystemDataTransferCallback : OutcomeReceiver<Void, CompanionException> {
84         private val completed = CountDownLatch(1)
85 
86         private var error: CompanionException? = null
87 
onResultnull88         override fun onResult(result: Void?) {
89             completed.countDown()
90         }
91 
onErrornull92         override fun onError(error: CompanionException) {
93             this.error = error
94             completed.countDown()
95         }
96 
waitForCompletionnull97         fun waitForCompletion() {
98             if (!completed.await(CALLBACK_TIMEOUT_SEC, SECONDS)) {
99                 throw TimeoutException("System data transfer timed out.")
100             }
101 
102             error?.let {
103                 throw it
104             }
105         }
106     }
107 }
108