@mentra/acs-meeting 3.2.0-dev.222 → 3.2.0-dev.225
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -3
- package/android/build.gradle +1 -0
- package/android/src/main/java/com/mentra/acsmeeting/AcsMeetingModule.kt +10 -10
- package/android/src/main/java/com/mentra/acsmeeting/AcsMeetingSession.kt +37 -37
- package/android/src/main/java/com/mentra/acsmeeting/audio/UplinkSender.kt +4 -4
- package/android/src/main/java/com/mentra/acsmeeting/source/MeetingVideoSourceSpec.kt +3 -0
- package/android/src/main/java/com/mentra/acsmeeting/video/AcsFrameSender.kt +12 -10
- package/android/src/main/java/com/mentra/acsmeeting/video/I420FormatSpec.kt +2 -0
- package/android/src/main/java/com/mentra/acsmeeting/video/Nv12Packer.kt +2 -0
- package/android/src/test/java/com/mentra/acsmeeting/source/{AcsInvestigationTest.kt → MediaDiagnosticsTest.kt} +10 -10
- package/android/src/test/java/com/mentra/acsmeeting/source/MeetingVideoSourceSpecTest.kt +3 -0
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/VideoQualityTest.kt +2 -2
- package/android/src/test/java/com/mentra/acsmeeting/video/I420FormatSpecTest.kt +2 -0
- package/android/src/test/java/com/mentra/acsmeeting/video/VideoProfileTest.kt +2 -2
- package/build/AcsMeeting.types.d.ts +10 -1
- package/build/AcsMeeting.types.d.ts.map +1 -1
- package/build/AcsMeeting.types.js.map +1 -1
- package/build/AcsMeetingModule.d.ts +2 -2
- package/build/AcsMeetingModule.d.ts.map +1 -1
- package/build/AcsMeetingModule.js.map +1 -1
- package/ios/AcsMeeting.podspec +1 -1
- package/ios/AcsMeetingModule.swift +284 -148
- package/ios/PolicyKit/Package.swift +2 -1
- package/ios/PolicyKit/Sources/AcsAudioPolicy/CallbackOperation.swift +60 -0
- package/ios/PolicyKit/Sources/AcsAudioPolicy/CapturePolicy.swift +5 -0
- package/ios/PolicyKit/Tests/AcsAudioPolicyTests/AcsAudioPolicyTests.swift +1 -0
- package/ios/PolicyKit/Tests/AcsAudioPolicyTests/CallAgentRetirementTests.swift +113 -0
- package/package.json +3 -2
- package/src/AcsMeeting.types.ts +4 -1
- package/src/AcsMeetingModule.ts +2 -2
- package/android/src/androidTest/java/com/mentra/acsmeeting/network/SoftApFeasibilityGateTest.kt +0 -291
- package/android/src/main/java/com/mentra/acsmeeting/network/InternetHold.kt +0 -501
- package/android/src/main/java/com/mentra/acsmeeting/network/Ipv4Prefix.kt +0 -51
- package/android/src/main/java/com/mentra/acsmeeting/network/NetworkFacts.kt +0 -81
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkChangeDetector.kt +0 -355
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkError.kt +0 -109
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkObserver.kt +0 -160
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkReadiness.kt +0 -103
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkRequestSpec.kt +0 -53
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedNetworkState.kt +0 -127
- package/android/src/main/java/com/mentra/acsmeeting/network/ScopedSoftApNetwork.kt +0 -573
- package/android/src/main/java/com/mentra/acsmeeting/source/BitmapFont.kt +0 -99
- package/android/src/main/java/com/mentra/acsmeeting/source/CloudflareWhepSource.kt +0 -487
- package/android/src/main/java/com/mentra/acsmeeting/source/DecodedTrackRelay.kt +0 -147
- package/android/src/main/java/com/mentra/acsmeeting/source/FirstFrameGate.kt +0 -45
- package/android/src/main/java/com/mentra/acsmeeting/source/GlassesMediaSource.kt +0 -143
- package/android/src/main/java/com/mentra/acsmeeting/source/LocalWhipIngestSource.kt +0 -772
- package/android/src/main/java/com/mentra/acsmeeting/source/MediaListeners.kt +0 -57
- package/android/src/main/java/com/mentra/acsmeeting/source/SdpAdapter.kt +0 -17
- package/android/src/main/java/com/mentra/acsmeeting/source/SelectedIcePair.kt +0 -139
- package/android/src/main/java/com/mentra/acsmeeting/source/SoftApIceDiagnosis.kt +0 -144
- package/android/src/main/java/com/mentra/acsmeeting/source/SoftApIcePolicy.kt +0 -46
- package/android/src/main/java/com/mentra/acsmeeting/source/SoftApSdpGuard.kt +0 -160
- package/android/src/main/java/com/mentra/acsmeeting/source/SyntheticFrameFactory.kt +0 -205
- package/android/src/main/java/com/mentra/acsmeeting/source/SyntheticI420Source.kt +0 -214
- package/android/src/main/java/com/mentra/acsmeeting/source/TrackRegistry.kt +0 -33
- package/android/src/main/java/com/mentra/acsmeeting/source/VideoSourceArm.kt +0 -110
- package/android/src/main/java/com/mentra/acsmeeting/source/WhipIngestProtocol.kt +0 -207
- package/android/src/main/java/com/mentra/acsmeeting/source/WhipIngestServer.kt +0 -356
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/AvSyncProbe.kt +0 -155
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/ChromaProbe.kt +0 -78
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/PipelineStats.kt +0 -372
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/PipelineTicker.kt +0 -79
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/ProcessCpu.kt +0 -15
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/RingPercentile.kt +0 -48
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/VideoQuality.kt +0 -178
- package/android/src/main/java/com/mentra/acsmeeting/telemetry/VideoRateVerdict.kt +0 -145
- package/android/src/main/java/com/mentra/acsmeeting/trace/SoftApTrace.kt +0 -143
- package/android/src/main/java/com/mentra/acsmeeting/video/FrameGeometry.kt +0 -22
- package/android/src/main/java/com/mentra/acsmeeting/video/I420Packer.kt +0 -72
- package/android/src/test/java/com/mentra/acsmeeting/network/InternetHoldLifecycleTest.kt +0 -102
- package/android/src/test/java/com/mentra/acsmeeting/network/InternetHoldTest.kt +0 -148
- package/android/src/test/java/com/mentra/acsmeeting/network/Ipv4PrefixTest.kt +0 -59
- package/android/src/test/java/com/mentra/acsmeeting/network/NetworkFactsTest.kt +0 -59
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedLocalNetworkPermissionTest.kt +0 -35
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkChangeDetectorTest.kt +0 -165
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkErrorTest.kt +0 -96
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkLifecycleTest.kt +0 -187
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkObserverTest.kt +0 -172
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkReadinessTest.kt +0 -141
- package/android/src/test/java/com/mentra/acsmeeting/network/ScopedNetworkRequestSpecTest.kt +0 -69
- package/android/src/test/java/com/mentra/acsmeeting/source/BitmapFontTest.kt +0 -22
- package/android/src/test/java/com/mentra/acsmeeting/source/DecodedTrackRelayTest.kt +0 -41
- package/android/src/test/java/com/mentra/acsmeeting/source/FirstFrameGateTest.kt +0 -60
- package/android/src/test/java/com/mentra/acsmeeting/source/GlassesMediaSourceTest.kt +0 -151
- package/android/src/test/java/com/mentra/acsmeeting/source/I420PlanesTest.kt +0 -67
- package/android/src/test/java/com/mentra/acsmeeting/source/SelectedIcePairTest.kt +0 -165
- package/android/src/test/java/com/mentra/acsmeeting/source/SoftApIceDiagnosisTest.kt +0 -148
- package/android/src/test/java/com/mentra/acsmeeting/source/SoftApIcePolicyTest.kt +0 -76
- package/android/src/test/java/com/mentra/acsmeeting/source/SoftApSdpGuardTest.kt +0 -275
- package/android/src/test/java/com/mentra/acsmeeting/source/SyntheticFrameFactoryTest.kt +0 -193
- package/android/src/test/java/com/mentra/acsmeeting/source/SyntheticI420SourceTest.kt +0 -176
- package/android/src/test/java/com/mentra/acsmeeting/source/TrackRegistryTest.kt +0 -45
- package/android/src/test/java/com/mentra/acsmeeting/source/WhipIngestProtocolTest.kt +0 -356
- package/android/src/test/java/com/mentra/acsmeeting/source/WhipIngestServerLoopbackTest.kt +0 -411
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/AvSyncProbeTest.kt +0 -83
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/ChromaProbeTest.kt +0 -61
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/PipelineStatsTest.kt +0 -322
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/ProcessCpuTest.kt +0 -18
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/RingPercentileTest.kt +0 -49
- package/android/src/test/java/com/mentra/acsmeeting/telemetry/VideoRateVerdictTest.kt +0 -149
- package/android/src/test/java/com/mentra/acsmeeting/trace/SoftApTraceTest.kt +0 -97
- package/android/src/test/java/com/mentra/acsmeeting/video/FrameGeometryTest.kt +0 -33
- package/android/src/test/java/com/mentra/acsmeeting/video/I420PackerTest.kt +0 -126
- package/ios/PolicyKit/Sources/AcsAudioPolicy/GlassesMediaSource.swift +0 -68
- package/ios/WhepVideoSource.swift +0 -356
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
package com.mentra.acsmeeting.network
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Decides when a joined scoped network is actually ready for ICE to gather on.
|
|
5
|
-
*
|
|
6
|
-
* `onAvailable` is not that moment. Android's own guidance is to wait for `onLinkPropertiesChanged`
|
|
7
|
-
* and `onCapabilitiesChanged` rather than reading properties synchronously inside `onAvailable`, and
|
|
8
|
-
* on device the consequence was concrete: the hotspot address can land in the kernel's interface
|
|
9
|
-
* table *after* `onAvailable` returns, and libwebrtc gathers from that table. Starting ingest on
|
|
10
|
-
* `onAvailable` therefore raced the address into existence, and losing that race is indistinguishable
|
|
11
|
-
* from the wiring bugs it was mistaken for.
|
|
12
|
-
*
|
|
13
|
-
* Readiness needs agreement from three places, so all three are recorded separately and the missing
|
|
14
|
-
* one is named. The kernel table is the odd one out: it has no callback, so the shell polls it and
|
|
15
|
-
* feeds the answer in through [onInterfaceTable].
|
|
16
|
-
*
|
|
17
|
-
* Pure and mutable-but-self-contained, so the awkward orderings are unit testable without a device.
|
|
18
|
-
*/
|
|
19
|
-
class ScopedNetworkReadiness {
|
|
20
|
-
|
|
21
|
-
/** What each source has reported so far. Null means "not yet", not "absent". */
|
|
22
|
-
data class Observations(
|
|
23
|
-
val available: Boolean = false,
|
|
24
|
-
val capabilities: Boolean = false,
|
|
25
|
-
val linkInterface: String? = null,
|
|
26
|
-
val linkAddress: String? = null,
|
|
27
|
-
val tableOwner: String? = null,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
sealed interface Verdict {
|
|
31
|
-
/**
|
|
32
|
-
* [owner] is the interface the kernel says holds [address]. It can differ from
|
|
33
|
-
* [interfaceName], which is what `LinkProperties` claimed — a disagreement worth logging,
|
|
34
|
-
* not worth blocking on, since ICE only ever uses the address.
|
|
35
|
-
*/
|
|
36
|
-
data class Ready(
|
|
37
|
-
val address: String,
|
|
38
|
-
val interfaceName: String?,
|
|
39
|
-
val owner: String,
|
|
40
|
-
) : Verdict
|
|
41
|
-
|
|
42
|
-
/** [missing] names the one source still to report, for the timeout message. */
|
|
43
|
-
data class Waiting(val missing: String) : Verdict
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@Volatile
|
|
47
|
-
var observations = Observations()
|
|
48
|
-
private set
|
|
49
|
-
|
|
50
|
-
private val lock = Any()
|
|
51
|
-
|
|
52
|
-
fun onAvailable() = update { it.copy(available = true) }
|
|
53
|
-
|
|
54
|
-
fun onCapabilities() = update { it.copy(capabilities = true) }
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Taken verbatim: `LinkProperties` carries the network's whole current state, so a later
|
|
58
|
-
* callback without an address means the address is gone, not that the old one still holds.
|
|
59
|
-
*/
|
|
60
|
-
fun onLinkProperties(interfaceName: String?, address: String?) =
|
|
61
|
-
update { it.copy(linkInterface = interfaceName, linkAddress = address) }
|
|
62
|
-
|
|
63
|
-
/** Seed from the synchronous read in `onAvailable`; never clears what a callback reported. */
|
|
64
|
-
fun seedLinkProperties(interfaceName: String?, address: String?) =
|
|
65
|
-
update {
|
|
66
|
-
if (address == null) it else it.copy(linkInterface = interfaceName, linkAddress = address)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
fun onInterfaceTable(owner: String?) = update { it.copy(tableOwner = owner) }
|
|
70
|
-
|
|
71
|
-
fun reset() = update { Observations() }
|
|
72
|
-
|
|
73
|
-
fun verdict(): Verdict = verdictOf(observations)
|
|
74
|
-
|
|
75
|
-
/** True once everything with a callback has reported, so only the table poll is left. */
|
|
76
|
-
fun callbacksSatisfied(): Boolean = callbacksSatisfiedBy(observations)
|
|
77
|
-
|
|
78
|
-
private inline fun update(transform: (Observations) -> Observations) {
|
|
79
|
-
synchronized(lock) { observations = transform(observations) }
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
companion object {
|
|
83
|
-
fun callbacksSatisfiedBy(observations: Observations): Boolean =
|
|
84
|
-
observations.available && observations.capabilities && observations.linkAddress != null
|
|
85
|
-
|
|
86
|
-
/** Ordered so the named blocker is the earliest unmet one, which is the useful one. */
|
|
87
|
-
fun verdictOf(observations: Observations): Verdict =
|
|
88
|
-
when {
|
|
89
|
-
!observations.available -> Verdict.Waiting("onAvailable")
|
|
90
|
-
!observations.capabilities -> Verdict.Waiting("onCapabilitiesChanged")
|
|
91
|
-
observations.linkAddress == null ->
|
|
92
|
-
Verdict.Waiting("an IPv4 address from onLinkPropertiesChanged")
|
|
93
|
-
observations.tableOwner == null ->
|
|
94
|
-
Verdict.Waiting("the kernel interface table to carry ${observations.linkAddress}")
|
|
95
|
-
else ->
|
|
96
|
-
Verdict.Ready(
|
|
97
|
-
observations.linkAddress,
|
|
98
|
-
observations.linkInterface,
|
|
99
|
-
observations.tableOwner,
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
package com.mentra.acsmeeting.network
|
|
2
|
-
|
|
3
|
-
import android.net.NetworkCapabilities
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Declarative description of the SoftAP network request.
|
|
7
|
-
*
|
|
8
|
-
* `NetworkRequest.Builder` cannot be constructed in a plain JVM test, so the shape of the request
|
|
9
|
-
* lives here as data and [ScopedSoftApNetwork] translates it into the real builder. That makes the
|
|
10
|
-
* one property this architecture depends on — that the request does **not** ask for
|
|
11
|
-
* `NET_CAPABILITY_INTERNET` — assertable without a device.
|
|
12
|
-
*
|
|
13
|
-
* Dropping the internet capability is what keeps the phone dual-homed: Android will not promote the
|
|
14
|
-
* glasses hotspot to the default network, so ACS traffic stays on cellular while media crosses the
|
|
15
|
-
* local link. The other half of that guarantee is the MTK firmware patch that stops the AP
|
|
16
|
-
* advertising a default route.
|
|
17
|
-
*/
|
|
18
|
-
data class ScopedNetworkRequestSpec(
|
|
19
|
-
val ssid: String,
|
|
20
|
-
val passphrase: String,
|
|
21
|
-
val transportTypes: Set<Int>,
|
|
22
|
-
val removedCapabilities: Set<Int>,
|
|
23
|
-
val timeoutMs: Int,
|
|
24
|
-
) {
|
|
25
|
-
/** True when the request cannot be satisfied by, or promoted to, an internet-bearing network. */
|
|
26
|
-
val avoidsInternetCapability: Boolean
|
|
27
|
-
get() = removedCapabilities.contains(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
|
28
|
-
|
|
29
|
-
val hasPassphrase: Boolean
|
|
30
|
-
get() = passphrase.isNotEmpty()
|
|
31
|
-
|
|
32
|
-
companion object {
|
|
33
|
-
/**
|
|
34
|
-
* Android caps `requestNetwork` timeouts well above this; 30 s matches the value the
|
|
35
|
-
* Bluetooth SDK already uses for the same hotspot and is long enough for a cold AP start.
|
|
36
|
-
*/
|
|
37
|
-
const val DEFAULT_TIMEOUT_MS = 30_000
|
|
38
|
-
|
|
39
|
-
/** The canonical SoftAP request. Every caller should go through this. */
|
|
40
|
-
fun forSoftAp(
|
|
41
|
-
ssid: String,
|
|
42
|
-
passphrase: String,
|
|
43
|
-
timeoutMs: Int = DEFAULT_TIMEOUT_MS,
|
|
44
|
-
): ScopedNetworkRequestSpec =
|
|
45
|
-
ScopedNetworkRequestSpec(
|
|
46
|
-
ssid = ssid,
|
|
47
|
-
passphrase = passphrase,
|
|
48
|
-
transportTypes = setOf(NetworkCapabilities.TRANSPORT_WIFI),
|
|
49
|
-
removedCapabilities = setOf(NetworkCapabilities.NET_CAPABILITY_INTERNET),
|
|
50
|
-
timeoutMs = timeoutMs,
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
package com.mentra.acsmeeting.network
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pure lifecycle state machine for a scoped SoftAP network join.
|
|
5
|
-
*
|
|
6
|
-
* Split from the Android shell so the awkward parts — duplicate callbacks, callbacks arriving after
|
|
7
|
-
* a cancel, a timeout racing a late `onAvailable` — are unit testable without a device. The shell
|
|
8
|
-
* ([ScopedSoftApNetwork]) owns `ConnectivityManager` and forwards raw callbacks in here.
|
|
9
|
-
*
|
|
10
|
-
* `ConnectivityManager` gives no ordering or at-most-once guarantee: `onAvailable` can fire more
|
|
11
|
-
* than once, `onCapabilitiesChanged` fires repeatedly, and callbacks from a request that was already
|
|
12
|
-
* unregistered can still land. Every transition below is therefore idempotent and generation-guarded.
|
|
13
|
-
*/
|
|
14
|
-
class ScopedNetworkState {
|
|
15
|
-
|
|
16
|
-
enum class Phase {
|
|
17
|
-
/** No request outstanding. */
|
|
18
|
-
IDLE,
|
|
19
|
-
|
|
20
|
-
/** `requestNetwork` issued, waiting for a usable network. */
|
|
21
|
-
REQUESTING,
|
|
22
|
-
|
|
23
|
-
/** Network joined and usable. */
|
|
24
|
-
AVAILABLE,
|
|
25
|
-
|
|
26
|
-
/** Terminal for this generation: released, lost, timed out, or failed. */
|
|
27
|
-
LOST,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Why a join ended without producing a usable network. */
|
|
31
|
-
enum class Failure {
|
|
32
|
-
NONE,
|
|
33
|
-
TIMEOUT,
|
|
34
|
-
UNAVAILABLE,
|
|
35
|
-
LOST,
|
|
36
|
-
PERMISSION_DENIED,
|
|
37
|
-
REQUEST_FAILED,
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var phase: Phase = Phase.IDLE
|
|
41
|
-
private set
|
|
42
|
-
|
|
43
|
-
var failure: Failure = Failure.NONE
|
|
44
|
-
private set
|
|
45
|
-
|
|
46
|
-
/** Incremented on every new request so late callbacks from an old one can be rejected. */
|
|
47
|
-
var generation: Int = 0
|
|
48
|
-
private set
|
|
49
|
-
|
|
50
|
-
val isActive: Boolean
|
|
51
|
-
get() = phase == Phase.REQUESTING || phase == Phase.AVAILABLE
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Begin a new join. Any in-flight generation is abandoned, so its callbacks become stale.
|
|
55
|
-
*
|
|
56
|
-
* @return the generation for this request; pass it back to every callback
|
|
57
|
-
*/
|
|
58
|
-
fun startRequest(): Int {
|
|
59
|
-
generation += 1
|
|
60
|
-
phase = Phase.REQUESTING
|
|
61
|
-
failure = Failure.NONE
|
|
62
|
-
return generation
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** True when a callback belongs to the current, still-active generation. */
|
|
66
|
-
fun accepts(callbackGeneration: Int): Boolean = callbackGeneration == generation && isActive
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* A usable network arrived.
|
|
70
|
-
*
|
|
71
|
-
* @return true if this transitioned the machine; false when stale or already available
|
|
72
|
-
*/
|
|
73
|
-
fun onAvailable(callbackGeneration: Int): Boolean {
|
|
74
|
-
if (!accepts(callbackGeneration)) return false
|
|
75
|
-
if (phase == Phase.AVAILABLE) return false // duplicate onAvailable
|
|
76
|
-
phase = Phase.AVAILABLE
|
|
77
|
-
return true
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** The request timed out before a usable network arrived. Ignored once available. */
|
|
81
|
-
fun onTimeout(callbackGeneration: Int): Boolean {
|
|
82
|
-
if (callbackGeneration != generation) return false
|
|
83
|
-
if (phase != Phase.REQUESTING) return false
|
|
84
|
-
phase = Phase.LOST
|
|
85
|
-
failure = Failure.TIMEOUT
|
|
86
|
-
return true
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** The framework reported the network cannot be provided. */
|
|
90
|
-
fun onUnavailable(callbackGeneration: Int): Boolean {
|
|
91
|
-
if (!accepts(callbackGeneration)) return false
|
|
92
|
-
phase = Phase.LOST
|
|
93
|
-
failure = Failure.UNAVAILABLE
|
|
94
|
-
return true
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** The joined network went away. This is the one the call path must react to. */
|
|
98
|
-
fun onLost(callbackGeneration: Int): Boolean {
|
|
99
|
-
if (!accepts(callbackGeneration)) return false
|
|
100
|
-
phase = Phase.LOST
|
|
101
|
-
failure = Failure.LOST
|
|
102
|
-
return true
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** `requestNetwork` threw, or the local-network permission was denied. */
|
|
106
|
-
fun onRequestFailed(callbackGeneration: Int, permissionDenied: Boolean): Boolean {
|
|
107
|
-
if (callbackGeneration != generation) return false
|
|
108
|
-
if (!isActive) return false
|
|
109
|
-
phase = Phase.LOST
|
|
110
|
-
failure = if (permissionDenied) Failure.PERMISSION_DENIED else Failure.REQUEST_FAILED
|
|
111
|
-
return true
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** Caller-initiated teardown. Not a failure. */
|
|
115
|
-
fun release(): Boolean {
|
|
116
|
-
if (!isActive) return false
|
|
117
|
-
phase = Phase.LOST
|
|
118
|
-
failure = Failure.NONE
|
|
119
|
-
return true
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/** Return to IDLE so the same instance can be reused for the next call. */
|
|
123
|
-
fun reset() {
|
|
124
|
-
phase = Phase.IDLE
|
|
125
|
-
failure = Failure.NONE
|
|
126
|
-
}
|
|
127
|
-
}
|