blob: b5966daf7bcc9fcc708745845e7245145406bb71 [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.window.embedding
import android.util.Log
import androidx.window.core.ExperimentalWindowApi
import androidx.window.embedding.EmbeddingInterfaceCompat.EmbeddingCallbackInterface
import androidx.window.extensions.WindowExtensionsProvider
import androidx.window.extensions.embedding.ActivityEmbeddingComponent
import androidx.window.extensions.embedding.SplitInfo
import java.util.function.Consumer
import androidx.window.extensions.embedding.EmbeddingRule as ExtensionsEmbeddingRule
/**
* Adapter implementation for different historical versions of activity embedding OEM interface in
* [ActivityEmbeddingComponent]. Only supports the single current version in this implementation.
*/
@ExperimentalWindowApi
internal class EmbeddingCompat constructor(
private val embeddingExtension: ActivityEmbeddingComponent,
private val adapter: EmbeddingAdapter
) : EmbeddingInterfaceCompat {
constructor() : this(
embeddingComponent(),
EmbeddingAdapter()
)
override fun setSplitRules(rules: Set<EmbeddingRule>) {
embeddingExtension.setEmbeddingRules(adapter.translate(rules))
}
override fun setEmbeddingCallback(embeddingCallback: EmbeddingCallbackInterface) {
try {
embeddingExtension.setSplitInfoCallback { splitInfoList ->
embeddingCallback.onSplitInfoChanged(
adapter.translate(splitInfoList)
)
}
} catch (e: NoSuchMethodError) {
// TODO(b/203472665): Remove the try-catch wrapper after the issue is resolved
}
}
companion object {
const val DEBUG = true
private const val TAG = "EmbeddingCompat"
fun getExtensionApiLevel(): Int? {
return try {
WindowExtensionsProvider.getWindowExtensions().vendorApiLevel
} catch (e: NoClassDefFoundError) {
if (DEBUG) {
Log.d(TAG, "Embedding extension version not found")
}
null
} catch (e: UnsupportedOperationException) {
if (DEBUG) {
Log.d(TAG, "Stub Extension")
}
null
}
}
fun isEmbeddingAvailable(): Boolean {
return try {
WindowExtensionsProvider.getWindowExtensions().activityEmbeddingComponent != null
} catch (e: NoClassDefFoundError) {
if (DEBUG) {
Log.d(TAG, "Embedding extension version not found")
}
false
} catch (e: UnsupportedOperationException) {
if (DEBUG) {
Log.d(TAG, "Stub Extension")
}
false
}
}
fun embeddingComponent(): ActivityEmbeddingComponent {
return if (isEmbeddingAvailable()) {
WindowExtensionsProvider.getWindowExtensions().getActivityEmbeddingComponent()
?: EmptyEmbeddingComponent()
} else {
EmptyEmbeddingComponent()
}
}
}
}
// Empty implementation of the embedding component to use when the device doesn't provide one and
// avoid null checks.
private class EmptyEmbeddingComponent : ActivityEmbeddingComponent {
override fun setEmbeddingRules(splitRules: MutableSet<ExtensionsEmbeddingRule>) {
// empty
}
override fun setSplitInfoCallback(consumer: Consumer<MutableList<SplitInfo>>) {
// empty
}
}