Merge "feat: add base media player container" into androidx-main
diff --git a/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
index 76b1f3e..656270a 100644
--- a/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
+++ b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class ActivityComposeIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ActivityResultLaunchDetector.LaunchDuringComposition
diff --git a/activity/activity-lint/src/main/java/androidx/activity/lint/ActivityIssueRegistry.kt b/activity/activity-lint/src/main/java/androidx/activity/lint/ActivityIssueRegistry.kt
index 168ec91..794624c 100644
--- a/activity/activity-lint/src/main/java/androidx/activity/lint/ActivityIssueRegistry.kt
+++ b/activity/activity-lint/src/main/java/androidx/activity/lint/ActivityIssueRegistry.kt
@@ -26,7 +26,7 @@
@Suppress("UnstableApiUsage")
class ActivityIssueRegistry : IssueRegistry() {
// tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ActivityResultFragmentVersionDetector.ISSUE
diff --git a/activity/activity/api/1.7.0-beta02.txt b/activity/activity/api/1.7.0-beta02.txt
index bf98034..4bbcdbb 100644
--- a/activity/activity/api/1.7.0-beta02.txt
+++ b/activity/activity/api/1.7.0-beta02.txt
@@ -319,7 +319,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/api/current.txt b/activity/activity/api/current.txt
index bf98034..4bbcdbb 100644
--- a/activity/activity/api/current.txt
+++ b/activity/activity/api/current.txt
@@ -319,7 +319,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/api/public_plus_experimental_1.7.0-beta02.txt b/activity/activity/api/public_plus_experimental_1.7.0-beta02.txt
index bf98034..4bbcdbb 100644
--- a/activity/activity/api/public_plus_experimental_1.7.0-beta02.txt
+++ b/activity/activity/api/public_plus_experimental_1.7.0-beta02.txt
@@ -319,7 +319,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/api/public_plus_experimental_current.txt b/activity/activity/api/public_plus_experimental_current.txt
index bf98034..4bbcdbb 100644
--- a/activity/activity/api/public_plus_experimental_current.txt
+++ b/activity/activity/api/public_plus_experimental_current.txt
@@ -319,7 +319,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/api/restricted_1.7.0-beta02.txt b/activity/activity/api/restricted_1.7.0-beta02.txt
index 7561e11..2997940 100644
--- a/activity/activity/api/restricted_1.7.0-beta02.txt
+++ b/activity/activity/api/restricted_1.7.0-beta02.txt
@@ -318,7 +318,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/api/restricted_current.txt b/activity/activity/api/restricted_current.txt
index 7561e11..2997940 100644
--- a/activity/activity/api/restricted_current.txt
+++ b/activity/activity/api/restricted_current.txt
@@ -318,7 +318,9 @@
method @Deprecated public static final boolean isPhotoPickerAvailable();
method public static final boolean isPhotoPickerAvailable(android.content.Context context);
method public final android.net.Uri? parseResult(int resultCode, android.content.Intent? intent);
+ field public static final String ACTION_SYSTEM_FALLBACK_PICK_IMAGES = "androidx.activity.result.contract.action.PICK_IMAGES";
field public static final androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion Companion;
+ field public static final String EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX = "androidx.activity.result.contract.extra.PICK_IMAGES_MAX";
}
public static final class ActivityResultContracts.PickVisualMedia.Companion {
diff --git a/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.kt b/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.kt
index 81d62c5..ed0c940 100644
--- a/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.kt
+++ b/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.kt
@@ -32,9 +32,11 @@
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.GetMultipleContents.Companion.getClipDataUris
+import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.ACTION_SYSTEM_FALLBACK_PICK_IMAGES
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.GMS_ACTION_PICK_IMAGES
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.GMS_EXTRA_PICK_IMAGES_MAX
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.getGmsPicker
+import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.getSystemFallbackPicker
import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.Companion.ACTION_INTENT_SENDER_REQUEST
import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.Companion.EXTRA_SEND_INTENT_EXCEPTION
import androidx.annotation.CallSuper
@@ -608,8 +610,21 @@
}
/**
- * An [ActivityResultContract] to use the photo picker through [MediaStore.ACTION_PICK_IMAGES]
- * when available, and else rely on ACTION_OPEN_DOCUMENT.
+ * An [ActivityResultContract] to use the
+ * [Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker)
+ * to select a single image, video, or other type of visual media.
+ *
+ * This contract always prefers the system framework provided Photo Picker available via
+ * [MediaStore.ACTION_PICK_IMAGES] when it is available, but will also provide a fallback
+ * on devices that it is not available to ensure a consistent API surface across all
+ * Android API 19 or higher devices.
+ *
+ * The priority order for handling the Photo Picker is:
+ * 1. The system framework provided [MediaStore.ACTION_PICK_IMAGES].
+ * - An OEM can provide a system app that implements [ACTION_SYSTEM_FALLBACK_PICK_IMAGES] to
+ * provide a consistent Photo Picker to older devices.
+ * - [Intent.ACTION_OPEN_DOCUMENT] is used as a final fallback on all Android API 19 or
+ * higher devices.
*
* The input is a [PickVisualMediaRequest].
*
@@ -624,13 +639,15 @@
companion object {
/**
* Check if the current device has support for the photo picker by checking the running
- * Android version or the SDK extension version (not including the picker
- * provided by Google Play services)
+ * Android version or the SDK extension version.
+ *
+ * Note that this does not check for any Intent handled by
+ * [ACTION_SYSTEM_FALLBACK_PICK_IMAGES].
*/
@SuppressLint("ClassVerificationFailure", "NewApi")
@Deprecated(
message = "This method is deprecated in favor of isPhotoPickerAvailable(context) " +
- "to support the picker provided by Google Play services",
+ "to support the picker provided by updatable system apps",
replaceWith = ReplaceWith("isPhotoPickerAvailable(context)")
)
@JvmStatic
@@ -638,6 +655,37 @@
return isSystemPickerAvailable()
}
+ /**
+ * In cases where the system framework provided [MediaStore.ACTION_PICK_IMAGES]
+ * Photo Picker cannot be implemented, OEMs or system apps can provide a consistent
+ * Photo Picker experience to those devices by creating an Activity that handles
+ * this action. This app must also include [Intent.CATEGORY_DEFAULT] in the activity's
+ * intent filter.
+ *
+ * Only system apps can implement this action - any non-system apps will be ignored
+ * when searching for the activities that handle this Intent.
+ *
+ * Note: this should not be used directly, instead relying on the selection logic
+ * done by [createIntent] to create the correct Intent for the current device.
+ */
+ @Suppress("ActionValue") /* Don't include SYSTEM_FALLBACk in the action */
+ const val ACTION_SYSTEM_FALLBACK_PICK_IMAGES =
+ "androidx.activity.result.contract.action.PICK_IMAGES"
+
+ /**
+ * Extra that will be sent by [PickMultipleVisualMedia] to an Activity that handles
+ * [ACTION_SYSTEM_FALLBACK_PICK_IMAGES] that indicates that maximum number of photos
+ * the user should select.
+ *
+ * If this extra is not present, only a single photo should be selectable.
+ *
+ * If this extra is present but equal to [Int.MAX_VALUE], then no limit should
+ * be enforced.
+ */
+ @Suppress("ActionValue") /* Don't include SYSTEM_FALLBACk in the extra */
+ const val EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX =
+ "androidx.activity.result.contract.extra.PICK_IMAGES_MAX"
+
internal const val GMS_ACTION_PICK_IMAGES =
"com.google.android.gms.provider.action.PICK_IMAGES"
internal const val GMS_EXTRA_PICK_IMAGES_MAX =
@@ -645,19 +693,22 @@
/**
* Check if the current device has support for the photo picker by checking the running
- * Android version, the SDK extension version or the picker provided by Google Play
- * services
+ * Android version, the SDK extension version or the picker provided by
+ * a system app implementing [ACTION_SYSTEM_FALLBACK_PICK_IMAGES].
*/
@SuppressLint("ClassVerificationFailure", "NewApi")
@JvmStatic
fun isPhotoPickerAvailable(context: Context): Boolean {
- return isSystemPickerAvailable() || isGmsPickerAvailable(context)
+ return isSystemPickerAvailable() || isSystemFallbackPickerAvailable(context) ||
+ isGmsPickerAvailable(context)
}
/**
- * Check if the current device has support for the Android photo picker by checking the
- * running Android version or the SDK extension version (not including the picker
- * provided by Google Play services)
+ * Check if the current device has support for the system framework provided photo
+ * picker by checking the running Android version or the SDK extension version.
+ *
+ * Note that this does not check for any Intent handled by
+ * [ACTION_SYSTEM_FALLBACK_PICK_IMAGES].
*/
@SuppressLint("ClassVerificationFailure", "NewApi")
@JvmStatic
@@ -674,6 +725,20 @@
}
@JvmStatic
+ internal fun isSystemFallbackPickerAvailable(context: Context): Boolean {
+ return getSystemFallbackPicker(context) != null
+ }
+
+ @Suppress("DEPRECATION")
+ @JvmStatic
+ internal fun getSystemFallbackPicker(context: Context): ResolveInfo? {
+ return context.packageManager.resolveActivity(
+ Intent(ACTION_SYSTEM_FALLBACK_PICK_IMAGES),
+ PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_SYSTEM_ONLY
+ )
+ }
+
+ @JvmStatic
internal fun isGmsPickerAvailable(context: Context): Boolean {
return getGmsPicker(context) != null
}
@@ -730,6 +795,12 @@
Intent(MediaStore.ACTION_PICK_IMAGES).apply {
type = getVisualMimeType(input.mediaType)
}
+ } else if (isSystemFallbackPickerAvailable(context)) {
+ val fallbackPicker = checkNotNull(getSystemFallbackPicker(context)).activityInfo
+ Intent(ACTION_SYSTEM_FALLBACK_PICK_IMAGES).apply {
+ setClassName(fallbackPicker.applicationInfo.packageName, fallbackPicker.name)
+ type = getVisualMimeType(input.mediaType)
+ }
} else if (isGmsPickerAvailable(context)) {
val gmsPicker = checkNotNull(getGmsPicker(context)).activityInfo
Intent(GMS_ACTION_PICK_IMAGES).apply {
@@ -769,12 +840,27 @@
}
/**
- * An [ActivityResultContract] to use the Photo Picker through [MediaStore.ACTION_PICK_IMAGES]
- * when available, and else rely on ACTION_OPEN_DOCUMENT.
+ * An [ActivityResultContract] to use the
+ * [Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker)
+ * to select a single image, video, or other type of visual media.
*
- * The constructor accepts one parameter `maxItems` to limit the number of selectable items when
- * using the photo picker to return. Keep in mind that this parameter isn't supported on devices
- * when the photo picker isn't available.
+ * This contract always prefers the system framework provided Photo Picker available via
+ * [MediaStore.ACTION_PICK_IMAGES] when it is available, but will also provide a fallback
+ * on devices that it is not available to provide a consistent API surface across all
+ * Android API 19 or higher devices.
+ *
+ * The priority order for handling the Photo Picker is:
+ * 1. The system framework provided [MediaStore.ACTION_PICK_IMAGES].
+ * - An OEM can provide a system app that implements
+ * [PickVisualMedia.ACTION_SYSTEM_FALLBACK_PICK_IMAGES] to provide a consistent Photo Picker
+ * to older devices. These system apps may handle the
+ * [PickVisualMedia.EXTRA_SYSTEM_FALLBACK_PICK_IMAGES_MAX] extra to respect the
+ * [maxItems] passed to this contract.
+ * - [Intent.ACTION_OPEN_DOCUMENT] is used as a final fallback on all Android API 19 or
+ * higher devices. This Intent does not allow limiting the max items the user selects.
+ *
+ * The constructor accepts one parameter [maxItems] to limit the number of selectable items when
+ * using the photo picker to return.
*
* The input is a [PickVisualMediaRequest].
*
@@ -808,6 +894,13 @@
putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxItems)
}
+ } else if (PickVisualMedia.isSystemFallbackPickerAvailable(context)) {
+ val fallbackPicker = checkNotNull(getSystemFallbackPicker(context)).activityInfo
+ Intent(ACTION_SYSTEM_FALLBACK_PICK_IMAGES).apply {
+ setClassName(fallbackPicker.applicationInfo.packageName, fallbackPicker.name)
+ type = PickVisualMedia.getVisualMimeType(input.mediaType)
+ putExtra(GMS_EXTRA_PICK_IMAGES_MAX, maxItems)
+ }
} else if (PickVisualMedia.isGmsPickerAvailable(context)) {
val gmsPicker = checkNotNull(getGmsPicker(context)).activityInfo
Intent(GMS_ACTION_PICK_IMAGES).apply {
@@ -848,8 +941,8 @@
/**
* The system photo picker has a maximum limit of selectable items returned by
* [MediaStore.getPickImagesMaxLimit()]
- * On devices supporting picker provided by Google Play services, the limit is ignored
- * if it's higher than the allowed limit.
+ * On devices supporting picker provided via [ACTION_SYSTEM_FALLBACK_PICK_IMAGES],
+ * the limit may be ignored if it's higher than the allowed limit.
* On devices not supporting the photo picker, the limit is ignored.
*
* @see MediaStore.EXTRA_PICK_IMAGES_MAX
diff --git a/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalIssueRegistry.kt b/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalIssueRegistry.kt
index 1cf3f9a..0f6ff59 100644
--- a/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalIssueRegistry.kt
+++ b/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalIssueRegistry.kt
@@ -23,7 +23,7 @@
@Suppress("UnstableApiUsage")
class ExperimentalIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues get() = ExperimentalDetector.ISSUES + AnnotationRetentionDetector.ISSUES
override val vendor = Vendor(
feedbackUrl = "https://issuetracker.google.com/issues/new?component=459778",
diff --git a/appactions/interaction/interaction-capabilities-core/build.gradle b/appactions/interaction/interaction-capabilities-core/build.gradle
index fdb938f..2fccf45 100644
--- a/appactions/interaction/interaction-capabilities-core/build.gradle
+++ b/appactions/interaction/interaction-capabilities-core/build.gradle
@@ -24,11 +24,13 @@
}
dependencies {
+ api(libs.kotlinStdlib)
api(libs.autoValueAnnotations)
api(libs.kotlinStdlib)
annotationProcessor(libs.autoValue)
implementation(libs.protobufLite)
implementation(libs.guavaListenableFuture)
+ implementation(libs.kotlinCoroutinesGuava)
implementation("androidx.concurrent:concurrent-futures:1.1.0")
implementation(project(":appactions:interaction:interaction-proto"))
@@ -37,6 +39,7 @@
testImplementation(libs.truth)
testImplementation(libs.testCore)
testImplementation(libs.mockitoCore)
+ testImplementation(libs.mockitoKotlin4)
testImplementation(libs.kotlinStdlib)
testImplementation(libs.androidLint)
testImplementation(libs.androidLintTests)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AbstractCapabilityBuilder.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AbstractCapabilityBuilder.java
index a7c0999..44762184 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AbstractCapabilityBuilder.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AbstractCapabilityBuilder.java
@@ -18,13 +18,14 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionCapabilityImpl;
+import androidx.appactions.interaction.capabilities.core.impl.SingleTurnCapabilityImpl;
import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec;
import androidx.appactions.interaction.capabilities.core.task.impl.AbstractTaskUpdater;
import androidx.appactions.interaction.capabilities.core.task.impl.TaskCapabilityImpl;
+import com.google.common.util.concurrent.ListenableFuture;
+
import java.util.Objects;
-import java.util.Optional;
/**
* An abstract Builder class for ActionCapability.
@@ -39,7 +40,12 @@
public abstract class AbstractCapabilityBuilder<
BuilderT extends
AbstractCapabilityBuilder<
- BuilderT, PropertyT, ArgumentT, OutputT, ConfirmationT, TaskUpdaterT>,
+ BuilderT,
+ PropertyT,
+ ArgumentT,
+ OutputT,
+ ConfirmationT,
+ TaskUpdaterT>,
PropertyT,
ArgumentT,
OutputT,
@@ -47,14 +53,10 @@
TaskUpdaterT extends AbstractTaskUpdater> {
private final ActionSpec<PropertyT, ArgumentT, OutputT> mActionSpec;
- @Nullable
- private String mId;
- @Nullable
- private PropertyT mProperty;
- @Nullable
- private ActionExecutor<ArgumentT, OutputT> mActionExecutor;
- @Nullable
- private TaskHandler<ArgumentT, OutputT, ConfirmationT, TaskUpdaterT> mTaskHandler;
+ @Nullable private String mId;
+ @Nullable private PropertyT mProperty;
+ @Nullable private ActionExecutor<ArgumentT, OutputT> mActionExecutor;
+ @Nullable private TaskHandler<ArgumentT, OutputT, ConfirmationT, TaskUpdaterT> mTaskHandler;
/**
* @param actionSpec
@@ -90,10 +92,9 @@
/**
* Sets the TaskHandler for this capability. The individual capability factory classes can
- * decide
- * to expose their own public {@code setTaskHandler} method and invoke this parent method.
- * Setting
- * the TaskHandler should build a capability instance that supports multi-turn tasks.
+ * decide to expose their own public {@code setTaskHandler} method and invoke this parent
+ * method. Setting the TaskHandler should build a capability instance that supports multi-turn
+ * tasks.
*/
protected final BuilderT setTaskHandler(
@NonNull TaskHandler<ArgumentT, OutputT, ConfirmationT, TaskUpdaterT> taskHandler) {
@@ -115,22 +116,31 @@
Objects.requireNonNull(mProperty, "property must not be null.");
if (mTaskHandler == null) {
Objects.requireNonNull(mActionExecutor, "actionExecutor must not be null.");
- return new ActionCapabilityImpl<>(
- mActionSpec, Optional.ofNullable(mId), mProperty, mActionExecutor);
+ return new SingleTurnCapabilityImpl<PropertyT, ArgumentT, OutputT>(
+ mId,
+ mActionSpec,
+ mProperty,
+ (hostProperties)->new BaseSession<ArgumentT, OutputT>() {
+ @Override
+ public ListenableFuture<ExecutionResult<OutputT>> onFinishAsync(
+ ArgumentT argument) {
+ return mActionExecutor.execute(argument);
+ }
+ });
}
TaskCapabilityImpl<PropertyT, ArgumentT, OutputT, ConfirmationT, TaskUpdaterT>
taskCapability =
- new TaskCapabilityImpl<>(
- Objects.requireNonNull(mId, "id field must not be null."),
- mActionSpec,
- mProperty,
- mTaskHandler.getParamsRegistry(),
- mTaskHandler.getOnInitListener(),
- mTaskHandler.getOnReadyToConfirmListener(),
- mTaskHandler.getOnFinishListener(),
- mTaskHandler.getConfirmationDataBindings(),
- mTaskHandler.getExecutionOutputBindings(),
- Runnable::run);
+ new TaskCapabilityImpl<>(
+ Objects.requireNonNull(mId, "id field must not be null."),
+ mActionSpec,
+ mProperty,
+ mTaskHandler.getParamsRegistry(),
+ mTaskHandler.getOnInitListener(),
+ mTaskHandler.getOnReadyToConfirmListener(),
+ mTaskHandler.getOnFinishListener(),
+ mTaskHandler.getConfirmationDataBindings(),
+ mTaskHandler.getExecutionOutputBindings(),
+ Runnable::run);
taskCapability.setTaskUpdaterSupplier(mTaskHandler.getTaskUpdaterSupplier());
return taskCapability;
}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.kt
similarity index 64%
rename from appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.java
rename to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.kt
index 6e1f4c3..2325c2a 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ActionCapability.kt
@@ -14,16 +14,14 @@
* limitations under the License.
*/
-package androidx.appactions.interaction.capabilities.core;
+package androidx.appactions.interaction.capabilities.core
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper;
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
-import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback;
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction;
-
-import java.util.Optional;
+import androidx.annotation.RestrictTo
+import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession
+import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
+import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
+import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
+import androidx.appactions.interaction.proto.AppActionsContext.AppAction
/**
* <b>Do not implement this interface yourself.</b>
@@ -32,11 +30,15 @@
*
* <p>Use helper classes provided by the capability library to get instances of this interface.
*/
-public interface ActionCapability {
+interface ActionCapability {
/** Returns the unique Id of this capability declaration. */
- @NonNull
- Optional<String> getId();
+ val id: String?
+
+ /**
+ * Returns whether or not this capability supports multi-turn task.
+ */
+ val supportsMultiTurnTask: Boolean
/**
* Returns an app action proto describing how to fulfill this capability.
@@ -44,18 +46,23 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @NonNull
- AppAction getAppAction();
+ fun getAppAction(): AppAction
/**
* Executes the action and returns the result of execution.
*
* @param argumentsWrapper The arguments send from assistant to the activity.
* @param callback The callback to receive app action result.
+ *
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- void execute(@NonNull ArgumentsWrapper argumentsWrapper, @NonNull CallbackInternal callback);
+ fun execute(
+ argumentsWrapper: ArgumentsWrapper,
+ callback: CallbackInternal,
+ ) {
+ throw UnsupportedOperationException()
+ }
/**
* Support for manual input. This method should be invoked by AppInteraction SDKs
@@ -65,5 +72,16 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- default void setTouchEventCallback(@NonNull TouchEventCallback callback) {}
+ fun setTouchEventCallback(callback: TouchEventCallback) {}
+
+ /**
+ * Create a new capability session. The capability library doesn't maintain registry of
+ * capabilities, so it's not going to assign any session id.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ fun createSession(hostProperties: HostProperties): ActionCapabilitySession {
+ throw UnsupportedOperationException()
+ }
}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseSession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseSession.kt
new file mode 100644
index 0000000..e4b20fe
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseSession.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core
+
+import com.google.common.util.concurrent.ListenableFuture
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.guava.future
+/**
+ * Base interface for Session of all verticals.
+ */
+interface BaseSession<ArgumentT, OutputT> {
+ /**
+ * Implement any initialization logic.
+ *
+ * This method is called once, before any other listeners are invoked.
+ */
+ fun onInit(initArg: InitArg) {}
+
+ /**
+ * Called when all arguments are finalized.
+ * @param argument the Argument instance containing data for fulfillment.
+ * @return an ExecutionResult instance.
+ */
+ suspend fun onFinish(argument: ArgumentT): ExecutionResult<OutputT> {
+ throw NotImplementedError()
+ }
+
+ /**
+ * Called when all arguments are finalized.
+ * @param argument the Argument instance containing data for fulfillment.
+ * @return a ListenableFuture containing an ExecutionResult instance.
+ */
+ @kotlin.OptIn(DelicateCoroutinesApi::class)
+ fun onFinishAsync(argument: ArgumentT): ListenableFuture<ExecutionResult<OutputT>> {
+ return GlobalScope.future { onFinish(argument) }
+ }
+
+ /**
+ * Implement any cleanup logic.
+ * This method is called some time after the session finishes.
+ */
+ fun onDestroy() {}
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
new file mode 100644
index 0000000..c0ceb39
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core
+
+import android.util.SizeF
+import java.util.Objects
+
+/**
+ * HostProperties contains information about the host that can be used to customize behaviour for
+ * different environments.
+ */
+class HostProperties internal constructor(val maxHostSizeDp: SizeF) {
+ override fun toString() =
+ "HostProperties(maxHostSizeDp=$maxHostSizeDp)"
+
+ override fun equals(other: Any?): Boolean {
+ return other is HostProperties && maxHostSizeDp == other.maxHostSizeDp
+ }
+
+ override fun hashCode() = Objects.hash(maxHostSizeDp)
+
+ /**
+ * Builder class for HostProperties.
+ */
+ class Builder {
+ private var maxHostSizeDp: SizeF? = null
+
+ /** Sets the dimensions of the host area where the app content will be displayed in dp. */
+ fun setMaxHostSizeDp(maxHostSizeDp: SizeF) = apply {
+ this.maxHostSizeDp = maxHostSizeDp
+ }
+
+ /**
+ * Builds and returns the HostProperties instance.
+ */
+ fun build() = HostProperties(
+ requireNotNull(maxHostSizeDp, { "maxHostSizeDp must be set." }),
+ )
+ }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InitArg.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InitArg.kt
new file mode 100644
index 0000000..f01729c
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InitArg.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core
+
+/**
+ * InitArg contains data passed to {@code BaseSession#onInit}.
+ */
+class InitArg internal constructor() {
+ override fun toString() =
+ "InitArg()"
+
+ override fun equals(other: Any?): Boolean {
+ return other is InitArg
+ }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionBuilder.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionBuilder.kt
new file mode 100644
index 0000000..7aa2a29
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionBuilder.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core
+
+/**
+ * Interface to be implemented for creating SessionT instances.
+ */
+fun interface SessionBuilder<SessionT> {
+ /**
+ * @return A new SessionT instance for handling a task.
+ */
+ fun createSession(
+ hostProperties: HostProperties,
+ ): SessionT
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ActionCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ActionCapabilitySession.kt
new file mode 100644
index 0000000..0a9fb0e
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ActionCapabilitySession.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.impl
+
+import androidx.annotation.RestrictTo
+
+/**
+ * Internal interface for a session, contains developer's Session instance
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface ActionCapabilitySession {
+ /**
+ * Executes the action and returns the result of execution.
+ *
+ * @param argumentsWrapper The arguments send from assistant to the activity.
+ * @param callback The callback to receive app action result.
+ */
+ fun execute(
+ argumentsWrapper: ArgumentsWrapper,
+ callback: CallbackInternal,
+ )
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
new file mode 100644
index 0000000..76ed7b5
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.impl
+
+import androidx.annotation.NonNull
+import androidx.appactions.interaction.capabilities.core.ActionCapability
+import androidx.appactions.interaction.capabilities.core.BaseSession
+import androidx.appactions.interaction.capabilities.core.HostProperties
+import androidx.appactions.interaction.capabilities.core.SessionBuilder
+import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
+import androidx.appactions.interaction.proto.AppActionsContext.AppAction
+import androidx.appactions.interaction.proto.TaskInfo
+
+import androidx.annotation.RestrictTo
+
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+internal class SingleTurnCapabilityImpl<
+ PropertyT,
+ ArgumentT,
+ OutputT,
+ > constructor(
+ override val id: String?,
+ val actionSpec: ActionSpec<PropertyT, ArgumentT, OutputT>,
+ val property: PropertyT,
+ val sessionBuilder: SessionBuilder<BaseSession<ArgumentT, OutputT>>,
+) : ActionCapability {
+ override val supportsMultiTurnTask = false
+
+ @NonNull
+ override fun getAppAction(): AppAction {
+ val appActionBuilder = actionSpec.convertPropertyToProto(property).toBuilder()
+ .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
+ id?.let(appActionBuilder::setIdentifier)
+ return appActionBuilder.build()
+ }
+
+ @NonNull
+ override fun createSession(hostProperties: HostProperties): ActionCapabilitySession {
+ return SingleTurnCapabilitySession(
+ actionSpec,
+ sessionBuilder.createSession(hostProperties),
+ )
+ }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
new file mode 100644
index 0000000..1b8bcf5
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
@@ -0,0 +1,90 @@
+
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.impl
+
+import androidx.annotation.NonNull
+import androidx.appactions.interaction.capabilities.core.ExecutionResult
+import androidx.appactions.interaction.capabilities.core.BaseSession
+import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback
+import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
+import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
+import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
+import androidx.appactions.interaction.proto.FulfillmentResponse
+import androidx.appactions.interaction.proto.ParamValue
+
+import androidx.annotation.RestrictTo
+
+/**
+ * ActionCapabilitySession implementation for executing single-turn fulfillment requests.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+internal class SingleTurnCapabilitySession<
+ ArgumentT,
+ OutputT,
+>(
+ val actionSpec: ActionSpec<*, ArgumentT, OutputT>,
+ val externalSession: BaseSession<ArgumentT, OutputT>,
+) : ActionCapabilitySession {
+ override fun execute(
+ @NonNull argumentsWrapper: ArgumentsWrapper,
+ @NonNull callback: CallbackInternal,
+ ) {
+ val paramValuesMap: Map<String, List<ParamValue>> = argumentsWrapper.paramValues().entries
+ .associate {
+ entry: Map.Entry<String, List<FulfillmentValue>> ->
+ Pair(
+ entry.key,
+ entry.value.mapNotNull {
+ fulfillmentValue: FulfillmentValue ->
+ fulfillmentValue.getValue()
+ },
+ )
+ }
+ val argument = actionSpec.buildArgument(paramValuesMap)
+ Futures.addCallback(
+ externalSession.onFinishAsync(argument),
+ object : FutureCallback<ExecutionResult<OutputT>> {
+ override fun onSuccess(executionResult: ExecutionResult<OutputT>) {
+ callback.onSuccess(convertToFulfillmentResponse(executionResult))
+ }
+
+ override fun onFailure(t: Throwable) {
+ callback.onError(ErrorStatusInternal.CANCELLED)
+ }
+ },
+ Runnable::run,
+ )
+ }
+
+ /** Converts typed {@link ExecutionResult} to {@link FulfillmentResponse} proto. */
+ private fun convertToFulfillmentResponse(
+ executionResult: ExecutionResult<OutputT>,
+ ): FulfillmentResponse {
+ val fulfillmentResponseBuilder =
+ FulfillmentResponse.newBuilder()
+ .setStartDictation(executionResult.startDictation)
+ executionResult.output?.let { it ->
+ fulfillmentResponseBuilder.setExecutionOutput(
+ actionSpec.convertOutputToProto(it),
+ )
+ }
+ return fulfillmentResponseBuilder.build()
+ }
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/PropertyConverter.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/PropertyConverter.java
index f665360..d1354c0 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/PropertyConverter.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/PropertyConverter.java
@@ -36,8 +36,7 @@
/** Contains utility functions that convert properties to IntentParameter proto. */
public final class PropertyConverter {
- private PropertyConverter() {
- }
+ private PropertyConverter() {}
/** Create IntentParameter proto from a StringProperty. */
@NonNull
@@ -112,16 +111,18 @@
@NonNull
public static Entity entityToProto(
@NonNull androidx.appactions.interaction.capabilities.core.properties.Entity entity) {
- Entity.Builder builder = Entity.newBuilder().addAllAlternateNames(
- entity.getAlternateNames());
- entity.getName().ifPresent(builder::setName);
- entity.getId().ifPresent(builder::setIdentifier);
+ Entity.Builder builder =
+ Entity.newBuilder()
+ .setName(entity.getName())
+ .addAllAlternateNames(entity.getAlternateNames());
+ if (entity.getId() != null) {
+ builder.setIdentifier(entity.getId());
+ }
return builder.build();
}
/**
- * Converts a capabilities library StringProperty.PossibleValue to a appactions Entity proto
- * .
+ * Converts a capabilities library StringProperty.PossibleValue to a appactions Entity proto .
*/
@NonNull
public static Entity possibleValueToProto(@NonNull PossibleValue possibleValue) {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImpl.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImpl.java
deleted file mode 100644
index a6bfaad..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImpl.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2023 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.appactions.interaction.capabilities.core.impl.spec;
-
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableList;
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableMap;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.ActionCapability;
-import androidx.appactions.interaction.capabilities.core.ActionExecutor;
-import androidx.appactions.interaction.capabilities.core.ExecutionResult;
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper;
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger;
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal;
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * The implementation of the {@link ActionCapability} interface.
- *
- * @param <PropertyT>
- * @param <ArgumentT>
- * @param <OutputT>
- */
-public final class ActionCapabilityImpl<PropertyT, ArgumentT, OutputT> implements ActionCapability {
-
- private static final String LOG_TAG = "ActionCapability";
- private final ActionSpec<PropertyT, ArgumentT, OutputT> mActionSpec;
- private final Optional<String> mIdentifier;
- private final PropertyT mProperty;
- private final ActionExecutor<ArgumentT, OutputT> mActionExecutor;
-
- public ActionCapabilityImpl(
- @NonNull ActionSpec<PropertyT, ArgumentT, OutputT> actionSpec,
- @NonNull Optional<String> identifier,
- @NonNull PropertyT property,
- @NonNull ActionExecutor<ArgumentT, OutputT> actionExecutor) {
- this.mActionSpec = actionSpec;
- this.mIdentifier = identifier;
- this.mProperty = property;
- this.mActionExecutor = actionExecutor;
- }
-
- @NonNull
- @Override
- public Optional<String> getId() {
- return mIdentifier;
- }
-
- @NonNull
- @Override
- public AppAction getAppAction() {
- AppAction appAction = mActionSpec.convertPropertyToProto(mProperty);
- if (mIdentifier.isPresent()) {
- appAction = appAction.toBuilder().setIdentifier(mIdentifier.get()).build();
- }
- return appAction;
- }
-
- @Override
- public void execute(
- @NonNull ArgumentsWrapper argumentsWrapper, @NonNull CallbackInternal callback) {
- // Filter out the task parts of ArgumentsWrapper. Send the raw arguments for one-shot
- // capabilities.
- Map<String, List<ParamValue>> args =
- argumentsWrapper.paramValues().entrySet().stream()
- .collect(
- toImmutableMap(
- Map.Entry::getKey,
- e ->
- e.getValue().stream()
- .filter(FulfillmentValue::hasValue)
- .map(FulfillmentValue::getValue)
- .collect(toImmutableList())));
- try {
- Futures.addCallback(
- mActionExecutor.execute(mActionSpec.buildArgument(args)),
- new FutureCallback<ExecutionResult<OutputT>>() {
- @Override
- public void onSuccess(ExecutionResult<OutputT> executionResult) {
- callback.onSuccess(convertToFulfillmentResponse(executionResult));
- }
-
- @Override
- public void onFailure(Throwable t) {
- callback.onError(ErrorStatusInternal.CANCELLED);
- }
- },
- Runnable::run);
- } catch (StructConversionException e) {
- if (e.getMessage() != null) {
- LoggerInternal.log(CapabilityLogger.LogLevel.ERROR, LOG_TAG, e.getMessage());
- }
- callback.onError(ErrorStatusInternal.STRUCT_CONVERSION_FAILURE);
- }
- }
-
- /** Converts typed {@link ExecutionResult} to {@link FulfillmentResponse} proto. */
- FulfillmentResponse convertToFulfillmentResponse(ExecutionResult<OutputT> executionResult) {
- FulfillmentResponse.Builder fulfillmentResponseBuilder =
- FulfillmentResponse.newBuilder()
- .setStartDictation(executionResult.getStartDictation());
- OutputT output = executionResult.getOutput();
- if (output != null && !(output instanceof Void)) {
- fulfillmentResponseBuilder.setExecutionOutput(mActionSpec.convertOutputToProto(output));
- }
- return fulfillmentResponseBuilder.build();
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.java
index de3aa6a..1c427d1 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.java
@@ -33,7 +33,7 @@
/** The implementation of {@code ActionSpec} interface. */
final class ActionSpecImpl<
- PropertyT, ArgumentT, ArgumentBuilderT extends BuilderOf<ArgumentT>, OutputT>
+ PropertyT, ArgumentT, ArgumentBuilderT extends BuilderOf<ArgumentT>, OutputT>
implements ActionSpec<PropertyT, ArgumentT, OutputT> {
private final String mCapabilityName;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.java
deleted file mode 100644
index a40eae1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2023 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.appactions.interaction.capabilities.core.properties;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Entities are used when defining ActionCapability for defining possible values for ParamProperty.
- */
-public final class Entity {
- private final Optional<String> mId;
- private final Optional<String> mName;
- private final List<String> mAlternateNames;
-
- private Entity(Builder builder) {
- this.mId = builder.mId;
- this.mName = builder.mName;
- this.mAlternateNames = builder.mAlternateNames;
- }
-
- /** Returns a new Builder to build an Entity instance. */
- @NonNull
- public static Builder newBuilder() {
- return new Builder();
- }
-
- /** The id of this Entity. */
- @NonNull
- public Optional<String> getId() {
- return mId;
- }
-
- /** The name of this entity. The name is what a user may say to refer to this Entity. */
- @NonNull
- public Optional<String> getName() {
- return mName;
- }
-
- /**
- * The alternate names of this entity. These are alternate names a user may say to refer to
- * this
- * Entity.
- */
- @NonNull
- public List<String> getAlternateNames() {
- if (mAlternateNames == null) {
- return Collections.emptyList();
- }
- return mAlternateNames;
- }
-
- /** Builder class for Entity. */
- public static class Builder {
- private Optional<String> mId = Optional.empty();
- private Optional<String> mName = Optional.empty();
- private @Nullable List<String> mAlternateNames = null;
-
- /** Sets the id of the Entity to be built. */
- @NonNull
- public Builder setId(@NonNull String id) {
- this.mId = Optional.of(id);
- return this;
- }
-
- /** Sets the name of the Entity to be built. */
- @NonNull
- public Builder setName(@NonNull String name) {
- this.mName = Optional.of(name);
- return this;
- }
-
- /** Sets the list of alternate names of the Entity to be built. */
- @NonNull
- public Builder setAlternateNames(@NonNull List<String> alternateNames) {
- this.mAlternateNames = alternateNames;
- return this;
- }
-
- /** Sets the list of alternate names of the Entity to be built. */
- @NonNull
- public final Builder setAlternateNames(@NonNull String... alternateNames) {
- return setAlternateNames(Collections.unmodifiableList(Arrays.asList(alternateNames)));
- }
-
- /** Builds and returns an Entity. */
- @NonNull
- public Entity build() {
- return new Entity(this);
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.kt
new file mode 100644
index 0000000..08946cb
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Entity.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.properties
+
+/**
+ * Entities are used when defining ActionCapability for defining possible values for ParamProperty.
+ */
+class Entity internal constructor(
+ val id: String?,
+ val name: String,
+ val alternateNames: List<String>,
+) {
+ /** Builder class for Entity. */
+ class Builder {
+ private var id: String? = null
+ private var name: String? = null
+ private var alternateNames: List<String> = listOf()
+
+ /** Sets the id of the Entity to be built. */
+ fun setId(id: String) = apply {
+ this.id = id
+ }
+
+ /** Sets the name of the Entity to be built. */
+ fun setName(name: String) = apply {
+ this.name = name
+ }
+
+ /** Sets the list of alternate names of the Entity to be built. */
+
+ fun setAlternateNames(alternateNames: List<String>) = apply {
+ this.alternateNames = alternateNames
+ }
+
+ /** Sets the list of alternate names of the Entity to be built. */
+
+ fun setAlternateNames(vararg alternateNames: String) = setAlternateNames(
+ alternateNames.asList(),
+ )
+
+ /** Builds and returns an Entity. */
+ fun build() = Entity(
+ id,
+ requireNotNull(name, {
+ "setName must be called before build"
+ }),
+ alternateNames,
+ )
+ }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImpl.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImpl.java
index 2655700..c3e46f2 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImpl.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityImpl.java
@@ -19,6 +19,7 @@
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
import androidx.appactions.interaction.capabilities.core.ActionCapability;
import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper;
import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
@@ -47,7 +48,9 @@
* @param <OutputT>
* @param <ConfirmationT>
* @param <TaskUpdaterT>
+ * @hide
*/
+@RestrictTo(RestrictTo.Scope.LIBRARY)
public final class TaskCapabilityImpl<
PropertyT,
ArgumentT,
@@ -104,8 +107,13 @@
@NonNull
@Override
- public Optional<String> getId() {
- return Optional.of(mIdentifier);
+ public String getId() {
+ return mIdentifier;
+ }
+
+ @Override
+ public boolean getSupportsMultiTurnTask() {
+ return true;
}
public void setTaskUpdaterSupplier(@NonNull Supplier<TaskUpdaterT> taskUpdaterSupplier) {
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
new file mode 100644
index 0000000..2082eb6
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.impl
+
+import android.util.SizeF
+import androidx.appactions.interaction.capabilities.core.ActionCapability
+import androidx.appactions.interaction.capabilities.core.ExecutionResult
+import androidx.appactions.interaction.capabilities.core.HostProperties
+import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
+import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
+import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
+import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
+import androidx.appactions.interaction.capabilities.core.properties.EntityProperty
+import androidx.appactions.interaction.capabilities.core.properties.StringProperty
+import androidx.appactions.interaction.capabilities.core.testing.ArgumentUtils
+import androidx.appactions.interaction.capabilities.core.testing.spec.Argument
+import androidx.appactions.interaction.capabilities.core.testing.spec.Output
+import androidx.appactions.interaction.capabilities.core.testing.spec.Property
+import androidx.appactions.interaction.capabilities.core.testing.spec.Session
+import androidx.appactions.interaction.proto.FulfillmentResponse
+import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
+import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
+import androidx.appactions.interaction.proto.ParamValue
+import com.google.common.util.concurrent.ListenableFuture
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.mock
+
+@RunWith(JUnit4::class)
+class SingleTurnCapabilityTest {
+
+ val mockCalback: CallbackInternal = mock()
+
+ @Test
+ fun oneShotCapability_successWithOutput() {
+ val capability: ActionCapability =
+ SingleTurnCapabilityImpl<Property, Argument, Output>(
+ "capabilityId",
+ ACTION_SPEC,
+ Property.newBuilder().setRequiredEntityField(
+ EntityProperty.EMPTY,
+ ).setOptionalStringField(
+ StringProperty.PROHIBITED,
+ ).build(),
+ {
+ object : Session {
+ override fun onFinishAsync(
+ argument: Argument,
+ ): ListenableFuture<ExecutionResult<Output>> {
+ return Futures.immediateFuture(
+ ExecutionResult.Builder<Output>().setOutput(
+ Output.builder().setOptionalStringField("stringOutput")
+ .build(),
+ ).build(),
+ )
+ }
+ }
+ },
+ )
+ val expectedFulfillmentResponse: FulfillmentResponse =
+ FulfillmentResponse.newBuilder().setExecutionOutput(
+ StructuredOutput.newBuilder()
+ .addOutputValues(
+ OutputValue.newBuilder()
+ .setName("optionalStringOutput")
+ .addValues(
+ ParamValue.newBuilder()
+ .setStringValue("stringOutput")
+ .build(),
+ )
+ .build(),
+ )
+ .build(),
+ ).build()
+
+ val capabilitySession = capability.createSession(
+ HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build(),
+ )
+ capabilitySession.execute(
+ ArgumentUtils.buildArgs(
+ mapOf(
+ "optionalString" to ParamValue.newBuilder().setIdentifier(
+ "string argument value",
+ ).build(),
+ ),
+ ),
+ mockCalback,
+ )
+
+ verify(mockCalback).onSuccess(expectedFulfillmentResponse)
+ }
+
+ companion object {
+ val ACTION_SPEC: ActionSpec<Property, Argument, Output> =
+ ActionSpecBuilder.ofCapabilityNamed(
+ "actions.intent.TEST",
+ )
+ .setDescriptor(Property::class.java)
+ .setArgument(Argument::class.java, Argument::newBuilder)
+ .setOutput(Output::class.java)
+ .bindOptionalStringParameter(
+ "optionalString",
+ Property::optionalStringField,
+ Argument.Builder::setOptionalStringField,
+ )
+ .bindOptionalOutput(
+ "optionalStringOutput",
+ Output::optionalStringField,
+ TypeConverters::toParamValue,
+ ).build()
+ }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImplTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImplTest.java
deleted file mode 100644
index f057569..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionCapabilityImplTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2023 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.appactions.interaction.capabilities.core.impl.spec;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.verify;
-
-import androidx.appactions.interaction.capabilities.core.ExecutionResult;
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper;
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures;
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters;
-import androidx.appactions.interaction.capabilities.core.properties.EntityProperty;
-import androidx.appactions.interaction.capabilities.core.testing.spec.Argument;
-import androidx.appactions.interaction.capabilities.core.testing.spec.Output;
-import androidx.appactions.interaction.capabilities.core.testing.spec.Property;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.List;
-import java.util.Optional;
-
-@RunWith(JUnit4.class)
-public final class ActionCapabilityImplTest {
-
- private static final ActionSpec<Property, Argument, Output> ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed("actions.intent.TEST")
- .setDescriptor(Property.class)
- .setArgument(Argument.class, Argument::newBuilder)
- .setOutput(Output.class)
- .bindRequiredEntityParameter(
- "requiredEntity",
- Property::requiredEntityField,
- Argument.Builder::setRequiredEntityField)
- .bindOptionalOutput(
- "optionalStringOutput",
- Output::optionalStringField,
- TypeConverters::toParamValue)
- .bindRepeatedOutput(
- "repeatedStringOutput",
- Output::repeatedStringField,
- TypeConverters::toParamValue)
- .build();
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
- @Captor ArgumentCaptor<FulfillmentResponse> mCaptor;
- @Mock private CallbackInternal mCallbackInternal;
-
- @Test
- @SuppressWarnings("JdkImmutableCollections")
- public void execute_convertExecutionResult() {
- Property property =
- Property.newBuilder()
- .setRequiredEntityField(EntityProperty.newBuilder().build())
- .build();
-
- ExecutionResult<Output> executionResult =
- new ExecutionResult.Builder<Output>()
- .setOutput(
- Output.builder()
- .setOptionalStringField("test2")
- .setRepeatedStringField(List.of("test3", "test4"))
- .build())
- .build();
- ActionCapabilityImpl<Property, Argument, Output> capability =
- new ActionCapabilityImpl<>(
- ACTION_SPEC,
- Optional.of("id"),
- property,
- (argument) -> Futures.immediateFuture(executionResult));
- StructuredOutput expectedExecutionOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test2")
- .build())
- .build())
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test3")
- .build())
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test4")
- .build())
- .build())
- .build();
-
- capability.execute(
- ArgumentsWrapper.create(Fulfillment.getDefaultInstance()), mCallbackInternal);
-
- verify(mCallbackInternal).onSuccess(mCaptor.capture());
- assertThat(mCaptor.getValue().getExecutionOutput().getOutputValuesList())
- .containsExactlyElementsIn(expectedExecutionOutput.getOutputValuesList());
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java
index 341351f..05a49f5 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java
@@ -19,15 +19,12 @@
import static com.google.common.truth.Truth.assertThat;
import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.ActionCapability;
-import androidx.appactions.interaction.capabilities.core.ActionExecutor;
import androidx.appactions.interaction.capabilities.core.impl.BuilderOf;
import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters;
import androidx.appactions.interaction.capabilities.core.properties.Entity;
import androidx.appactions.interaction.capabilities.core.properties.EntityProperty;
import androidx.appactions.interaction.capabilities.core.properties.EnumProperty;
import androidx.appactions.interaction.capabilities.core.properties.StringProperty;
-import androidx.appactions.interaction.capabilities.core.testing.TestingUtils;
import androidx.appactions.interaction.capabilities.core.testing.spec.Output;
import androidx.appactions.interaction.capabilities.core.values.EntityValue;
import androidx.appactions.interaction.proto.AppActionsContext.AppAction;
@@ -92,18 +89,13 @@
TypeConverters::toParamValue)
.build();
- private static ActionCapability createCapability(
- String id, Property property, ActionExecutor<Argument, Output> executor) {
- return new ActionCapabilityImpl<>(ACTION_SPEC, Optional.of(id), property, executor);
- }
-
@Test
public void getAppAction_onlyRequiredProperty() {
Property property =
Property.create(
EntityProperty.newBuilder()
.addPossibleEntity(
- Entity.newBuilder()
+ new Entity.Builder()
.setId("contact_2")
.setName("Donald")
.setAlternateNames("Duck")
@@ -112,13 +104,9 @@
.build(),
StringProperty.EMPTY);
- ActionCapability capability =
- createCapability("id", property, TestingUtils.createFakeActionExecutor());
-
- assertThat(capability.getAppAction())
+ assertThat(ACTION_SPEC.convertPropertyToProto(property))
.isEqualTo(
AppAction.newBuilder()
- .setIdentifier("id")
.setName("actions.intent.TEST")
.addParams(
IntentParameter.newBuilder()
@@ -142,7 +130,7 @@
Property.create(
EntityProperty.newBuilder()
.addPossibleEntity(
- Entity.newBuilder()
+ new Entity.Builder()
.setId("contact_2")
.setName("Donald")
.setAlternateNames("Duck")
@@ -151,7 +139,7 @@
Optional.of(
EntityProperty.newBuilder()
.addPossibleEntity(
- Entity.newBuilder()
+ new Entity.Builder()
.setId("entity1")
.setName("optional possible entity")
.build())
@@ -165,12 +153,12 @@
Optional.of(
EntityProperty.newBuilder()
.addPossibleEntity(
- Entity.newBuilder()
+ new Entity.Builder()
.setId("entity1")
.setName("repeated entity1")
.build())
.addPossibleEntity(
- Entity.newBuilder()
+ new Entity.Builder()
.setId("entity2")
.setName("repeated entity2")
.build())
@@ -185,13 +173,9 @@
.build()),
Optional.of(StringProperty.PROHIBITED));
- ActionCapability capability =
- createCapability("id", property, TestingUtils.createFakeActionExecutor());
-
- assertThat(capability.getAppAction())
+ assertThat(ACTION_SPEC.convertPropertyToProto(property))
.isEqualTo(
AppAction.newBuilder()
- .setIdentifier("id")
.setName("actions.intent.TEST")
.addParams(
IntentParameter.newBuilder()
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.java
index c18a61a..5464ff6 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.java
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.java
@@ -18,6 +18,7 @@
import com.google.auto.value.AutoValue;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -26,12 +27,11 @@
public abstract class Output {
public static Builder builder() {
- return new AutoValue_Output.Builder();
+ return new AutoValue_Output.Builder().setRepeatedStringField(Collections.emptyList());
}
public abstract Optional<String> optionalStringField();
- @SuppressWarnings("AutoValueImmutableFields")
public abstract List<String> repeatedStringField();
@AutoValue.Builder
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Session.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Session.kt
new file mode 100644
index 0000000..60de640
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Session.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 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.appactions.interaction.capabilities.core.testing.spec
+
+import androidx.appactions.interaction.capabilities.core.BaseSession
+
+interface Session : BaseSession<Argument, Output>
\ No newline at end of file
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.java b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.java
index 47cca71..41df1b9 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.java
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.java
@@ -23,6 +23,7 @@
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appactions.interaction.capabilities.core.ActionCapability;
import androidx.appactions.interaction.service.proto.AppActionsServiceGrpc;
@@ -135,7 +136,7 @@
@Override
@NonNull
- public IBinder onBind(Intent intent) {
+ public IBinder onBind(@Nullable Intent intent) {
return mBinderSupplier.get();
}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt
index 56ca2a4..90af3ce 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt
@@ -47,7 +47,11 @@
/** Set the packageName that will be part of the [AppVerificationInfo] */
fun addSignature(signatures: List<ByteArray>) = apply { this.signatures = signatures }
- /** Creates a new instance of [AppVerificationInfo] */
+ /**
+ * Creates a new instance of [AppVerificationInfo]
+ *
+ * @Throws IllegalArgumentException if packageName is null or signatures are empty.
+ */
fun build(): AppVerificationInfo {
if (packageName == null) {
throw IllegalArgumentException("App verification info packageName is missing.")
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
index 37a4387..c118e72 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
@@ -16,6 +16,7 @@
package androidx.appactions.interaction.service
+import android.annotation.SuppressLint
import android.util.SizeF
import android.widget.RemoteViews
import android.widget.RemoteViewsService.RemoteViewsFactory
@@ -54,6 +55,7 @@
* @param layout the wear-tile [LayoutElementBuilders.Layout] to be displayed.
* @param resources the resources associated with the layout.
*/
+ @SuppressLint("MissingGetterMatchingBuilder")
fun setTileLayout(
layout: LayoutElementBuilders.Layout,
resources: ResourceBuilders.Resources
@@ -80,6 +82,7 @@
* @param remoteViews the `RemoteViews` to be displayed
* @param size the size, in dp, of the RemoteViews being displayed
*/
+ @SuppressLint("MissingGetterMatchingBuilder")
fun setRemoteViews(remoteViews: RemoteViews, size: SizeF?): RemoteViewsUiBuilder {
this.remoteViews = remoteViews
this.size = size
@@ -92,6 +95,7 @@
* Any errors resulting from the provided view IDs will contain "RemoteViewsCollection
* error: " errors with some message from the host.
*/
+ @SuppressLint("MissingGetterMatchingBuilder")
fun addViewIdForCollectionUpdate(@IdRes viewId: Int): RemoteViewsUiBuilder {
changedViewIds.add(viewId)
return this
@@ -105,6 +109,7 @@
* @param viewId the id of the collection view
* @param factory a RemoteViewsFactory associated with the collection view
*/
+ @SuppressLint("MissingGetterMatchingBuilder")
fun addRemoteViewsFactory(
@IdRes viewId: Int,
factory: RemoteViewsFactory
diff --git a/appcompat/appcompat-lint/integration-tests/OWNERS b/appcompat/appcompat-lint/integration-tests/OWNERS
index 7928c5c..97d8080 100644
--- a/appcompat/appcompat-lint/integration-tests/OWNERS
+++ b/appcompat/appcompat-lint/integration-tests/OWNERS
@@ -1,2 +1,2 @@
-# Bug components: 461199
+# Bug component: 461199
[email protected]
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
index 65f052b..ffb51ab 100644
--- a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
@@ -32,7 +32,7 @@
@Suppress("UnstableApiUsage")
class AppCompatIssueRegistry : IssueRegistry() {
override val minApi = 10 // Only compatible with the latest lint
- override val api = 14
+ override val api = 13
override val issues get() = listOf(
SetActionBarDetector.USING_CORE_ACTION_BAR,
ColorStateListAlphaDetector.NOT_USING_ANDROID_ALPHA,
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/SearchSpec.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/SearchSpec.java
index cdb54ca..9f951fd 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/SearchSpec.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/SearchSpec.java
@@ -452,9 +452,6 @@
/**
* Returns whether the {@link Features#NUMERIC_SEARCH} feature is enabled.
- *
- * TODO(b/259744228): add more documentation about the numeric search feature and when it
- * needs to be enabled.
*/
public boolean isNumericSearchEnabled() {
return getEnabledFeatures().contains(Features.NUMERIC_SEARCH);
@@ -462,9 +459,6 @@
/**
* Returns whether the {@link Features#VERBATIM_SEARCH} feature is enabled.
- *
- * TODO(b/204333391): add more documentation about the verbatim search feature and when it
- * needs to be enabled.
*/
public boolean isVerbatimSearchEnabled() {
return getEnabledFeatures().contains(Features.VERBATIM_SEARCH);
@@ -472,9 +466,6 @@
/**
* Returns whether the {@link Features#LIST_FILTER_QUERY_LANGUAGE} feature is enabled.
- *
- * TODO(b/208654892): add more documentation about the list filter query language feature and
- * when it needs to be enabled.
*/
public boolean isListFilterQueryLanguageEnabled() {
return getEnabledFeatures().contains(Features.LIST_FILTER_QUERY_LANGUAGE);
@@ -1283,8 +1274,9 @@
*
* @param enabled Enables the feature if true, otherwise disables it.
*
- * TODO(b/259744228): add more documentation about the numeric search feature and when it
- * needs to be enabled.
+ * <p>If disabled, disallows use of
+ * {@link AppSearchSchema.LongPropertyConfig#INDEXING_TYPE_RANGE} and all other numeric
+ * querying features.
*/
// @exportToFramework:startStrip()
@RequiresFeature(
@@ -1303,8 +1295,13 @@
*
* @param enabled Enables the feature if true, otherwise disables it
*
- * TODO(b/204333391): add more documentation about the verbatim search feature and when
- * it needs to be enabled.
+ * <p>If disabled, disallows use of
+ * {@link AppSearchSchema.StringPropertyConfig#TOKENIZER_TYPE_VERBATIM} and all other
+ * verbatim search features within the query language that allows clients to search
+ * using the verbatim string operator.
+ *
+ * <p>Ex. The verbatim string operator '"foo/bar" OR baz' will ensure that 'foo/bar' is
+ * treated as a single 'verbatim' token.
*/
// @exportToFramework:startStrip()
@RequiresFeature(
@@ -1323,8 +1320,28 @@
*
* @param enabled Enables the feature if true, otherwise disables it.
*
- * TODO(b/208654892): add more documentation about the list filter query language feature
- * and when it needs to be enabled.
+ * This feature covers the expansion of the query language to conform to the definition
+ * of the list filters language (https://aip.dev/160). This includes:
+ * <ul>
+ * <li>addition of explicit 'AND' and 'NOT' operators</li>
+ * <li>property restricts are allowed with grouping (ex. "prop:(a OR b)")</li>
+ * <li>addition of custom functions to control matching</li>
+ * </ul>
+ *
+ * <p>The newly added custom functions covered by this feature are:
+ * <ul>
+ * <li>createList(String...)</li>
+ * <li>termSearch(String, List<String>)</li>
+ * </ul>
+ *
+ * <p>createList takes a variable number of strings and returns a list of strings.
+ * It is for use with termSearch.
+ *
+ * <p>termSearch takes a query string that will be parsed according to the supported
+ * query language and an optional list of strings that specify the properties to be
+ * restricted to. This exists as a convenience for multiple property restricts. So,
+ * for example, the query "(subject:foo OR body:foo) (subject:bar OR body:bar)"
+ * could be rewritten as "termSearch(\"foo bar\", createList(\"subject\", \"bar\"))"
*/
// @exportToFramework:startStrip()
@RequiresFeature(
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
index 65ac589..c2348b5 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
@@ -47,7 +47,7 @@
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
-private const val tracingPerfettoVersion = "1.0.0-alpha10" // TODO(224510255): get by 'reflection'
+private const val tracingPerfettoVersion = "1.0.0-alpha11" // TODO(224510255): get by 'reflection'
private const val minSupportedSdk = Build.VERSION_CODES.R // TODO(234351579): Support API < 30
@RunWith(Parameterized::class)
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/metalava/UpdateApiTaskTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/metalava/UpdateApiTaskTest.kt
new file mode 100644
index 0000000..a502b62d
--- /dev/null
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/metalava/UpdateApiTaskTest.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2023 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.build.metalava
+
+import org.gradle.api.GradleException
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertThrows
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+class UpdateApiTaskTest {
+ @Rule
+ @JvmField
+ val tmpFolder = TemporaryFolder()
+
+ @Test
+ fun testCompareLineCount() {
+ val testCases = mapOf(
+ "No lines" to 0,
+ "Has one\nline" to 1,
+ "Has\ntwo\nlines" to 2,
+ "" to 0,
+ "\n" to 1,
+ "\n\n" to 2
+ )
+
+ for ((text, count) in testCases) {
+ assertEquals(compareLineCount(text, count), 0)
+ }
+ }
+
+ @Test
+ fun testCopyThrowsExceptionOnDiff() {
+ val source = tmpFolder.newFile().apply {
+ writeText("""
+// Signature format: 4.0
+ """.trimIndent())
+ }
+ val dest = tmpFolder.newFile().apply {
+ writeText("""
+// Signature format: 4.0
+package androidx.core.accessibilityservice {
+ public final class AccessibilityServiceInfoCompat {
+ method public static String capabilityToString(int);
+ }
+}
+ """.trimIndent())
+ }
+
+ assertThrows(GradleException::class.java) {
+ copy(source, dest, false)
+ }
+ }
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/VersionFileWriterTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/VersionFileWriterTask.kt
index a81686a..328350a 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/VersionFileWriterTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/VersionFileWriterTask.kt
@@ -48,7 +48,7 @@
val outputFile = File(outputDir.get().asFile, relativePath.get())
outputFile.parentFile.mkdirs()
val writer = PrintWriter(outputFile)
- writer.println(version)
+ writer.println(version.get())
writer.close()
}
}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
index f3a8727..d827a8d 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
@@ -81,7 +81,11 @@
}
}
-private fun summarizeDiff(a: File, b: File): String {
+/**
+ * Returns the output of running the `diff` command-line tool on files [a] and [b], truncated to
+ * [maxSummaryLines] lines.
+ */
+fun summarizeDiff(a: File, b: File, maxSummaryLines: Int = 50): String {
if (!a.exists()) {
return "$a does not exist"
}
@@ -93,7 +97,6 @@
.start()
process.waitFor(5, TimeUnit.SECONDS)
var diffLines = process.inputStream.bufferedReader().readLines().toMutableList()
- val maxSummaryLines = 50
if (diffLines.size > maxSummaryLines) {
diffLines = diffLines.subList(0, maxSummaryLines)
diffLines.plusAssign("[long diff was truncated]")
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
index 80a4c17..0286efc 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
@@ -150,7 +150,7 @@
source: File,
dest: File,
permitOverwriting: Boolean,
- logger: Logger
+ logger: Logger? = null
) {
val sourceText = if (source.exists()) {
source.readText()
@@ -161,11 +161,18 @@
val changing = overwriting || (dest.exists() != source.exists())
if (changing) {
if (overwriting && !permitOverwriting) {
+ val diff = summarizeDiff(source, dest, maxDiffLines + 1)
+ val diffMsg = if (compareLineCount(diff, maxDiffLines) > 0) {
+ "Diff is greater than $maxDiffLines lines, use diff tool to compare.\n\n"
+ } else {
+ "Diff:\n$diff\n\n"
+ }
val message = "Modifying the API definition for a previously released artifact " +
"having a final API version (version not ending in '-alpha') is not " +
"allowed.\n\n" +
"Previously declared definition is $dest\n" +
"Current generated definition is $source\n\n" +
+ diffMsg +
"Did you mean to increment the library version first?\n\n" +
"If you have a valid reason to override Semantic Versioning policy, see " +
"go/androidx/versioning#beta-api-change for information on obtaining approval."
@@ -174,10 +181,37 @@
if (source.exists()) {
@Suppress("UnstableApiUsage")
Files.copy(source, dest)
- logger.lifecycle("Copied $source to $dest")
+ logger?.lifecycle("Copied $source to $dest")
} else {
dest.delete()
- logger.lifecycle("Deleted $dest because $source does not exist")
+ logger?.lifecycle("Deleted $dest because $source does not exist")
}
}
}
+
+/**
+ * Returns -1 if [text] has fewer than [count] newline characters, 0 if equal, and 1 if greater
+ * than.
+ */
+fun compareLineCount(text: String, count: Int): Int {
+ var found = 0
+ var index = 0
+ while (found < count) {
+ index = text.indexOf('\n', index)
+ if (index < 0) {
+ break
+ }
+ found++
+ index++
+ }
+ return if (found < count) {
+ -1
+ } else if (found == count) {
+ 0
+ } else {
+ 1
+ }
+}
+
+/** Maximum number of diff lines to include in output. */
+internal const val maxDiffLines = 8
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/EncoderProfilesProviderAdapterDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/EncoderProfilesProviderAdapterDeviceTest.kt
index c61aa16..5d6c9c4 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/EncoderProfilesProviderAdapterDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/EncoderProfilesProviderAdapterDeviceTest.kt
@@ -21,6 +21,8 @@
import android.media.EncoderProfiles.VideoProfile.YUV_420
import android.os.Build
import androidx.camera.camera2.pipe.integration.adapter.EncoderProfilesProviderAdapter
+import androidx.camera.camera2.pipe.integration.compat.quirk.DeviceQuirks
+import androidx.camera.camera2.pipe.integration.compat.quirk.InvalidVideoProfilesQuirk
import androidx.camera.core.CameraSelector
import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy.BIT_DEPTH_8
import androidx.camera.testing.CameraUtil
@@ -68,7 +70,6 @@
@Before
fun setup() {
- skipTestOnProblematicBuildsOfCuttlefishApi33()
Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
cameraId = CameraUtil.getCameraIdWithLensFacing(CameraSelector.LENS_FACING_BACK)!!
@@ -156,6 +157,7 @@
@Test
fun afterApi33_hasSameContentAsEncoderProfiles() {
Assume.assumeTrue(CamcorderProfile.hasProfile(quality))
+ skipTestOnDevicesWithProblematicBuild()
val profiles = CamcorderProfile.getAll(cameraId, quality)
val video = profiles!!.videoProfiles[0]
@@ -184,13 +186,14 @@
assertThat(audioProxy.profile).isEqualTo(audio.profile)
}
- // TODO: removes after b/265613005 is fixed
- private fun skipTestOnProblematicBuildsOfCuttlefishApi33() {
- // Skip test for b/265613005
+ private fun skipTestOnDevicesWithProblematicBuild() {
+ // Skip test for b/265613005 and b/223439995
+ val hasVideoProfilesQuirk = DeviceQuirks[InvalidVideoProfilesQuirk::class.java] != null
+ val isProblematicCuttlefishBuild =
+ Build.MODEL.contains("Cuttlefish") && Build.ID.startsWith("TP1A")
Assume.assumeFalse(
- "Cuttlefish has null VideoProfile issue. Unable to test.",
- Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 33 &&
- Build.ID.startsWith("TP1A")
+ "Skip test with null VideoProfile issue. Unable to test.",
+ hasVideoProfilesQuirk || isProblematicCuttlefishBuild
)
}
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
index 65e72dc..b6ba0b18 100644
--- a/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/androidTest/java/androidx/camera/camera2/pipe/integration/UseCaseSurfaceManagerDeviceTest.kt
@@ -41,11 +41,9 @@
import androidx.camera.testing.activity.Camera2TestActivity
import androidx.camera.testing.fakes.FakeUseCase
import androidx.camera.testing.fakes.FakeUseCaseConfig
-import androidx.camera.testing.waitForIdle
import androidx.core.os.HandlerCompat
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
-import androidx.test.espresso.IdlingResource
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
@@ -149,8 +147,15 @@
assertThat(cameraClosedUsageCount).isEqualTo(1)
}
+ /**
+ * This test launches another (test) Activity with the intention of taking away camera from the
+ * test itself. On Android T and above, we listen to onCameraAccessPrioritiesChanged() and
+ * retries opening the camera when the camera is disconnected. That means the test activity will
+ * no longer deterministically get the final camera access on Android T and above. As such, we
+ * set the maximum SDK version to S_V2.
+ */
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.M, maxSdkVersion = Build.VERSION_CODES.S_V2)
fun disconnectOpenedCameraGraph_deferrableSurfaceUsageCountTest() = runBlocking {
CoreAppTestUtil.prepareDeviceUI(InstrumentationRegistry.getInstrumentation())
@@ -194,9 +199,13 @@
putExtra(Camera2TestActivity.EXTRA_CAMERA_ID, cameraId)
}
).use {
- lateinit var previewReady: IdlingResource
- it.onActivity { activity -> previewReady = activity.mPreviewReady!! }
- previewReady.waitForIdle()
+ // TODO(b/268768235): Under some conditions, it is possible that the camera gets
+ // disconnected for both the foreground and test activity, before the preview has a
+ // chance to be ready. Fix it with follow-up changes to change this test by using a
+ // CameraGraphSimulator rather than a real CameraGraph.
+ // lateinit var previewReady: IdlingResource
+ // it.onActivity { activity -> previewReady = activity.mPreviewReady!! }
+ // previewReady.waitForIdle()
cameraDisconnectedUsageCount = testSessionParameters.deferrableSurface.useCount
}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CamcorderProfileProviderAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CamcorderProfileProviderAdapter.kt
deleted file mode 100644
index b75b73d..0000000
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CamcorderProfileProviderAdapter.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2022 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.camera.camera2.pipe.integration.adapter
-
-import android.media.CamcorderProfile
-import android.os.Build
-import androidx.annotation.Nullable
-import androidx.annotation.RequiresApi
-import androidx.camera.core.Logger
-import androidx.camera.core.impl.CamcorderProfileProvider
-import androidx.camera.core.impl.CamcorderProfileProxy
-
-/**
- * Adapt the [CamcorderProfileProvider] interface to [CameraPipe].
- */
-@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-class CamcorderProfileProviderAdapter(cameraIdString: String) : CamcorderProfileProvider {
- private val hasValidCameraId: Boolean
- private val cameraId: Int
-
- init {
- var hasValidCameraId = false
- var intCameraId = -1
- try {
- intCameraId = cameraIdString.toInt()
- hasValidCameraId = true
- } catch (e: NumberFormatException) {
- Logger.w(
- TAG,
- "Camera id is not an integer: " +
- "$cameraIdString, unable to create CamcorderProfileProvider"
- )
- }
- this.hasValidCameraId = hasValidCameraId
- cameraId = intCameraId
-
- // TODO(b/241296464): CamcorderProfileResolutionQuirk and CamcorderProfileResolutionValidator
- }
-
- override fun hasProfile(quality: Int): Boolean {
- if (!hasValidCameraId) {
- return false
- }
- return CamcorderProfile.hasProfile(cameraId, quality)
- // TODO: b241296464 CamcorderProfileResolutionQuirk and
- // CamcorderProfileResolutionValidator. If has quick, check if the proxy profile has
- // valid video resolution
- }
-
- override fun get(quality: Int): CamcorderProfileProxy? {
- if (!hasValidCameraId) {
- return null
- }
- return if (!CamcorderProfile.hasProfile(cameraId, quality)) {
- null
- } else getProfileInternal(quality)
- // TODO: b241296464 CamcorderProfileResolutionQuirk and
- // CamcorderProfileResolutionValidator. If has quick, check if the proxy profile has
- // valid video resolution
- }
-
- @Nullable
- @Suppress("DEPRECATION")
- private fun getProfileInternal(quality: Int): CamcorderProfileProxy? {
- var profile: CamcorderProfile? = null
- try {
- profile = CamcorderProfile.get(cameraId, quality)
- } catch (e: RuntimeException) {
- // CamcorderProfile.get() will throw
- // - RuntimeException if not able to retrieve camcorder profile params.
- // - IllegalArgumentException if quality is not valid.
- Logger.w(TAG, "Unable to get CamcorderProfile by quality: $quality", e)
- }
- return if (profile != null) CamcorderProfileProxy.fromCamcorderProfile(profile) else null
- }
-
- companion object {
- private const val TAG = "CamcorderProfileProviderAdapter"
- }
-}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraControlAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraControlAdapter.kt
index 9f5dbc4..50a01d6 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraControlAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraControlAdapter.kt
@@ -108,21 +108,19 @@
override fun cancelFocusAndMetering(): ListenableFuture<Void> {
return Futures.nonCancellationPropagating(
- FutureChain.from(
- focusMeteringControl.cancelFocusAndMeteringAsync().asListenableFuture()
- ).transform(
- Function { return@Function null }, CameraXExecutors.directExecutor()
- )
+ threads.sequentialScope.async {
+ focusMeteringControl.cancelFocusAndMeteringAsync().join()
+ // Convert to null once the task is done, ignore the results.
+ return@async null
+ }.asListenableFuture()
)
}
override fun setZoomRatio(ratio: Float): ListenableFuture<Void> =
- zoomControl.setZoomRatioAsync(ratio)
+ zoomControl.setZoomRatio(ratio)
- override fun setLinearZoom(linearZoom: Float): ListenableFuture<Void> {
- val ratio = zoomControl.toZoomRatio(linearZoom)
- return setZoomRatio(ratio)
- }
+ override fun setLinearZoom(linearZoom: Float): ListenableFuture<Void> =
+ zoomControl.setLinearZoom(linearZoom)
override fun getFlashMode(): Int {
return flashControl.flashMode
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
index c62c357..56257d4 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
@@ -31,6 +31,7 @@
import androidx.camera.camera2.pipe.integration.internal.CameraCompatibilityFilter
import androidx.camera.camera2.pipe.integration.internal.CameraSelectionOptimizer
import androidx.camera.core.CameraSelector
+import androidx.camera.core.concurrent.CameraCoordinator
import androidx.camera.core.impl.CameraFactory
import androidx.camera.core.impl.CameraInternal
import androidx.camera.core.impl.CameraThreadConfig
@@ -88,5 +89,10 @@
// Use a LinkedHashSet to preserve order
LinkedHashSet(mAvailableCameraIds)
+ override fun getCameraCoordinator(): CameraCoordinator? {
+ // TODO(b/262772650): camera-pipe support for concurrent camera.
+ return null
+ }
+
override fun getCameraManager(): Any? = appComponent
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapter.kt
index 8e53e5c..1834af5 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapter.kt
@@ -40,9 +40,9 @@
import androidx.camera.core.ExposureState
import androidx.camera.core.FocusMeteringAction
import androidx.camera.core.ZoomState
-import androidx.camera.core.impl.CamcorderProfileProvider
import androidx.camera.core.impl.CameraCaptureCallback
import androidx.camera.core.impl.CameraInfoInternal
+import androidx.camera.core.impl.EncoderProfilesProvider
import androidx.camera.core.impl.ImageFormatConstants
import androidx.camera.core.impl.Quirks
import androidx.camera.core.impl.Timebase
@@ -68,7 +68,7 @@
private val cameraCallbackMap: CameraCallbackMap,
private val focusMeteringControl: FocusMeteringControl
) : CameraInfoInternal {
- private lateinit var camcorderProfileProviderAdapter: CamcorderProfileProviderAdapter
+ private lateinit var encoderProfilesProviderAdapter: EncoderProfilesProviderAdapter
@OptIn(ExperimentalCamera2Interop::class)
internal val camera2CameraInfo: Camera2CameraInfo by lazy {
Camera2CameraInfo.create(cameraProperties)
@@ -127,11 +127,11 @@
override fun getImplementationType(): String = "CameraPipe"
- override fun getCamcorderProfileProvider(): CamcorderProfileProvider {
- if (!::camcorderProfileProviderAdapter.isInitialized) {
- camcorderProfileProviderAdapter = CamcorderProfileProviderAdapter(cameraId)
+ override fun getEncoderProfilesProvider(): EncoderProfilesProvider {
+ if (!::encoderProfilesProviderAdapter.isInitialized) {
+ encoderProfilesProviderAdapter = EncoderProfilesProviderAdapter(cameraId)
}
- return camcorderProfileProviderAdapter
+ return encoderProfilesProviderAdapter
}
override fun getTimebase(): Timebase {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
index 4c03b51..9e84e9c 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraSurfaceAdapter.kt
@@ -65,7 +65,7 @@
SupportedSurfaceCombination(
context,
checkNotNull(cameraMetadata),
- CamcorderProfileProviderAdapter(cameraId)
+ EncoderProfilesProviderAdapter(cameraId)
)
}
}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapters.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapters.kt
index 1e31588..491c696 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapters.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapters.kt
@@ -21,10 +21,11 @@
import androidx.annotation.RequiresApi
import androidx.concurrent.futures.CallbackToFutureAdapter
import com.google.common.util.concurrent.ListenableFuture
+import java.util.concurrent.CancellationException
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
-import java.util.concurrent.CancellationException
/**
* Convert a job into a ListenableFuture<Void>.
@@ -75,4 +76,20 @@
tag
}
return CallbackToFutureAdapter.getFuture(resolver)
+}
+
+@OptIn(ExperimentalCoroutinesApi::class)
+fun <T> Deferred<T>.propagateTo(destination: CompletableDeferred<T>) {
+ invokeOnCompletion {
+ if (it != null) {
+ if (it is CancellationException) {
+ destination.cancel(it)
+ } else {
+ destination.completeExceptionally(it)
+ }
+ } else {
+ // Ignore exceptions - This should never throw in this situation.
+ destination.complete(getCompleted())
+ }
+ }
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/EncoderProfilesProviderAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/EncoderProfilesProviderAdapter.kt
index 224eeab..73addda 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/EncoderProfilesProviderAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/EncoderProfilesProviderAdapter.kt
@@ -22,6 +22,8 @@
import androidx.annotation.DoNotInline
import androidx.annotation.Nullable
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.integration.compat.quirk.DeviceQuirks
+import androidx.camera.camera2.pipe.integration.compat.quirk.InvalidVideoProfilesQuirk
import androidx.camera.core.Logger
import androidx.camera.core.impl.EncoderProfilesProvider
import androidx.camera.core.impl.EncoderProfilesProxy
@@ -71,23 +73,44 @@
}
@Nullable
- @Suppress("DEPRECATION")
private fun getProfilesInternal(quality: Int): EncoderProfilesProxy? {
- return if (Build.VERSION.SDK_INT >= 31) {
- val profiles: EncoderProfiles? = Api31Impl.getAll(cameraIdString, quality)
- if (profiles != null) EncoderProfilesProxyCompat.from(profiles) else null
- } else {
- var profile: CamcorderProfile? = null
- try {
- profile = CamcorderProfile.get(cameraId, quality)
- } catch (e: RuntimeException) {
- // CamcorderProfile.get() will throw
- // - RuntimeException if not able to retrieve camcorder profile params.
- // - IllegalArgumentException if quality is not valid.
- Logger.w(TAG, "Unable to get CamcorderProfile by quality: $quality", e)
+ if (Build.VERSION.SDK_INT >= 31) {
+ val profiles: EncoderProfiles = Api31Impl.getAll(cameraIdString, quality) ?: return null
+
+ val isVideoProfilesInvalid = DeviceQuirks[InvalidVideoProfilesQuirk::class.java] != null
+ if (isVideoProfilesInvalid) {
+ Logger.d(
+ TAG, "EncoderProfiles contains invalid video profiles, use " +
+ "CamcorderProfile to create EncoderProfilesProxy."
+ )
+ } else {
+ try {
+ return EncoderProfilesProxyCompat.from(profiles)
+ } catch (e: NullPointerException) {
+ Logger.w(
+ TAG, "Failed to create EncoderProfilesProxy, EncoderProfiles might " +
+ "contain invalid video profiles. Use CamcorderProfile instead.", e
+ )
+ }
}
- if (profile != null) EncoderProfilesProxyCompat.from(profile) else null
}
+
+ return createProfilesFromCamcorderProfile(quality)
+ }
+
+ @Nullable
+ @Suppress("DEPRECATION")
+ private fun createProfilesFromCamcorderProfile(quality: Int): EncoderProfilesProxy? {
+ var profile: CamcorderProfile? = null
+ try {
+ profile = CamcorderProfile.get(cameraId, quality)
+ } catch (e: RuntimeException) {
+ // CamcorderProfile.get() will throw
+ // - RuntimeException if not able to retrieve camcorder profile params.
+ // - IllegalArgumentException if quality is not valid.
+ Logger.w(TAG, "Unable to get CamcorderProfile by quality: $quality", e)
+ }
+ return if (profile != null) EncoderProfilesProxyCompat.from(profile) else null
}
@RequiresApi(31)
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
index 05cb202..527cc63 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombination.kt
@@ -34,7 +34,7 @@
import androidx.camera.core.AspectRatio
import androidx.camera.core.Logger
import androidx.camera.core.impl.AttachedSurfaceInfo
-import androidx.camera.core.impl.CamcorderProfileProxy
+import androidx.camera.core.impl.EncoderProfilesProxy
import androidx.camera.core.impl.ImageFormatConstants
import androidx.camera.core.impl.ImageOutputConfig
import androidx.camera.core.impl.StreamSpec
@@ -70,7 +70,7 @@
class SupportedSurfaceCombination(
context: Context,
private val cameraMetadata: CameraMetadata,
- private val camcorderProfileProviderAdapter: CamcorderProfileProviderAdapter
+ private val encoderProfilesProviderAdapter: EncoderProfilesProviderAdapter
) {
private val cameraId = cameraMetadata.camera.value
private val hardwareLevel =
@@ -289,12 +289,12 @@
// StreamConfigurationMap to determine the RECORD size.
return getRecordSizeFromStreamConfigurationMap()
}
- var profile: CamcorderProfileProxy? = null
- if (camcorderProfileProviderAdapter.hasProfile(cameraId)) {
- profile = camcorderProfileProviderAdapter.get(cameraId)
+ var profiles: EncoderProfilesProxy? = null
+ if (encoderProfilesProviderAdapter.hasProfile(cameraId)) {
+ profiles = encoderProfilesProviderAdapter.getAll(cameraId)
}
- return if (profile != null) {
- Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ return if (profiles != null && profiles.videoProfiles.isNotEmpty()) {
+ Size(profiles.videoProfiles[0].width, profiles.videoProfiles[0].height)
} else getRecordSizeByHasProfile()
}
@@ -337,25 +337,25 @@
*/
private fun getRecordSizeByHasProfile(): Size {
var recordSize: Size = RESOLUTION_480P
- var profile: CamcorderProfileProxy? = null
+ var profiles: EncoderProfilesProxy? = null
// Check whether 4KDCI, 2160P, 2K, 1080P, 720P, 480P (sorted by size) are supported by
- // CamcorderProfile
- if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_4KDCI)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_4KDCI)
- } else if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_2160P)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_2160P)
- } else if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_2K)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_2K)
- } else if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_1080P)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_1080P)
- } else if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_720P)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_720P)
- } else if (camcorderProfileProviderAdapter.hasProfile(CamcorderProfile.QUALITY_480P)) {
- profile = camcorderProfileProviderAdapter.get(CamcorderProfile.QUALITY_480P)
+ // EncoderProfiles
+ if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_4KDCI)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_4KDCI)
+ } else if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_2160P)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_2160P)
+ } else if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_2K)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_2K)
+ } else if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_1080P)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_1080P)
+ } else if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_720P)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_720P)
+ } else if (encoderProfilesProviderAdapter.hasProfile(CamcorderProfile.QUALITY_480P)) {
+ profiles = encoderProfilesProviderAdapter.getAll(CamcorderProfile.QUALITY_480P)
}
- if (profile != null) {
- recordSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ if (profiles != null && profiles.videoProfiles.isNotEmpty()) {
+ recordSize = Size(profiles.videoProfiles[0].width, profiles.videoProfiles[0].height)
}
return recordSize
}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/ZoomValue.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/ZoomValue.kt
index 5cc5969..8d19d82 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/ZoomValue.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/ZoomValue.kt
@@ -17,6 +17,8 @@
package androidx.camera.camera2.pipe.integration.adapter
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getLinearZoomFromZoomRatio
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getZoomRatioFromLinearZoom
import androidx.camera.core.ZoomState
/**
@@ -26,16 +28,39 @@
data class ZoomValue(
private val zoomRatio: Float,
private val minZoomRatio: Float,
- private val maxZoomRatio: Float
+ private val maxZoomRatio: Float,
) : ZoomState {
+ private var linearZoom: Float? = null
+
+ /**
+ * ZoomValue should be created with either zoomRatio or linearZoom and the other value should
+ * be calculated. If both are allowed to be set from outside, it becomes confusing regarding
+ * which value to use if the values don't align with conversion values.
+ * Secondary constructor with a LinearZoom value wrapper class is used for this purpose.
+ */
+ data class LinearZoom(val value: Float)
+ constructor(
+ linearZoom: LinearZoom,
+ minZoomRatio: Float,
+ maxZoomRatio: Float,
+ ) : this(
+ getZoomRatioFromLinearZoom(
+ linearZoom = linearZoom.value,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ ),
+ minZoomRatio,
+ maxZoomRatio
+ ) {
+ this.linearZoom = linearZoom.value
+ }
+
override fun getZoomRatio(): Float = zoomRatio
override fun getMaxZoomRatio(): Float = maxZoomRatio
override fun getMinZoomRatio(): Float = minZoomRatio
- override fun getLinearZoom(): Float {
- val range = maxZoomRatio - minZoomRatio
- if (range > 0) {
- return (zoomRatio - minZoomRatio) / range
- }
- return 1.0f
- }
-}
\ No newline at end of file
+ override fun getLinearZoom() = linearZoom ?: getLinearZoomFromZoomRatio(
+ zoomRatio = zoomRatio,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/Camera2CameraControlCompat.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/Camera2CameraControlCompat.kt
index b00002b..33adefc 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/Camera2CameraControlCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/Camera2CameraControlCompat.kt
@@ -24,6 +24,7 @@
import androidx.camera.camera2.pipe.FrameNumber
import androidx.camera.camera2.pipe.Request
import androidx.camera.camera2.pipe.RequestMetadata
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
import androidx.camera.camera2.pipe.integration.config.CameraScope
import androidx.camera.camera2.pipe.integration.impl.Camera2ImplConfig
import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera
@@ -51,7 +52,7 @@
fun clearRequestOption()
fun cancelCurrentTask()
- fun applyAsync(camera: UseCaseCamera?): Deferred<Void?>
+ fun applyAsync(camera: UseCaseCamera?, cancelPreviousTask: Boolean = true): Deferred<Void?>
@Module
abstract class Bindings {
@@ -114,15 +115,23 @@
}
}
- override fun applyAsync(camera: UseCaseCamera?): Deferred<Void?> {
+ override fun applyAsync(camera: UseCaseCamera?, cancelPreviousTask: Boolean): Deferred<Void?> {
val signal: CompletableDeferred<Void?> = CompletableDeferred()
val config = synchronized(lock) {
configBuilder.build()
}
threads.sequentialScope.launch {
if (camera != null) {
- // Cancel the previous request signal if exist.
- updateSignal?.cancelSignal()
+ if (cancelPreviousTask) {
+ // Cancel the previous request signal if exist.
+ updateSignal?.cancelSignal()
+ } else {
+ // propagate the result to the previous updateSignal
+ updateSignal?.let { previousUpdateSignal ->
+ signal.propagateTo(previousUpdateSignal)
+ }
+ }
+
updateSignal = signal
camera.requestControl.setConfigAsync(
type = UseCaseCameraRequestControl.Type.CAMERA2_CAMERA_CONTROL,
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/EvCompCompat.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/EvCompCompat.kt
index 7324125..3dafac7 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/EvCompCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/EvCompCompat.kt
@@ -29,6 +29,7 @@
import androidx.camera.camera2.pipe.FrameNumber
import androidx.camera.camera2.pipe.Request
import androidx.camera.camera2.pipe.RequestMetadata
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
import androidx.camera.camera2.pipe.integration.config.CameraScope
import androidx.camera.camera2.pipe.integration.impl.CameraProperties
import androidx.camera.camera2.pipe.integration.impl.ComboRequestListener
@@ -37,21 +38,22 @@
import androidx.camera.core.CameraControl
import dagger.Binds
import dagger.Module
+import javax.inject.Inject
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.launch
-import javax.inject.Inject
interface EvCompCompat {
val supported: Boolean
val range: Range<Int>
val step: Rational
- fun stopRunningTask()
+ fun stopRunningTask(throwable: Throwable)
fun applyAsync(
evCompIndex: Int,
- camera: UseCaseCamera
+ camera: UseCaseCamera,
+ cancelPreviousTask: Boolean,
): Deferred<Int>
@Module
@@ -90,18 +92,38 @@
private var updateSignal: CompletableDeferred<Int>? = null
private var updateListener: Request.Listener? = null
- override fun stopRunningTask() {
+ override fun stopRunningTask(throwable: Throwable) {
threads.sequentialScope.launch {
- stopRunningTaskInternal()
+ updateSignal?.completeExceptionally(throwable)
}
}
- override fun applyAsync(evCompIndex: Int, camera: UseCaseCamera): Deferred<Int> {
+ override fun applyAsync(
+ evCompIndex: Int,
+ camera: UseCaseCamera,
+ cancelPreviousTask: Boolean,
+ ): Deferred<Int> {
val signal = CompletableDeferred<Int>()
threads.sequentialScope.launch {
- stopRunningTaskInternal()
+ updateSignal?.let { previousUpdateSignal ->
+ if (cancelPreviousTask) {
+ // Cancel the previous request signal if exist.
+ previousUpdateSignal.completeExceptionally(
+ CameraControl.OperationCanceledException(
+ "Cancelled by another setExposureCompensationIndex()"
+ )
+ )
+ } else {
+ // Propagate the result to the previous updateSignal
+ signal.propagateTo(previousUpdateSignal)
+ }
+ }
updateSignal = signal
+ updateListener?.let {
+ comboRequestListener.removeListener(it)
+ updateListener = null
+ }
camera.setParameterAsync(CONTROL_AE_EXPOSURE_COMPENSATION, evCompIndex)
@@ -110,7 +132,7 @@
override fun onComplete(
requestMetadata: RequestMetadata,
frameNumber: FrameNumber,
- result: FrameInfo
+ result: FrameInfo,
) {
val state = result.metadata[CaptureResult.CONTROL_AE_STATE]
val evResult = result.metadata[CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION]
@@ -121,7 +143,6 @@
CaptureResult.CONTROL_AE_STATE_LOCKED ->
if (evResult == evCompIndex) {
signal.complete(evCompIndex)
- comboRequestListener.removeListener(this)
}
else -> {
}
@@ -130,32 +151,14 @@
// If AE state is null, only wait for the exposure result to the desired
// value.
signal.complete(evCompIndex)
-
- // Remove the capture result listener. The updateSignal and
- // updateListener will be cleared before the next set exposure task.
- comboRequestListener.removeListener(this)
}
}
+ }.also { requestListener ->
+ comboRequestListener.addListener(requestListener, threads.sequentialExecutor)
+ signal.invokeOnCompletion { comboRequestListener.removeListener(requestListener) }
}
- comboRequestListener.addListener(updateListener!!, threads.sequentialExecutor)
}
return signal
}
-
- private fun stopRunningTaskInternal() {
- updateSignal?.let {
- it.completeExceptionally(
- CameraControl.OperationCanceledException(
- "Cancelled by another setExposureCompensationIndex()"
- )
- )
- updateSignal = null
- }
-
- updateListener?.let {
- comboRequestListener.removeListener(it)
- updateListener = null
- }
- }
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
index 38d92ef..a9e1348 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
@@ -30,14 +30,21 @@
import dagger.Provides
interface ZoomCompat {
- val minZoom: Float
- val maxZoom: Float
+ val minZoomRatio: Float
+ val maxZoomRatio: Float
fun apply(
zoomRatio: Float,
camera: UseCaseCamera
)
+ /**
+ * Returns the current crop sensor region which should be used for converting
+ * [androidx.camera.core.MeteringPoint] to sensor coordinates. Returns the sensor
+ * rect if there is no crop region being set.
+ */
+ fun getCropSensorRegion(): Rect
+
@Module
abstract class Bindings {
companion object {
@@ -47,7 +54,7 @@
val range =
cameraProperties.metadata[CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE]
if (range != null) {
- AndroidRZoomCompat(range)
+ AndroidRZoomCompat(cameraProperties, range)
} else {
CropRegionZoomCompat(cameraProperties)
}
@@ -60,23 +67,28 @@
}
class CropRegionZoomCompat(private val cameraProperties: CameraProperties) : ZoomCompat {
- override val minZoom: Float
+ override val minZoomRatio: Float
get() = 1.0f
- override val maxZoom: Float
+ override val maxZoomRatio: Float
get() = cameraProperties.metadata.getOrDefault(
- CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, minZoom
+ CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, minZoomRatio
)
+ private var currentCropRect: Rect? = null
+
override fun apply(
zoomRatio: Float,
camera: UseCaseCamera
) {
val sensorRect =
cameraProperties.metadata[CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE]!!
- val cropRect = computeCropRect(sensorRect, zoomRatio)
- camera.setParameterAsync(CaptureRequest.SCALER_CROP_REGION, cropRect)
+ currentCropRect = computeCropRect(sensorRect, zoomRatio)
+ camera.setParameterAsync(CaptureRequest.SCALER_CROP_REGION, currentCropRect)
}
+ override fun getCropSensorRegion() = currentCropRect
+ ?: cameraProperties.metadata[CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE]!!
+
private fun computeCropRect(sensorRect: Rect, zoomRatio: Float): Rect {
val cropWidth: Float = sensorRect.width() / zoomRatio
val cropHeight: Float = sensorRect.height() / zoomRatio
@@ -92,17 +104,23 @@
}
@RequiresApi(Build.VERSION_CODES.R)
-class AndroidRZoomCompat(private val range: Range<Float>) : ZoomCompat {
- override val minZoom: Float
+class AndroidRZoomCompat(
+ private val cameraProperties: CameraProperties,
+ private val range: Range<Float>,
+) : ZoomCompat {
+ override val minZoomRatio: Float
get() = range.lower
- override val maxZoom: Float
+ override val maxZoomRatio: Float
get() = range.upper
override fun apply(
zoomRatio: Float,
camera: UseCaseCamera
) {
- require(zoomRatio in minZoom..maxZoom)
+ require(zoomRatio in minZoomRatio..maxZoomRatio)
camera.setParameterAsync(CaptureRequest.CONTROL_ZOOM_RATIO, zoomRatio)
}
-}
\ No newline at end of file
+
+ override fun getCropSensorRegion(): Rect =
+ cameraProperties.metadata[CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE]!!
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirks.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirks.kt
new file mode 100644
index 0000000..a46eb22
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirks.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 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.
+ */
+
+@file:RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+
+package androidx.camera.camera2.pipe.integration.compat.quirk
+
+import androidx.annotation.RequiresApi
+import androidx.camera.core.impl.Quirk
+import androidx.camera.core.impl.Quirks
+
+/**
+ * Provider of device specific quirks, which are used for device specific workarounds.
+ *
+ * Device specific quirks depend on device properties, including the manufacturer
+ * ([android.os.Build.MANUFACTURER]), model ([android.os.Build.MODEL]) and OS
+ * level ([android.os.Build.VERSION.SDK_INT]).
+ *
+ * Device specific quirks are lazily loaded, i.e. They are loaded the first time they're needed.
+ */
+object DeviceQuirks {
+
+ /** Returns all device specific quirks loaded on the current device. */
+ val all: Quirks by lazy {
+ Quirks(DeviceQuirksLoader.loadQuirks())
+ }
+
+ /**
+ * Retrieves a specific device [Quirk] instance given its type.
+ *
+ * @param quirkClass The type of device quirk to retrieve.
+ * @return A device [Quirk] instance of the provided type, or `null` if it isn't found.
+ */
+ operator fun <T : Quirk?> get(quirkClass: Class<T>): T? {
+ return all.get(quirkClass)
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt
new file mode 100644
index 0000000..43b87c6
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 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.
+ */
+
+@file:RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+
+package androidx.camera.camera2.pipe.integration.compat.quirk
+
+import androidx.annotation.RequiresApi
+import androidx.camera.core.impl.Quirk
+
+/**
+ * Loads all device specific quirks required for the current device.
+ */
+object DeviceQuirksLoader {
+
+ /**
+ * Goes through all defined device-specific quirks, and returns those that should be loaded
+ * on the current device.
+ */
+ fun loadQuirks(): List<Quirk> {
+ val quirks: MutableList<Quirk> = mutableListOf()
+
+ // Load all device specific quirks.
+ if (InvalidVideoProfilesQuirk.load()) {
+ quirks.add(InvalidVideoProfilesQuirk())
+ }
+
+ return quirks
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt
new file mode 100644
index 0000000..20abaa1
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/InvalidVideoProfilesQuirk.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 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.
+ */
+
+@file:RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+
+package androidx.camera.camera2.pipe.integration.compat.quirk
+
+import android.annotation.SuppressLint
+import android.media.EncoderProfiles
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.camera.core.impl.Quirk
+
+/**
+ * Quirk denoting the video profile list returns by [EncoderProfiles] is invalid.
+ *
+ * QuirkSummary
+ * - Bug Id: 267727595
+ * - Description: When using [EncoderProfiles] on TP1A or TD1A builds of Android API 33,
+ * [EncoderProfiles.getVideoProfiles] returns a list with size one, but the single value in the
+ * list is null. This is not the expected behavior, and makes [EncoderProfiles] lack of video
+ * information.
+ * - Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33).
+ *
+ * TODO: enable CameraXQuirksClassDetector lint check when kotlin is supported.
+ */
+@SuppressLint("CameraXQuirksClassDetector")
+class InvalidVideoProfilesQuirk : Quirk {
+
+ companion object {
+ private val AFFECTED_MODELS: List<String> = listOf(
+ "pixel 4",
+ "pixel 4a",
+ "pixel 4 xl",
+ "pixel 5",
+ "pixel 5a",
+ "pixel 6",
+ "pixel 6a",
+ "pixel 6 pro",
+ "pixel 7",
+ "pixel 7 pro"
+ )
+
+ fun load(): Boolean {
+ return isAffectedModel() && isAffectedBuild()
+ }
+
+ private fun isAffectedModel(): Boolean {
+ return AFFECTED_MODELS.contains(
+ Build.MODEL.lowercase()
+ )
+ }
+
+ private fun isAffectedBuild(): Boolean {
+ return isTp1aBuild() || isTd1aBuild()
+ }
+
+ private fun isTp1aBuild(): Boolean {
+ return Build.ID.startsWith("TP1A")
+ }
+
+ private fun isTd1aBuild(): Boolean {
+ return Build.ID.startsWith("TD1A")
+ }
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/package-info.java b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/package-info.java
new file mode 100644
index 0000000..eca73c3
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2023 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.
+ */
+
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+package androidx.camera.camera2.pipe.integration.compat.quirk;
+
+import androidx.annotation.RestrictTo;
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/EvCompControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/EvCompControl.kt
index a4be0a8..2bba010 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/EvCompControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/EvCompControl.kt
@@ -63,16 +63,15 @@
get() = _useCaseCamera
set(value) {
_useCaseCamera = value
- updateAsync(evCompIndex)
+ updateAsync(evCompIndex, cancelPreviousTask = false)
}
override fun reset() {
- evCompIndex = 0
- compat.stopRunningTask()
- updateAsync(0)
+ evCompIndex = DEFAULT_EXPOSURE_COMPENSATION
+ updateAsync(DEFAULT_EXPOSURE_COMPENSATION)
}
- fun updateAsync(exposureIndex: Int): Deferred<Int> {
+ fun updateAsync(exposureIndex: Int, cancelPreviousTask: Boolean = true): Deferred<Int> {
if (!compat.supported) {
return createFailureResult(
IllegalArgumentException("ExposureCompensation is not supported")
@@ -88,12 +87,15 @@
)
}
- useCaseCamera?.let {
+ return useCaseCamera?.let { camera ->
evCompIndex = exposureIndex
- return compat.applyAsync(exposureIndex, it)
- } ?: return createFailureResult(
- CameraControl.OperationCanceledException("Camera is not active.")
- )
+ compat.applyAsync(exposureIndex, camera, cancelPreviousTask)
+ } ?: run {
+ CameraControl.OperationCanceledException("Camera is not active.").let { cancelResult ->
+ compat.stopRunningTask(cancelResult)
+ createFailureResult(cancelResult)
+ }
+ }
}
private fun createFailureResult(exception: Exception) = CompletableDeferred<Int>().apply {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FlashControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FlashControl.kt
index 21fe187..e053c73 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FlashControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FlashControl.kt
@@ -17,6 +17,7 @@
package androidx.camera.camera2.pipe.integration.impl
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
import androidx.camera.camera2.pipe.integration.config.CameraScope
import androidx.camera.core.CameraControl
import androidx.camera.core.ImageCapture
@@ -45,7 +46,7 @@
get() = _useCaseCamera
set(value) {
_useCaseCamera = value
- setFlashAsync(_flashMode)
+ setFlashAsync(_flashMode, false)
}
override fun reset() {
@@ -71,7 +72,7 @@
}
private set
- fun setFlashAsync(flashMode: Int): Deferred<Unit> {
+ fun setFlashAsync(flashMode: Int, cancelPreviousTask: Boolean = true): Deferred<Unit> {
val signal = CompletableDeferred<Unit>()
useCaseCamera?.let {
@@ -81,13 +82,18 @@
_flashMode = flashMode
threads.sequentialScope.launch {
- stopRunningTask()
+ if (cancelPreviousTask) {
+ stopRunningTask()
+ } else {
+ // Propagate the result to the previous updateSignal
+ _updateSignal?.let { previousUpdateSignal ->
+ signal.propagateTo(previousUpdateSignal)
+ }
+ }
_updateSignal = signal
state3AControl.flashMode = flashMode
- state3AControl.updateSignal?.join()
-
- signal.complete(Unit)
+ state3AControl.updateSignal?.propagateTo(signal) ?: run { signal.complete(Unit) }
}
} ?: run {
signal.completeExceptionally(
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FocusMeteringControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FocusMeteringControl.kt
index 0b11ba7..a7c456f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FocusMeteringControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/FocusMeteringControl.kt
@@ -27,6 +27,8 @@
import androidx.camera.camera2.pipe.AeMode
import androidx.camera.camera2.pipe.Result3A
import androidx.camera.camera2.pipe.integration.adapter.asListenableFuture
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
+import androidx.camera.camera2.pipe.integration.compat.ZoomCompat
import androidx.camera.camera2.pipe.integration.config.CameraScope
import androidx.camera.core.CameraControl.OperationCanceledException
import androidx.camera.core.FocusMeteringAction
@@ -53,6 +55,7 @@
private val cameraProperties: CameraProperties,
private val state3AControl: State3AControl,
private val threads: UseCaseThreads,
+ private val zoomCompat: ZoomCompat,
) : UseCaseCameraControl, UseCaseCamera.RunningUseCasesChangeListener {
private var _useCaseCamera: UseCaseCamera? = null
@@ -80,15 +83,12 @@
cancelFocusAndMeteringAsync()
}
- @Volatile
private var previewAspectRatio: Rational? = null
- private val sensorRect by lazy {
- // TODO("b/262225455"): use the actual crop sensor region like in camera-camera2
- cameraProperties.metadata[CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE]!!
- }
+ private val cropSensorRegion
+ get() = zoomCompat.getCropSensorRegion()
private val defaultAspectRatio: Rational
- get() = previewAspectRatio ?: Rational(sensorRect.width(), sensorRect.height())
+ get() = previewAspectRatio ?: Rational(cropSensorRegion.width(), cropSensorRegion.height())
private val maxAfRegionCount =
cameraProperties.metadata.getOrDefault(CameraCharacteristics.CONTROL_MAX_REGIONS_AF, 0)
@@ -114,19 +114,19 @@
val aeRectangles = meteringRegionsFromMeteringPoints(
action.meteringPointsAe,
maxAeRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
val afRectangles = meteringRegionsFromMeteringPoints(
action.meteringPointsAf,
maxAfRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
val awbRectangles = meteringRegionsFromMeteringPoints(
action.meteringPointsAwb,
maxAwbRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
if (aeRectangles.isEmpty() && afRectangles.isEmpty() && awbRectangles.isEmpty()) {
@@ -161,7 +161,7 @@
} else {
if (isCancelEnabled) {
if (signal.isActive) {
- cancelFocusAndMeteringNow(useCaseCamera, signal)
+ cancelFocusAndMeteringNowAsync(useCaseCamera, signal)
}
} else {
signal.complete(FocusMeteringResult.create(false))
@@ -190,19 +190,19 @@
val rectanglesAe = meteringRegionsFromMeteringPoints(
action.meteringPointsAe,
maxAeRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
val rectanglesAf = meteringRegionsFromMeteringPoints(
action.meteringPointsAf,
maxAfRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
val rectanglesAwb = meteringRegionsFromMeteringPoints(
action.meteringPointsAwb,
maxAwbRegionCount,
- sensorRect,
+ cropSensorRegion,
defaultAspectRatio
)
return rectanglesAe.isNotEmpty() || rectanglesAf.isNotEmpty() || rectanglesAwb.isNotEmpty()
@@ -231,7 +231,7 @@
threads.sequentialScope.launch {
cancelSignal?.setCancelException("Cancelled by another cancelFocusAndMetering()")
cancelSignal = signal
- signal.complete(cancelFocusAndMeteringNow(useCaseCamera, updateSignal))
+ cancelFocusAndMeteringNowAsync(useCaseCamera, updateSignal).propagateTo(signal)
}
} ?: run {
signal.completeExceptionally(OperationCanceledException("Camera is not active."))
@@ -240,13 +240,13 @@
return signal
}
- private suspend fun cancelFocusAndMeteringNow(
+ private suspend fun cancelFocusAndMeteringNowAsync(
useCaseCamera: UseCaseCamera,
signalToCancel: CompletableDeferred<FocusMeteringResult>?,
- ): Result3A {
+ ): Deferred<Result3A> {
signalToCancel?.setCancelException("Cancelled by cancelFocusAndMetering()")
state3AControl.preferredFocusMode = null
- return useCaseCamera.requestControl.cancelFocusAndMeteringAsync().await()
+ return useCaseCamera.requestControl.cancelFocusAndMeteringAsync()
}
private fun <T> CompletableDeferred<T>.setCancelException(message: String) {
@@ -287,8 +287,6 @@
val cropRegionAspectRatio =
Rational(cropSensorRegion.width(), cropSensorRegion.height())
- // TODO(sushilnath@): limit the number of metering regions to what is supported by the
- // device.
for (meteringPoint in meteringPoints) {
// Only enable at most maxRegionCount.
if (meteringRegions.size >= maxRegionCount) {
@@ -297,8 +295,6 @@
if (!isValid(meteringPoint)) {
continue
}
- // TODO(sushilnath@): Use the zoom based crop region aspect ratio instead of sensor
- // active array aspect ratio.
val adjustedPoint: PointF =
getFovAdjustedPoint(meteringPoint, cropRegionAspectRatio, defaultAspectRatio)
val meteringRectangle: MeteringRectangle =
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/State3AControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/State3AControl.kt
index dc8aa7e..4c5f71f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/State3AControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/State3AControl.kt
@@ -19,9 +19,12 @@
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CaptureRequest
+import androidx.annotation.GuardedBy
import androidx.annotation.RequiresApi
import androidx.camera.camera2.pipe.integration.adapter.SessionConfigAdapter
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
import androidx.camera.camera2.pipe.integration.config.CameraScope
+import androidx.camera.core.CameraControl
import androidx.camera.core.ImageCapture
import androidx.camera.core.UseCase
import androidx.camera.core.impl.CaptureConfig
@@ -45,7 +48,16 @@
set(value) {
_useCaseCamera = value
value?.let {
+ val previousSignals = synchronized(lock) {
+ updateSignal = null
+ updateSignals.toList()
+ }
+
invalidate() // Always apply the settings to the camera.
+
+ synchronized(lock) { updateSignal }?.let { newUpdateSignal ->
+ previousSignals.forEach { newUpdateSignal.propagateTo(it) }
+ } ?: run { previousSignals.forEach { it.complete(Unit) } }
}
}
@@ -68,6 +80,12 @@
intArrayOf(CaptureRequest.CONTROL_AWB_MODE_OFF)
).asList()
+ private val lock = Any()
+
+ @GuardedBy("lock")
+ private val updateSignals = mutableSetOf<CompletableDeferred<Unit>>()
+
+ @GuardedBy("lock")
var updateSignal: Deferred<Unit>? = null
private set
var flashMode by updateOnPropertyChange(DEFAULT_FLASH_MODE)
@@ -76,6 +94,7 @@
var preferredFocusMode: Int? by updateOnPropertyChange(null)
override fun reset() {
+ synchronized(lock) { updateSignals.toList() }.cancelAll()
preferredAeMode = null
preferredFocusMode = null
flashMode = DEFAULT_FLASH_MODE
@@ -106,7 +125,7 @@
val preferAfMode = preferredFocusMode ?: getDefaultAfMode()
- updateSignal = useCaseCamera?.requestControl?.addParametersAsync(
+ useCaseCamera?.requestControl?.addParametersAsync(
values = mapOf(
CaptureRequest.CONTROL_AE_MODE to getSupportedAeMode(preferAeMode),
CaptureRequest.CONTROL_AF_MODE to getSupportedAfMode(preferAfMode),
@@ -114,7 +133,21 @@
CaptureRequest.CONTROL_AWB_MODE_AUTO
),
)
- ) ?: CompletableDeferred(null)
+ )?.apply {
+ toCompletableDeferred().also { signal ->
+ synchronized(lock) {
+ updateSignals.add(signal)
+ updateSignal = signal
+ signal.invokeOnCompletion {
+ synchronized(lock) {
+ updateSignals.remove(signal)
+ }
+ }
+ }
+ }
+ } ?: run {
+ synchronized(lock) { updateSignal = CompletableDeferred(null) }
+ }
}
private fun getDefaultAfMode(): Int = when (template) {
@@ -189,6 +222,13 @@
}
}
+ private fun <T> Deferred<T>.toCompletableDeferred() =
+ CompletableDeferred<T>().also { propagateTo(it) }
+
+ private fun <T> Collection<CompletableDeferred<T>>.cancelAll() = forEach {
+ it.completeExceptionally(CameraControl.OperationCanceledException("Camera is not active."))
+ }
+
@Module
abstract class Bindings {
@Binds
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/TorchControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/TorchControl.kt
index 7981dc9..21e752a 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/TorchControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/TorchControl.kt
@@ -19,6 +19,7 @@
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CaptureRequest
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.integration.adapter.propagateTo
import androidx.camera.camera2.pipe.integration.config.CameraScope
import androidx.camera.core.CameraControl
import androidx.camera.core.TorchState
@@ -51,10 +52,11 @@
set(value) {
_useCaseCamera = value
setTorchAsync(
- when (torchStateLiveData.value) {
+ torch = when (torchStateLiveData.value) {
TorchState.ON -> true
else -> false
- }
+ },
+ cancelPreviousTask = false,
)
}
@@ -77,7 +79,7 @@
private var _updateSignal: CompletableDeferred<Unit>? = null
- fun setTorchAsync(torch: Boolean): Deferred<Unit> {
+ fun setTorchAsync(torch: Boolean, cancelPreviousTask: Boolean = true): Deferred<Unit> {
val signal = CompletableDeferred<Unit>()
if (!hasFlashUnit) {
@@ -89,7 +91,15 @@
_torchState.setLiveDataValue(torch)
threads.sequentialScope.launch {
- stopRunningTaskInternal()
+ if (cancelPreviousTask) {
+ stopRunningTaskInternal()
+ } else {
+ // Propagate the result to the previous updateSignal
+ _updateSignal?.let { previousUpdateSignal ->
+ signal.propagateTo(previousUpdateSignal)
+ }
+ }
+
_updateSignal = signal
// TODO(b/209757083), handle the failed result of the setTorchAsync().
@@ -98,9 +108,7 @@
// Hold the internal AE mode to ON while the torch is turned ON.
state3AControl.preferredAeMode =
if (torch) CaptureRequest.CONTROL_AE_MODE_ON else null
- state3AControl.updateSignal?.join()
-
- signal.complete(Unit)
+ state3AControl.updateSignal?.propagateTo(signal) ?: run { signal.complete(Unit) }
}
} ?: run {
signal.createFailureResult(
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/ZoomControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/ZoomControl.kt
index 698da1b..66fbb27 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/ZoomControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/ZoomControl.kt
@@ -21,6 +21,8 @@
import androidx.camera.camera2.pipe.integration.adapter.asListenableFuture
import androidx.camera.camera2.pipe.integration.compat.ZoomCompat
import androidx.camera.camera2.pipe.integration.config.CameraScope
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getLinearZoomFromZoomRatio
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getZoomRatioFromLinearZoom
import androidx.camera.core.CameraControl
import androidx.camera.core.ZoomState
import androidx.camera.core.impl.utils.futures.Futures
@@ -31,7 +33,6 @@
import dagger.Module
import dagger.multibindings.IntoSet
import javax.inject.Inject
-import kotlin.math.abs
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -47,11 +48,11 @@
) : UseCaseCameraControl {
// NOTE: minZoom may be lower than 1.0
// NOTE: Default zoom ratio is 1.0 (DEFAULT_ZOOM_RATIO)
- val minZoom: Float = zoomCompat.minZoom
- val maxZoom: Float = zoomCompat.maxZoom
+ val minZoomRatio: Float = zoomCompat.minZoomRatio
+ val maxZoomRatio: Float = zoomCompat.maxZoomRatio
val defaultZoomState by lazy {
- ZoomValue(DEFAULT_ZOOM_RATIO, minZoom, maxZoom)
+ ZoomValue(DEFAULT_ZOOM_RATIO, minZoomRatio, maxZoomRatio)
}
private val _zoomState by lazy {
@@ -62,28 +63,18 @@
get() = _zoomState
/** Linear zoom is between 0.0f and 1.0f */
- fun toLinearZoom(zoomRatio: Float): Float {
- val range = zoomCompat.maxZoom - zoomCompat.minZoom
- if (range > 0) {
- return (zoomRatio - zoomCompat.minZoom) / range
- }
- return 0.0f
- }
+ fun toLinearZoom(zoomRatio: Float) = getLinearZoomFromZoomRatio(
+ zoomRatio = zoomRatio,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
/** Zoom ratio is commonly used as the "1x, 2x, 5x" zoom ratio. Zoom ratio may be less than 1 */
- fun toZoomRatio(linearZoom: Float): Float {
- val range = zoomCompat.maxZoom - zoomCompat.minZoom
- if (range > 0) {
- return linearZoom * range + zoomCompat.minZoom
- }
-
- // if minZoom = maxZoom = 2.0f, 2.0f should be returned instead of default 1.0f
- if (nearZero(range)) {
- return zoomCompat.minZoom
- }
-
- return DEFAULT_ZOOM_RATIO
- }
+ private fun toZoomRatio(linearZoom: Float) = getZoomRatioFromLinearZoom(
+ linearZoom = linearZoom,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
private var _useCaseCamera: UseCaseCamera? = null
override var useCaseCamera: UseCaseCamera?
@@ -117,16 +108,46 @@
}
}
- fun setZoomRatioAsync(ratio: Float): ListenableFuture<Void> {
+ fun setLinearZoom(linearZoom: Float): ListenableFuture<Void> {
+ if (linearZoom > 1.0f || linearZoom < 0f) {
+ val outOfRangeDesc =
+ "Requested linearZoom $linearZoom is not within valid range [0, 1]"
+ return Futures.immediateFailedFuture(
+ IllegalArgumentException(outOfRangeDesc)
+ )
+ }
+
+ val zoomValue = ZoomValue(
+ ZoomValue.LinearZoom(linearZoom),
+ minZoomRatio,
+ maxZoomRatio,
+ )
+ return setZoomValue(zoomValue)
+ }
+
+ fun setZoomRatio(zoomRatio: Float): ListenableFuture<Void> {
+ if (zoomRatio > maxZoomRatio || zoomRatio < minZoomRatio) {
+ val outOfRangeDesc =
+ "Requested zoomRatio $zoomRatio is not within valid range" +
+ " [$minZoomRatio, $maxZoomRatio]"
+ return Futures.immediateFailedFuture(
+ IllegalArgumentException(outOfRangeDesc)
+ )
+ }
+
+ val zoomValue = ZoomValue(
+ zoomRatio,
+ minZoomRatio,
+ maxZoomRatio,
+ )
+ return setZoomValue(zoomValue)
+ }
+
+ fun setZoomValue(zoomValue: ZoomValue): ListenableFuture<Void> {
// TODO: report IllegalArgumentException if ratio not in range
return Futures.nonCancellationPropagating(
useCaseCamera?.let {
threads.scope.launch(start = CoroutineStart.UNDISPATCHED) {
- val zoomValue = ZoomValue(
- ratio,
- minZoom,
- maxZoom
- )
setZoomState(zoomValue)
update()
}.asListenableFuture()
@@ -136,10 +157,6 @@
)
}
- private fun nearZero(num: Float): Boolean {
- return abs(num) < 2.0 * Math.ulp(abs(num))
- }
-
@Module
abstract class Bindings {
@Binds
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/ZoomMath.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/ZoomMath.kt
new file mode 100644
index 0000000..0114d24
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/ZoomMath.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2023 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.camera.camera2.pipe.integration.internal
+
+import androidx.core.math.MathUtils
+import kotlin.math.abs
+
+/**
+ * This class is used for containing the mathematical calculations for ZoomControl, mainly the
+ * conversions between zoomRatio and linearZoom.
+ *
+ * The linearZoom is the percentage of zoom amount i.e. how much cropWidth is being used,
+ * so linearZoom = 0.5 should represent the middle point of
+ * [minZoomCropWidth, maxZoomCropWidth] range. But that does not mean it should be the same as
+ * (minZoom + maxZoom) / 2. For example, consider the case where
+ * original cropWidth = 10000 for zoomRatio = 1.0f,
+ * minZoomRatio = 1.0f, maxZoomRatio = 10.0f,
+ * zoomRatio = 5.5f may not represent linearZoom = 0.5 i.e. the half zoom amount. Here,
+ * zoomRatio = 1.0f, cropWidth = 10000,
+ * zoomRatio = 5.5f, cropWidth = 1818.18
+ * zoomRatio = 10.0f, cropWidth = 1000
+ * As observed, zoomRatio = 5.5f does not yield cropWidth = 5500 which would be the actual
+ * zooming amount middle point.
+ */
+object ZoomMath {
+ fun getLinearZoomFromZoomRatio(
+ zoomRatio: Float,
+ minZoomRatio: Float,
+ maxZoomRatio: Float
+ ): Float {
+ // if zoom is not supported i.e. minZoomRatio = maxZoomRatio, return 0
+ if (areFloatsEqual(minZoomRatio, maxZoomRatio)) {
+ return 0f
+ }
+
+ if (areFloatsEqual(zoomRatio, maxZoomRatio)) {
+ return 1f
+ } else if (areFloatsEqual(zoomRatio, minZoomRatio)) {
+ return 0f
+ }
+
+ /**
+ * linearZoom should represent the percentage of zoom amount based on how much cropWidth
+ * is visible.
+ *
+ * The original sensor region width is considered as 1.0f here as we only need the
+ * linearZoom ratio, not the actual crop width.
+ */
+ val relativeCropWidth = 1.0f / zoomRatio
+ val relativeCropWidthInMaxZoom = 1.0f / maxZoomRatio
+ val relativeCropWidthInMinZoom = 1.0f / minZoomRatio
+
+ val linearZoom = (relativeCropWidthInMinZoom - relativeCropWidth) /
+ (relativeCropWidthInMinZoom - relativeCropWidthInMaxZoom)
+
+ return MathUtils.clamp(linearZoom, 0f, 1.0f)
+ }
+
+ fun getZoomRatioFromLinearZoom(
+ linearZoom: Float,
+ minZoomRatio: Float,
+ maxZoomRatio: Float
+ ): Float {
+ if (areFloatsEqual(linearZoom, 1.0f)) {
+ return maxZoomRatio
+ } else if (areFloatsEqual(linearZoom, 0f)) {
+ return minZoomRatio
+ }
+
+ /**
+ * This crop width is proportional to the real crop width.
+ * The real crop with = sensorWidth/ zoomRatio, but we need the ratio only so we can
+ * assume sensorWidth as 1.0f.
+ */
+ val relativeCropWidthInMaxZoom = 1.0f / maxZoomRatio
+ val relativeCropWidthInMinZoom = 1.0f / minZoomRatio
+
+ val cropWidth = relativeCropWidthInMinZoom -
+ (relativeCropWidthInMinZoom - relativeCropWidthInMaxZoom) * linearZoom
+
+ val ratio = 1.0f / cropWidth
+
+ return MathUtils.clamp(ratio, minZoomRatio, maxZoomRatio)
+ }
+
+ private fun areFloatsEqual(num1: Float, num2: Float): Boolean {
+ return nearZero(num1 - num2)
+ }
+
+ private fun nearZero(num: Float): Boolean {
+ return abs(num) < 2.0 * Math.ulp(abs(num))
+ }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControl.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControl.kt
index 35d0833..4d669ef 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControl.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControl.kt
@@ -69,7 +69,7 @@
_useCaseCamera?.also {
requestListener.removeListener(compat)
requestListener.addListener(compat, threads.sequentialExecutor)
- compat.applyAsync(it)
+ compat.applyAsync(it, false)
}
}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapterTest.kt
index fe14c55..685eb31 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapterTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraInfoAdapterTest.kt
@@ -98,12 +98,12 @@
// if useCaseCamera is null, zoom setting operation will be cancelled
zoomControl.useCaseCamera = FakeUseCaseCamera()
- zoomControl.setZoomRatioAsync(3.0f)[3, TimeUnit.SECONDS]
+ val expectedZoomState = ZoomValue(3.0f, 1.0f, 10.0f)
+ zoomControl.setZoomValue(expectedZoomState)[3, TimeUnit.SECONDS]
- // minZoom and maxZoom will be set as 0 due to FakeZoomCompat using those values
- assertWithMessage("zoomState did not return default zoom ratio successfully")
+ assertWithMessage("zoomState did not return the correct zoom state successfully")
.that(currentZoomState)
- .isEqualTo(ZoomValue(3.0f, zoomControl.minZoom, zoomControl.maxZoom))
+ .isEqualTo(expectedZoomState)
}
@Test
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapterTest.kt
new file mode 100644
index 0000000..87533ee
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CoroutineAdapterTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 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.camera.camera2.pipe.integration.adapter
+
+import android.os.Build
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+@DoNotInstrument
+class CoroutineAdapterTest {
+ @Test
+ fun propagateCompleteResult(): Unit = runBlocking {
+ // Arrange.
+ val resultValue = 123
+ val sourceDeferred = CompletableDeferred<Int>()
+ val resultDeferred = CompletableDeferred<Int>()
+ sourceDeferred.propagateTo(resultDeferred)
+
+ // Act.
+ sourceDeferred.complete(resultValue)
+
+ // Assert.
+ assertThat(resultDeferred.await()).isEqualTo(resultValue)
+ }
+
+ @Test
+ fun propagateCancelResult() {
+ // Arrange.
+ val sourceDeferred = CompletableDeferred<Unit>()
+ val resultDeferred = CompletableDeferred<Unit>()
+ sourceDeferred.propagateTo(resultDeferred)
+
+ // Act.
+ sourceDeferred.cancel()
+
+ // Assert.
+ assertThat(resultDeferred.isCancelled).isTrue()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun propagateExceptionResult() {
+ // Arrange.
+ val sourceDeferred = CompletableDeferred<Unit>()
+ val resultDeferred = CompletableDeferred<Unit>()
+ sourceDeferred.propagateTo(resultDeferred)
+ val testThrowable = Throwable()
+
+ // Act.
+ sourceDeferred.completeExceptionally(testThrowable)
+
+ // Assert.
+ assertThat(resultDeferred.getCompletionExceptionOrNull()).isSameInstanceAs(testThrowable)
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
index 157d7a7..d1c277d 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/FocusMeteringControlTest.kt
@@ -29,6 +29,7 @@
import android.util.Size
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.Result3A
+import androidx.camera.camera2.pipe.integration.compat.ZoomCompat
import androidx.camera.camera2.pipe.integration.impl.CameraProperties
import androidx.camera.camera2.pipe.integration.impl.FocusMeteringControl
import androidx.camera.camera2.pipe.integration.impl.State3AControl
@@ -37,6 +38,7 @@
import androidx.camera.camera2.pipe.integration.impl.UseCaseThreads
import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraRequestControl
+import androidx.camera.camera2.pipe.integration.testing.FakeZoomCompat
import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
import androidx.camera.camera2.pipe.testing.FakeFrameMetadata
import androidx.camera.core.CameraControl
@@ -409,6 +411,82 @@
}
@Test
+ fun cropRegionIsSet_resultBasedOnCropRegion() {
+ val cropWidth = 480
+ val cropHeight = 360
+ val cropRect = Rect(
+ SENSOR_WIDTH / 2 - cropWidth / 2,
+ SENSOR_HEIGHT / 2 - cropHeight / 2,
+ SENSOR_WIDTH / 2 + cropWidth / 2, SENSOR_HEIGHT / 2 + cropHeight / 2
+ )
+
+ focusMeteringControl = initFocusMeteringControl(
+ cameraId = CAMERA_ID_0,
+ zoomCompat = FakeZoomCompat(croppedSensorArea = cropRect),
+ )
+
+ val centerPt = pointFactory.createPoint(0.5f, 0.5f)
+ startFocusMeteringAndAwait(
+ FocusMeteringAction.Builder(centerPt).build()
+ )
+
+ val areaWidth = (MeteringPointFactory.getDefaultPointSize() * cropRect.width()).toInt()
+ val areaHeight = (MeteringPointFactory.getDefaultPointSize() * cropRect.height()).toInt()
+ val adjustedRect = Rect(
+ cropRect.centerX() - areaWidth / 2,
+ cropRect.centerY() - areaHeight / 2,
+ cropRect.centerX() + areaWidth / 2,
+ cropRect.centerY() + areaHeight / 2
+ )
+ with(fakeRequestControl.focusMeteringCalls.last()) {
+ assertWithMessage("Wrong number of AF regions").that(afRegions.size).isEqualTo(1)
+ assertWithMessage("Wrong AF region")
+ .that(afRegions[0].rect).isEqualTo(adjustedRect)
+ }
+ }
+
+ @Test
+ fun cropRegionIsSetTwice_resultAlwaysBasedOnCurrentCropRegion() {
+ val cropWidth = 480
+ val cropHeight = 360
+ val cropRect = Rect(
+ SENSOR_WIDTH / 2 - cropWidth / 2,
+ SENSOR_HEIGHT / 2 - cropHeight / 2,
+ SENSOR_WIDTH / 2 + cropWidth / 2, SENSOR_HEIGHT / 2 + cropHeight / 2
+ )
+
+ val zoomCompat = FakeZoomCompat(croppedSensorArea = Rect(0, 0, 640, 480))
+ focusMeteringControl = initFocusMeteringControl(
+ cameraId = CAMERA_ID_0,
+ zoomCompat = zoomCompat,
+ )
+
+ val centerPt = pointFactory.createPoint(0.5f, 0.5f)
+ startFocusMeteringAndAwait(
+ FocusMeteringAction.Builder(centerPt).build()
+ )
+
+ zoomCompat.croppedSensorArea = cropRect
+ startFocusMeteringAndAwait(
+ FocusMeteringAction.Builder(centerPt).build()
+ )
+
+ val areaWidth = (MeteringPointFactory.getDefaultPointSize() * cropRect.width()).toInt()
+ val areaHeight = (MeteringPointFactory.getDefaultPointSize() * cropRect.height()).toInt()
+ val adjustedRect = Rect(
+ cropRect.centerX() - areaWidth / 2,
+ cropRect.centerY() - areaHeight / 2,
+ cropRect.centerX() + areaWidth / 2,
+ cropRect.centerY() + areaHeight / 2
+ )
+ with(fakeRequestControl.focusMeteringCalls.last()) {
+ assertWithMessage("Wrong number of AF regions").that(afRegions.size).isEqualTo(1)
+ assertWithMessage("Wrong AF region")
+ .that(afRegions[0].rect).isEqualTo(adjustedRect)
+ }
+ }
+
+ @Test
fun previewFovAdjusted_16by9_to_4by3() {
// use 16:9 preview aspect ratio with sensor region of 4:3 (camera 0)
focusMeteringControl = initFocusMeteringControl(
@@ -431,8 +509,9 @@
fun previewFovAdjusted_4by3_to_16by9() {
// use 4:3 preview aspect ratio with sensor region of 16:9 (camera 1)
focusMeteringControl = initFocusMeteringControl(
- CAMERA_ID_1,
- setOf(createPreview(Size(640, 480))),
+ cameraId = CAMERA_ID_1,
+ useCases = setOf(createPreview(Size(640, 480))),
+ zoomCompat = FakeZoomCompat(croppedSensorArea = Rect(0, 0, 1920, 1080))
)
startFocusMeteringAndAwait(
@@ -1031,7 +1110,6 @@
// - [b/255679866] triggerAfWithTemplate, triggerAePrecaptureWithTemplate,
// cancelAfAeTriggerWithTemplate
// - startFocusAndMetering_AfRegionCorrectedByQuirk
- // - [b/262225455] cropRegionIsSet_resultBasedOnCropRegion
private fun assertFutureFocusCompleted(
future: ListenableFuture<FocusMeteringResult>,
@@ -1126,10 +1204,12 @@
useCases: Set<UseCase> = emptySet(),
useCaseThreads: UseCaseThreads = fakeUseCaseThreads,
state3AControl: State3AControl = createState3AControl(cameraId),
+ zoomCompat: ZoomCompat = FakeZoomCompat()
) = FocusMeteringControl(
cameraPropertiesMap[cameraId]!!,
state3AControl,
- useCaseThreads
+ useCaseThreads,
+ zoomCompat
).apply {
fakeUseCaseCamera.runningUseCases = useCases
useCaseCamera = fakeUseCaseCamera
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
index 59295e2..23571ca 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/SupportedSurfaceCombinationTest.kt
@@ -21,7 +21,10 @@
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.hardware.camera2.params.StreamConfigurationMap
-import android.media.CamcorderProfile
+import android.media.CamcorderProfile.QUALITY_1080P
+import android.media.CamcorderProfile.QUALITY_2160P
+import android.media.CamcorderProfile.QUALITY_480P
+import android.media.CamcorderProfile.QUALITY_720P
import android.media.MediaRecorder
import android.os.Build
import android.util.Pair
@@ -50,8 +53,9 @@
import androidx.camera.core.Preview
import androidx.camera.core.SurfaceRequest
import androidx.camera.core.UseCase
-import androidx.camera.core.impl.CamcorderProfileProxy
import androidx.camera.core.impl.CameraThreadConfig
+import androidx.camera.core.impl.EncoderProfilesProxy
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy
import androidx.camera.core.impl.MutableStateObservable
import androidx.camera.core.impl.Observable
import androidx.camera.core.impl.StreamSpec
@@ -61,16 +65,15 @@
import androidx.camera.core.impl.UseCaseConfigFactory
import androidx.camera.core.impl.utils.CompareSizesByArea
import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import androidx.camera.testing.CamcorderProfileUtil
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraXUtil
import androidx.camera.testing.Configs
+import androidx.camera.testing.EncoderProfilesUtil
import androidx.camera.testing.SurfaceTextureProvider
-import androidx.camera.testing.SurfaceTextureProvider.SurfaceTextureCallback
-import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeEncoderProfilesProvider
import androidx.camera.testing.fakes.FakeUseCaseConfig
import androidx.camera.video.FallbackStrategy
import androidx.camera.video.MediaSpec
@@ -125,20 +128,17 @@
private val legacyVideoMaximumVideoSize = Size(1920, 1080)
private val mod16Size = Size(960, 544)
private val mod16SizeStreamSpec = StreamSpec.builder(mod16Size).build()
- private val profileUhd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_2160P, recordSize.width, recordSize
- .height
+ private val profileUhd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ recordSize.width, recordSize.height
)
- private val profileFhd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_1080P, 1920, 1080
+ private val profileFhd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ 1920, 1080
)
- private val profileHd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_720P, previewSize.width, previewSize
- .height
+ private val profileHd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ previewSize.width, previewSize.height
)
- private val profileSd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_480P, vgaSize.width,
- vgaSize.height
+ private val profileSd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ vgaSize.width, vgaSize.height
)
private val supportedSizes = arrayOf(
Size(4032, 3024), // 4:3
@@ -161,8 +161,9 @@
private lateinit var fakeCameraMetadata: FakeCameraMetadata
private val mockCameraAppComponent: CameraAppComponent = mock()
- private val mockCamcorderProfileAdapter: CamcorderProfileProviderAdapter = mock()
- private val mockCamcorderProxy: CamcorderProfileProxy = mock()
+ private val mockEncoderProfilesAdapter: EncoderProfilesProviderAdapter = mock()
+ private val mockEncoderProfilesProxy: EncoderProfilesProxy = mock()
+ private val mockVideoProfileProxy: VideoProfileProxy = mock()
@Before
fun setUp() {
@@ -172,12 +173,12 @@
displaySize
.height
)
- whenever(mockCamcorderProfileAdapter.hasProfile(ArgumentMatchers.anyInt()))
- .thenReturn(true)
- whenever(mockCamcorderProxy.videoFrameWidth).thenReturn(3840)
- whenever(mockCamcorderProxy.videoFrameHeight).thenReturn(2160)
- whenever(mockCamcorderProfileAdapter[ArgumentMatchers.anyInt()])
- .thenReturn(mockCamcorderProxy)
+ whenever(mockEncoderProfilesAdapter.hasProfile(ArgumentMatchers.anyInt())).thenReturn(true)
+ whenever(mockVideoProfileProxy.width).thenReturn(3840)
+ whenever(mockVideoProfileProxy.height).thenReturn(2160)
+ whenever(mockEncoderProfilesProxy.videoProfiles).thenReturn(listOf(mockVideoProfileProxy))
+ whenever(mockEncoderProfilesAdapter.getAll(ArgumentMatchers.anyInt()))
+ .thenReturn(mockEncoderProfilesProxy)
}
@After
@@ -190,7 +191,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLegacySupportedCombinationList()
for (combination in combinationList) {
@@ -205,7 +206,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLegacySupportedCombinationList()
val isSupported = isAllSubConfigListSupported(supportedSurfaceCombination, combinationList)
@@ -217,7 +218,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLimitedSupportedCombinationList()
for (combination in combinationList) {
@@ -232,7 +233,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getFullSupportedCombinationList()
for (combination in combinationList) {
@@ -247,7 +248,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLevel3SupportedCombinationList()
for (combination in combinationList) {
@@ -262,7 +263,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLimitedSupportedCombinationList()
for (combination in combinationList) {
@@ -277,7 +278,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLimitedSupportedCombinationList()
val isSupported = isAllSubConfigListSupported(supportedSurfaceCombination, combinationList)
@@ -289,7 +290,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getFullSupportedCombinationList()
for (combination in combinationList) {
@@ -304,7 +305,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLevel3SupportedCombinationList()
for (combination in combinationList) {
@@ -319,7 +320,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getFullSupportedCombinationList()
for (combination in combinationList) {
@@ -334,7 +335,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getFullSupportedCombinationList()
val isSupported = isAllSubConfigListSupported(supportedSurfaceCombination, combinationList)
@@ -346,7 +347,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLevel3SupportedCombinationList()
for (combination in combinationList) {
@@ -365,7 +366,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLimitedSupportedCombinationList()
for (combination in combinationList) {
@@ -384,7 +385,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLegacySupportedCombinationList()
for (combination in combinationList) {
@@ -403,7 +404,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getFullSupportedCombinationList()
for (combination in combinationList) {
@@ -422,7 +423,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getRAWSupportedCombinationList()
for (combination in combinationList) {
@@ -437,7 +438,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLevel3SupportedCombinationList()
for (combination in combinationList) {
@@ -452,7 +453,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val combinationList = getLevel3SupportedCombinationList()
val isSupported = isAllSubConfigListSupported(supportedSurfaceCombination, combinationList)
@@ -464,7 +465,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val fakeUseCase = FakeUseCaseConfig.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -499,7 +500,7 @@
.build()
preview.setSurfaceProvider(
CameraXExecutors.directExecutor(),
- SurfaceTextureProvider.createSurfaceTextureProvider(mock<SurfaceTextureCallback>())
+ SurfaceTextureProvider.createSurfaceTextureProvider(mock())
)
val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -540,12 +541,12 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val preview = Preview.Builder().build()
preview.setSurfaceProvider(
CameraXExecutors.directExecutor(),
- SurfaceTextureProvider.createSurfaceTextureProvider(mock<SurfaceTextureCallback>())
+ SurfaceTextureProvider.createSurfaceTextureProvider(mock())
)
val imageCapture = ImageCapture.Builder().build()
val imageAnalysis = ImageAnalysis.Builder().build()
@@ -610,7 +611,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
/* This test case is for b/139018208 that get small resolution 144x256 with below
@@ -658,7 +659,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Sets each of mSupportedSizes as target resolution and also sets target rotation as
@@ -685,7 +686,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Sets target resolution as 1280x640, all supported resolutions will be put into aspect
@@ -709,7 +710,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -740,7 +741,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Legacy camera only support (PRIV, PREVIEW) + (PRIV, PREVIEW)
@@ -774,7 +775,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -818,7 +819,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -869,7 +870,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_4_3) // mMaximumSize(4032x3024) is 4:3
@@ -919,7 +920,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
/* This test case is for b/132603284 that divide by zero issue crash happened in below
@@ -1007,7 +1008,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val formatResolutionsPairList: MutableList<Pair<Int, Array<Size>>> = ArrayList()
formatResolutionsPairList.add(Pair.create(ImageFormat.JPEG, arrayOf(vgaSize)))
@@ -1059,7 +1060,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.YUV_420_888, vgaSize
@@ -1074,7 +1075,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.YUV_420_888, previewSize
@@ -1089,7 +1090,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.YUV_420_888, recordSize
@@ -1104,7 +1105,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.YUV_420_888, maximumSize
@@ -1119,7 +1120,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.JPEG, vgaSize
@@ -1134,7 +1135,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.JPEG, previewSize
@@ -1149,7 +1150,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.JPEG, recordSize
@@ -1164,7 +1165,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val surfaceConfig = supportedSurfaceCombination.transformSurfaceConfig(
ImageFormat.JPEG, maximumSize
@@ -1179,7 +1180,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val maximumYUVSize =
supportedSurfaceCombination.getMaxOutputSizeByFormat(ImageFormat.YUV_420_888)
@@ -1194,7 +1195,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val preview = Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
@@ -1256,7 +1257,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().build()
@@ -1285,7 +1286,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3)
.build()
@@ -1319,7 +1320,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(
AspectRatio.RATIO_16_9
@@ -1354,7 +1355,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(1080, 1920)
@@ -1391,7 +1392,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetRotation(
Surface.ROTATION_90
@@ -1427,7 +1428,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetRotation(
Surface.ROTATION_90
@@ -1458,7 +1459,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetRotation(
Surface.ROTATION_90
@@ -1491,7 +1492,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(1280, 600)
@@ -1521,7 +1522,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(Size(1280, 720)).build()
@@ -1545,7 +1546,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val customOrderedResolutions = listOf(
Size(640, 480),
@@ -1583,7 +1584,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setDefaultResolution(
Size(
@@ -1613,7 +1614,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setDefaultResolution(
Size(1280, 720)
@@ -1657,7 +1658,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(1920, 1080)
@@ -1685,7 +1686,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(320, 240)
@@ -1718,7 +1719,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(320, 180)
@@ -1753,7 +1754,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(320, 240)
@@ -1782,7 +1783,7 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(1920, 1080)
@@ -1826,7 +1827,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(320, 200)
@@ -1861,7 +1862,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(192, 144)
@@ -1893,7 +1894,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setMaxResolution(
Size(192, 144)
@@ -1919,7 +1920,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(185, 90)
@@ -1959,7 +1960,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetResolution(
Size(1080, 2016)
@@ -2000,7 +2001,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(
AspectRatio.RATIO_16_9
@@ -2050,7 +2051,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(
AspectRatio.RATIO_16_9
@@ -2087,7 +2088,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(
AspectRatio.RATIO_16_9
@@ -2135,7 +2136,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val useCase = FakeUseCaseConfig.Builder().setTargetAspectRatio(
AspectRatio.RATIO_16_9
@@ -2172,7 +2173,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Checks the determined RECORD size
@@ -2201,7 +2202,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Sets the target resolution as 640x480 with target rotation as ROTATION_90 because the
@@ -2229,7 +2230,7 @@
)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
// Sets the max resolution as 720x1280
@@ -2250,13 +2251,13 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val preview = Preview.Builder().build()
preview.setSurfaceProvider(
CameraXExecutors.directExecutor(),
SurfaceTextureProvider.createSurfaceTextureProvider(
- mock<SurfaceTextureCallback>()
+ mock()
)
)
@@ -2299,13 +2300,13 @@
setupCamera(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
val supportedSurfaceCombination = SupportedSurfaceCombination(
context, fakeCameraMetadata,
- mockCamcorderProfileAdapter
+ mockEncoderProfilesAdapter
)
val preview = Preview.Builder().build()
preview.setSurfaceProvider(
CameraXExecutors.directExecutor(),
SurfaceTextureProvider.createSurfaceTextureProvider(
- mock<SurfaceTextureCallback>()
+ mock()
)
)
@@ -2428,15 +2429,12 @@
CameraCharacteristics.LENS_FACING_BACK
)
val cameraInfo = FakeCameraInfoInternal(fakeCameraMetadata.camera.value)
- cameraInfo.camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
- .addProfile(
- CamcorderProfileUtil.asHighQuality(profileUhd),
- profileUhd,
- profileFhd,
- profileHd,
- profileSd,
- CamcorderProfileUtil.asLowQuality(profileSd)
- ).build()
+ cameraInfo.encoderProfilesProvider = FakeEncoderProfilesProvider.Builder()
+ .add(QUALITY_2160P, profileUhd)
+ .add(QUALITY_1080P, profileFhd)
+ .add(QUALITY_720P, profileHd)
+ .add(QUALITY_480P, profileSd)
+ .build()
cameraFactory!!.insertCamera(
lensFacingEnum, fakeCameraMetadata.camera.value
) { FakeCamera(fakeCameraMetadata.camera.value, null, cameraInfo) }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/EvCompControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/EvCompControlTest.kt
index d1c5f1c..59d5f6e 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/EvCompControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/EvCompControlTest.kt
@@ -17,17 +17,26 @@
package androidx.camera.camera2.pipe.integration.impl
import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.CaptureResult
import android.os.Build
import android.util.Range
import android.util.Rational
+import androidx.camera.camera2.pipe.FrameNumber
+import androidx.camera.camera2.pipe.RequestNumber
import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
import androidx.camera.camera2.pipe.integration.compat.EvCompImpl
import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCamera
import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+import androidx.camera.camera2.pipe.testing.FakeFrameInfo
+import androidx.camera.camera2.pipe.testing.FakeFrameMetadata
+import androidx.camera.camera2.pipe.testing.FakeRequestMetadata
import androidx.camera.core.CameraControl
import androidx.testutils.assertThrows
import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
@@ -39,8 +48,6 @@
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import org.robolectric.annotation.internal.DoNotInstrument
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
@RunWith(RobolectricCameraPipeTestRunner::class)
@DoNotInstrument
@@ -146,9 +153,68 @@
}
}
+ @Test
+ fun useCaseCameraUpdated_setExposureResultShouldPropagate(): Unit = runBlocking {
+ val targetEv = 1
+ val deferred = exposureControl.updateAsync(targetEv)
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ exposureControl.useCaseCamera = FakeUseCaseCamera()
+ comboRequestListener.simulateAeConverge(exposureValue = targetEv)
+
+ // Assert. The setEV task should be completed.
+ assertThat(deferred.awaitWithTimeout()).isEqualTo(targetEv)
+ }
+
+ @Test
+ fun useCaseCameraUpdated_onlyCompleteLatestRequest(): Unit = runBlocking {
+ val targetEv = 2
+ val deferred = exposureControl.updateAsync(1)
+
+ // Act. Simulate the UseCaseCamera is recreated,
+ exposureControl.useCaseCamera = FakeUseCaseCamera()
+ // Act. Submits a new EV value.
+ val deferred2 = exposureControl.updateAsync(targetEv)
+ comboRequestListener.simulateAeConverge(exposureValue = targetEv)
+
+ // Assert. The previous setEV task should be cancelled
+ assertThrows<CameraControl.OperationCanceledException> {
+ deferred.awaitWithTimeout()
+ }
+ // Assert. The latest setEV task should be completed.
+ assertThat(deferred2.awaitWithTimeout()).isEqualTo(targetEv)
+ }
+
private suspend fun Deferred<Int>.awaitWithTimeout(
timeMillis: Long = TimeUnit.SECONDS.toMillis(5)
) = withTimeout(timeMillis) {
await()
}
+
+ private fun ComboRequestListener.simulateAeConverge(
+ exposureValue: Int,
+ frameNumber: FrameNumber = FrameNumber(101L),
+ ) {
+ val requestMetadata = FakeRequestMetadata(
+ requestParameters = mapOf(
+ CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION to exposureValue
+ ),
+ requestNumber = RequestNumber(1)
+ )
+ val resultMetaData = FakeFrameMetadata(
+ resultMetadata = mapOf(
+ CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION to exposureValue,
+ CaptureResult.CONTROL_AE_STATE to CaptureResult.CONTROL_AE_STATE_CONVERGED,
+ ),
+ frameNumber = frameNumber,
+ )
+ fakeUseCaseThreads.sequentialExecutor.execute {
+ onComplete(
+ requestMetadata, frameNumber, FakeFrameInfo(
+ metadata = resultMetaData,
+ requestMetadata = requestMetadata,
+ )
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/FlashControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/FlashControlTest.kt
new file mode 100644
index 0000000..e3559f1
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/FlashControlTest.kt
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2023 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.camera.camera2.pipe.integration.impl
+
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CaptureRequest
+import android.os.Build
+import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
+import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCamera
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraRequestControl
+import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+import androidx.camera.core.CameraControl
+import androidx.camera.core.ImageCapture
+import androidx.testutils.assertThrows
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class FlashControlTest {
+ private val fakeUseCaseThreads by lazy {
+ val executor = MoreExecutors.directExecutor()
+ val dispatcher = executor.asCoroutineDispatcher()
+ val cameraScope = CoroutineScope(Job() + dispatcher)
+
+ UseCaseThreads(
+ cameraScope,
+ executor,
+ dispatcher,
+ )
+ }
+ private val metadata = FakeCameraMetadata(
+ mapOf(
+ CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES to intArrayOf(
+ CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH,
+ CaptureRequest.CONTROL_AE_MODE_ON,
+ CaptureRequest.CONTROL_AE_MODE_OFF,
+ CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH
+ ),
+ ),
+ )
+ private val fakeRequestControl = FakeUseCaseCameraRequestControl()
+ private val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+ private val state3AControl = State3AControl(FakeCameraProperties(metadata)).apply {
+ useCaseCamera = fakeUseCaseCamera
+ }
+ private lateinit var flashControl: FlashControl
+
+ @Before
+ fun setUp() {
+ flashControl = FlashControl(
+ state3AControl = state3AControl,
+ threads = fakeUseCaseThreads,
+ )
+ flashControl.useCaseCamera = fakeUseCaseCamera
+ }
+
+ @Test
+ fun setFlash_whenInactive(): Unit = runBlocking {
+ val fakeUseCaseCamera = FakeUseCaseCamera()
+ val fakeCameraProperties = FakeCameraProperties()
+
+ val flashControl = FlashControl(
+ State3AControl(fakeCameraProperties).apply {
+ useCaseCamera = fakeUseCaseCamera
+ },
+ fakeUseCaseThreads,
+ )
+
+ assertThrows<CameraControl.OperationCanceledException> {
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON).awaitWithTimeout()
+ }
+ }
+
+ @Test
+ fun setFlash_flashModeOn(): Unit = runBlocking {
+ // Arrange, clear data of the initial invocations.
+ fakeRequestControl.addParameterCalls.clear()
+
+ // Act.
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON).awaitWithTimeout()
+
+ // Assert. AE mode should change accordingly.
+ assertThat(fakeRequestControl.addParameterCalls).hasSize(1)
+ assertThat(fakeRequestControl.addParameterCalls[0]).containsAtLeastEntriesIn(
+ mapOf(CaptureRequest.CONTROL_AE_MODE to CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH)
+ )
+ }
+
+ @Test
+ fun setFlash_flashModeAuto(): Unit = runBlocking {
+ // Arrange, clear data of the initial invocations.
+ fakeRequestControl.addParameterCalls.clear()
+
+ // Act.
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_AUTO).awaitWithTimeout()
+
+ // Assert. AE mode should change accordingly.
+ assertThat(fakeRequestControl.addParameterCalls).hasSize(1)
+ assertThat(fakeRequestControl.addParameterCalls[0]).containsAtLeastEntriesIn(
+ mapOf(CaptureRequest.CONTROL_AE_MODE to CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
+ )
+ }
+
+ @Test
+ fun setFlash_flashModeOnThenOff(): Unit = runBlocking {
+ // Arrange, clear data of the initial invocations.
+ fakeRequestControl.addParameterCalls.clear()
+
+ // Act.
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON).awaitWithTimeout()
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_OFF).awaitWithTimeout()
+
+ // Assert. AE mode should change accordingly.
+ assertThat(fakeRequestControl.addParameterCalls).hasSize(2)
+ assertThat(fakeRequestControl.addParameterCalls[0]).containsAtLeastEntriesIn(
+ mapOf(CaptureRequest.CONTROL_AE_MODE to CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH)
+ )
+ assertThat(fakeRequestControl.addParameterCalls[1]).containsAtLeastEntriesIn(
+ mapOf(CaptureRequest.CONTROL_AE_MODE to CaptureRequest.CONTROL_AE_MODE_ON)
+ )
+ }
+
+ @Test
+ fun setFlashTwice_cancelPreviousFuture(): Unit = runBlocking {
+ // Arrange. Set a never complete deferred.
+ fakeRequestControl.addParameterResult = CompletableDeferred()
+
+ // Act. call setFlashAsync twice.
+ val deferred = flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+
+ assertThrows<CameraControl.OperationCanceledException> {
+ deferred.awaitWithTimeout()
+ }
+ }
+
+ @Test
+ fun setInActive_cancelPreviousFuture(): Unit = runBlocking {
+ // Arrange. Set a never complete deferred.
+ fakeRequestControl.addParameterResult = CompletableDeferred()
+ val deferred = flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+
+ // Act. call reset & clear the UseCaseCamera.
+ flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+ flashControl.reset()
+ flashControl.useCaseCamera = null
+
+ assertThrows<CameraControl.OperationCanceledException> {
+ deferred.awaitWithTimeout()
+ }
+ }
+
+ @Test
+ fun useCaseCameraUpdated_setFlashResultShouldPropagate(): Unit = runBlocking {
+ // Arrange.
+ fakeRequestControl.addParameterResult = CompletableDeferred()
+
+ val deferred = flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ addParameterResult = CompletableDeferred()
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ flashControl.useCaseCamera = fakeUseCaseCamera
+ state3AControl.useCaseCamera = fakeUseCaseCamera
+
+ // Simulate setFlash is completed on the recreated UseCaseCamera
+ fakeRequestControl.addParameterResult.complete(Unit)
+
+ // Assert. The setFlash task should be completed.
+ assertThat(deferred.awaitWithTimeout()).isNotNull()
+ }
+
+ @Test
+ fun useCaseCameraUpdated_onlyCompleteLatestRequest(): Unit = runBlocking {
+ // Arrange.
+ fakeRequestControl.addParameterResult = CompletableDeferred()
+
+ val deferred = flashControl.setFlashAsync(ImageCapture.FLASH_MODE_ON)
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ addParameterResult = CompletableDeferred()
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ flashControl.useCaseCamera = fakeUseCaseCamera
+ state3AControl.useCaseCamera = fakeUseCaseCamera
+ // Act. Submits a new Flash mode.
+ val deferred2 = flashControl.setFlashAsync(ImageCapture.FLASH_MODE_AUTO)
+ // Simulate setFlash is completed on the recreated UseCaseCamera
+ fakeRequestControl.addParameterResult.complete(Unit)
+
+ // Assert. The previous set Flash mode task should be cancelled
+ assertThrows<CameraControl.OperationCanceledException> {
+ deferred.awaitWithTimeout()
+ }
+ // Assert. The latest set Flash mode task should be completed.
+ assertThat(deferred2.awaitWithTimeout()).isNotNull()
+ }
+
+ private suspend fun <T> Deferred<T>.awaitWithTimeout(
+ timeMillis: Long = TimeUnit.SECONDS.toMillis(5)
+ ) = withTimeout(timeMillis) {
+ await()
+ }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/TorchControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/TorchControlTest.kt
index 6b24bc2..8aeaf43 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/TorchControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/TorchControlTest.kt
@@ -17,29 +17,23 @@
package androidx.camera.camera2.pipe.integration.impl
import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.CaptureRequest
-import android.hardware.camera2.params.MeteringRectangle
import android.os.Build
-import androidx.camera.camera2.pipe.AeMode
-import androidx.camera.camera2.pipe.Request
-import androidx.camera.camera2.pipe.RequestTemplate
import androidx.camera.camera2.pipe.Result3A
-import androidx.camera.camera2.pipe.StreamId
import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCamera
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraRequestControl
import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
import androidx.camera.core.CameraControl
import androidx.camera.core.TorchState
-import androidx.camera.core.impl.CaptureConfig
-import androidx.camera.core.impl.SessionConfig
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.testutils.assertThrows
import com.google.common.truth.Truth
+import com.google.common.util.concurrent.MoreExecutors
import java.util.Objects
-import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
@@ -48,7 +42,7 @@
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import org.junit.AfterClass
+import kotlinx.coroutines.withTimeout
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,7 +56,7 @@
class TorchControlTest {
companion object {
- private val executor = Executors.newSingleThreadExecutor()
+ private val executor = MoreExecutors.directExecutor()
private val fakeUseCaseThreads by lazy {
val dispatcher = executor.asCoroutineDispatcher()
val cameraScope = CoroutineScope(Job() + dispatcher)
@@ -73,12 +67,6 @@
dispatcher
)
}
-
- @JvmStatic
- @AfterClass
- fun close() {
- executor.shutdown()
- }
}
private val metadata = FakeCameraMetadata(
@@ -87,60 +75,9 @@
),
)
- private val neverCompleteTorchRequestControl = object : UseCaseCameraRequestControl {
- override fun addParametersAsync(
- type: UseCaseCameraRequestControl.Type,
- values: Map<CaptureRequest.Key<*>, Any>,
- optionPriority: androidx.camera.core.impl.Config.OptionPriority,
- tags: Map<String, Any>,
- streams: Set<StreamId>?,
- template: RequestTemplate?,
- listeners: Set<Request.Listener>
- ): Deferred<Unit> {
- return CompletableDeferred(Unit)
- }
-
- override fun setConfigAsync(
- type: UseCaseCameraRequestControl.Type,
- config: androidx.camera.core.impl.Config?,
- tags: Map<String, Any>,
- streams: Set<StreamId>?,
- template: RequestTemplate?,
- listeners: Set<Request.Listener>
- ): Deferred<Unit> {
- return CompletableDeferred(Unit)
- }
-
- override fun setSessionConfigAsync(sessionConfig: SessionConfig): Deferred<Unit> {
- return CompletableDeferred(Unit)
- }
-
- override suspend fun setTorchAsync(enabled: Boolean): Deferred<Result3A> {
- // Return a CompletableDeferred without set it to completed.
- return CompletableDeferred()
- }
-
- override suspend fun startFocusAndMeteringAsync(
- aeRegions: List<MeteringRectangle>,
- afRegions: List<MeteringRectangle>,
- awbRegions: List<MeteringRectangle>,
- afTriggerStartAeMode: AeMode?
- ): Deferred<Result3A> {
- return CompletableDeferred(Result3A(status = Result3A.Status.OK))
- }
-
- override suspend fun cancelFocusAndMeteringAsync(): Deferred<Result3A> {
- return CompletableDeferred(Result3A(status = Result3A.Status.OK))
- }
-
- override suspend fun issueSingleCaptureAsync(
- captureSequence: List<CaptureConfig>,
- captureMode: Int,
- flashType: Int,
- flashMode: Int,
- ): List<Deferred<Void?>> {
- return listOf(CompletableDeferred(null))
- }
+ private val neverCompleteTorchRequestControl = FakeUseCaseCameraRequestControl().apply {
+ // Set a CompletableDeferred without set it to completed.
+ setTorchResult = CompletableDeferred()
}
private lateinit var torchControl: TorchControl
@@ -309,4 +246,59 @@
Truth.assertThat(receivedTorchState[1]).isEqualTo(TorchState.ON) // by setTorchAsync(true)
Truth.assertThat(receivedTorchState[2]).isEqualTo(TorchState.OFF) // by setTorchAsync(false)
}
+
+ @Test
+ fun useCaseCameraUpdated_setTorchResultShouldPropagate(): Unit = runBlocking {
+ // Arrange.
+ torchControl.useCaseCamera =
+ FakeUseCaseCamera(requestControl = neverCompleteTorchRequestControl)
+
+ val deferred = torchControl.setTorchAsync(true)
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ setTorchResult = CompletableDeferred<Result3A>()
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ torchControl.useCaseCamera = fakeUseCaseCamera
+
+ // Simulate setTorch is completed in the recreated UseCaseCamera
+ fakeRequestControl.setTorchResult.complete(Result3A(status = Result3A.Status.OK))
+
+ // Assert. The setTorch task should be completed.
+ Truth.assertThat(deferred.awaitWithTimeout()).isNotNull()
+ }
+
+ @Test
+ fun useCaseCameraUpdated_onlyCompleteLatestRequest(): Unit = runBlocking {
+ // Arrange.
+ torchControl.useCaseCamera =
+ FakeUseCaseCamera(requestControl = neverCompleteTorchRequestControl)
+
+ val deferred = torchControl.setTorchAsync(true)
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ setTorchResult = CompletableDeferred()
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ torchControl.useCaseCamera = fakeUseCaseCamera
+ // Act. Set Torch mode again.
+ val deferred2 = torchControl.setTorchAsync(false)
+ // Simulate setTorch is completed in the recreated UseCaseCamera
+ fakeRequestControl.setTorchResult.complete(Result3A(status = Result3A.Status.OK))
+
+ // Assert. The previous setTorch task should be cancelled
+ assertThrows<CameraControl.OperationCanceledException> {
+ deferred.awaitWithTimeout()
+ }
+ // Assert. The latest setTorch task should be completed.
+ Truth.assertThat(deferred2.awaitWithTimeout()).isNotNull()
+ }
+
+ private suspend fun <T> Deferred<T>.awaitWithTimeout(
+ timeMillis: Long = TimeUnit.SECONDS.toMillis(5)
+ ) = withTimeout(timeMillis) {
+ await()
+ }
}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/ZoomControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/ZoomControlTest.kt
index 600f8ab..1abf1d4 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/ZoomControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/ZoomControlTest.kt
@@ -54,7 +54,7 @@
)
}
- private val zoomCompat = FakeZoomCompat()
+ private val zoomCompat = FakeZoomCompat(1.0f, 5.0f)
private lateinit var zoomControl: ZoomControl
@Before
@@ -66,9 +66,9 @@
@Test
fun canUpdateZoomRatioInCompat() {
- zoomControl.setZoomRatioAsync(3.0f)[3, TimeUnit.SECONDS]
+ zoomControl.setZoomRatio(3.0f)[3, TimeUnit.SECONDS]
- Truth.assertWithMessage("zoomState did not return default zoom state successfully")
+ Truth.assertWithMessage("zoomCompat not updated with correct zoom ratio")
.that(zoomCompat.zoomRatio)
.isEqualTo(3.0f)
}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/ZoomMathTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/ZoomMathTest.kt
new file mode 100644
index 0000000..f2fe667
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/ZoomMathTest.kt
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2023 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.camera.camera2.pipe.integration.internal
+
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getLinearZoomFromZoomRatio
+import androidx.camera.camera2.pipe.integration.internal.ZoomMath.getZoomRatioFromLinearZoom
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+private const val CROP_REGION_TOLERANCE = 5f
+class ZoomMathTest {
+ private val minZoomRatio = 0.6f
+ private val maxZoomRatio = 8f
+
+ @Test
+ fun getLinearZoomFromZoomRatio_zoomRatioIsMin_linearZoomIs0() {
+ val linearZoom = getLinearZoomFromZoomRatio(
+ zoomRatio = minZoomRatio,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ assertThat(linearZoom).isEqualTo(0f)
+ }
+
+ @Test
+ fun getLinearZoomFromZoomRatio_zoomRatioIsMax_linearZoomIs1() {
+ val linearZoom = getLinearZoomFromZoomRatio(
+ zoomRatio = maxZoomRatio,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ assertThat(linearZoom).isEqualTo(1f)
+ }
+
+ @Test
+ fun getLinearZoomFromZoomRatio_zoomUnsupported_linearZoomIs0() {
+ // zoom unsupported means minZoomRatio = maxZoomRatio
+ val linearZoom = getLinearZoomFromZoomRatio(
+ zoomRatio = 1.0f,
+ minZoomRatio = 1.0f,
+ maxZoomRatio = 1.0f
+ )
+
+ assertThat(linearZoom).isEqualTo(0f)
+ }
+
+ @Test
+ fun getZoomRatioFromLinearZoom_linearZoomIs0_zoomRatioIsMin() {
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 0f,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ assertThat(zoomRatio).isEqualTo(minZoomRatio)
+ }
+
+ @Test
+ fun getZoomRatioFromLinearZoom_linearZoomIs1_zoomRatioIsMax() {
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 1.0f,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ assertThat(zoomRatio).isEqualTo(maxZoomRatio)
+ }
+
+ @Test
+ fun getZoomRatioFromLinearZoom_zoomUnsupportedAndLinearZoom0_zoomRatioIsTheAllowedValue() {
+ // zoom unsupported means minZoomRatio = maxZoomRatio
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 0f,
+ minZoomRatio = 1.0f,
+ maxZoomRatio = 1.0f
+ )
+
+ assertThat(zoomRatio).isEqualTo(1.0f)
+ }
+
+ @Test
+ fun getZoomRatioFromLinearZoom_zoomUnsupportedAndLinearZoom0_5f_zoomRatioIsTheAllowedValue() {
+ // zoom unsupported means minZoomRatio = maxZoomRatio
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 0.5f,
+ minZoomRatio = 1.0f,
+ maxZoomRatio = 1.0f
+ )
+
+ assertThat(zoomRatio).isEqualTo(1.0f)
+ }
+
+ @Test
+ fun getZoomRatioFromLinearZoom_zoomUnsupportedAndLinearZoom1_zoomRatioIsTheAllowedValue() {
+ // zoom unsupported means minZoomRatio = maxZoomRatio
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 1.0f,
+ minZoomRatio = 1.0f,
+ maxZoomRatio = 1.0f
+ )
+
+ assertThat(zoomRatio).isEqualTo(1.0f)
+ }
+
+ @Test
+ fun getLinearZoomFromZoomRatio_getZoomRatioFromLinearZoomReturnsSameRatio() {
+ val linearZoom = getLinearZoomFromZoomRatio(
+ zoomRatio = 2f,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = linearZoom,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ assertThat(zoomRatio).isEqualTo(2f)
+ }
+
+ @Test
+ fun linearZoomIs0_5f_cropWidthIsHalf() {
+ val sensorRegionWidth = 10000f
+ val minZoomCropWidth = sensorRegionWidth / minZoomRatio
+ val maxZoomCropWidth = sensorRegionWidth / maxZoomRatio
+
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = 0.5f,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+ val cropWidth = sensorRegionWidth / zoomRatio
+
+ assertThat(cropWidth)
+ .isWithin(CROP_REGION_TOLERANCE)
+ .of((minZoomCropWidth + maxZoomCropWidth) / 2)
+ }
+
+ @Test
+ fun linearZoomIsIncreasedProgressively_cropWidthIsChangedLinearly() {
+ val sensorRegionWidth = 10000f
+ var previousCropWidth = sensorRegionWidth / minZoomRatio
+ var previousCropWidthDiff = Float.NaN
+
+ var linearZoom = 0.1f
+
+ while (linearZoom < 1f) {
+ val zoomRatio = getZoomRatioFromLinearZoom(
+ linearZoom = linearZoom,
+ minZoomRatio = minZoomRatio,
+ maxZoomRatio = maxZoomRatio
+ )
+
+ val cropWidth = sensorRegionWidth / zoomRatio
+ val cropWidthDiff = previousCropWidth - cropWidth
+
+ if (!previousCropWidthDiff.isNaN()) {
+ assertThat(cropWidthDiff)
+ .isWithin(CROP_REGION_TOLERANCE)
+ .of(previousCropWidthDiff)
+ }
+
+ previousCropWidthDiff = cropWidthDiff
+ previousCropWidth = cropWidth
+ linearZoom += 0.1f
+ }
+ }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControlTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControlTest.kt
index 5bcde30..efeb07f 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControlTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControlTest.kt
@@ -16,9 +16,36 @@
package androidx.camera.camera2.pipe.integration.interop
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.CaptureResult
import android.os.Build
+import androidx.camera.camera2.pipe.FrameNumber
+import androidx.camera.camera2.pipe.RequestNumber
import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
+import androidx.camera.camera2.pipe.integration.compat.Camera2CameraControlCompatImpl
+import androidx.camera.camera2.pipe.integration.impl.CAMERAX_TAG_BUNDLE
+import androidx.camera.camera2.pipe.integration.impl.ComboRequestListener
+import androidx.camera.camera2.pipe.integration.impl.UseCaseCameraRequestControl
+import androidx.camera.camera2.pipe.integration.impl.UseCaseThreads
+import androidx.camera.camera2.pipe.integration.impl.toParameters
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCamera
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraRequestControl
+import androidx.camera.camera2.pipe.testing.FakeFrameInfo
+import androidx.camera.camera2.pipe.testing.FakeFrameMetadata
+import androidx.camera.camera2.pipe.testing.FakeRequestMetadata
import androidx.camera.core.impl.CameraControlInternal
+import androidx.camera.core.impl.MutableTagBundle
+import androidx.testutils.assertThrows
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@@ -28,10 +55,147 @@
@OptIn(ExperimentalCamera2Interop::class)
class Camera2CameraControlTest {
+ private val fakeUseCaseThreads by lazy {
+ val executor = MoreExecutors.directExecutor()
+ val dispatcher = executor.asCoroutineDispatcher()
+ val cameraScope = CoroutineScope(Job() + dispatcher)
+
+ UseCaseThreads(
+ cameraScope,
+ executor,
+ dispatcher,
+ )
+ }
+ private val comboRequestListener = ComboRequestListener()
+ private val fakeRequestControl = FakeUseCaseCameraRequestControl()
+ private val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+ private val camera2CameraControlCompatImpl = Camera2CameraControlCompatImpl(fakeUseCaseThreads)
+ private lateinit var camera2CameraControl: Camera2CameraControl
+
+ @Before
+ fun setUp() {
+ camera2CameraControl = Camera2CameraControl.create(
+ compat = camera2CameraControlCompatImpl,
+ threads = fakeUseCaseThreads,
+ requestListener = comboRequestListener,
+ )
+ camera2CameraControl.useCaseCamera = fakeUseCaseCamera
+ }
+
+ @Test
+ fun useCaseCameraUpdated_setRequestOptionResultShouldPropagate(): Unit = runBlocking {
+ // Arrange.
+ val completeDeferred = CompletableDeferred<Unit>()
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ setConfigResult = completeDeferred
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ val resultFuture = camera2CameraControl.setCaptureRequestOptions(
+ CaptureRequestOptions.Builder().setCaptureRequestOption(
+ CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_OFF
+ ).build()
+ )
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ camera2CameraControl.useCaseCamera = fakeUseCaseCamera
+ // Simulate setRequestOption is completed in the recreated UseCaseCamera
+ completeDeferred.complete(Unit)
+ val requestsToCamera = fakeRequestControl.setConfigCalls.filter {
+ it.type == UseCaseCameraRequestControl.Type.CAMERA2_CAMERA_CONTROL
+ }.onEach { request ->
+ comboRequestListener.simulateRepeatingResult(
+ requests = request.config?.toParameters() ?: emptyMap(),
+ tags = request.tags,
+ )
+ }
+
+ // Assert. The setRequestOption task should be completed.
+ assertThat(requestsToCamera).isNotEmpty()
+ assertThat(resultFuture.get(3, TimeUnit.SECONDS)).isNull()
+ }
+
+ @Test
+ fun useCaseCameraUpdated_onlyCompleteLatestRequest(): Unit = runBlocking {
+ // Arrange.
+ val completeDeferred = CompletableDeferred<Unit>()
+ val fakeRequestControl = FakeUseCaseCameraRequestControl().apply {
+ setConfigResult = completeDeferred
+ }
+ val fakeUseCaseCamera = FakeUseCaseCamera(requestControl = fakeRequestControl)
+
+ val resultFuture = camera2CameraControl.setCaptureRequestOptions(
+ CaptureRequestOptions.Builder().setCaptureRequestOption(
+ CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_OFF
+ ).build()
+ )
+
+ // Act. Simulate the UseCaseCamera is recreated.
+ camera2CameraControl.useCaseCamera = fakeUseCaseCamera
+ // Act. Submit a new request option.
+ val resultFuture2 = camera2CameraControl.setCaptureRequestOptions(
+ CaptureRequestOptions.Builder().setCaptureRequestOption(
+ CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH
+ ).build()
+ )
+ // Simulate setRequestOption is completed in the recreated UseCaseCamera
+ completeDeferred.complete(Unit)
+ val requestsToCamera = fakeRequestControl.setConfigCalls.filter {
+ it.type == UseCaseCameraRequestControl.Type.CAMERA2_CAMERA_CONTROL
+ }.onEach { request ->
+ comboRequestListener.simulateRepeatingResult(
+ requests = request.config?.toParameters() ?: emptyMap(),
+ tags = request.tags,
+ )
+ }
+
+ // Assert. The first request should be cancelled., the latest setRequestOption
+ // task should be completed.
+ assertThat(requestsToCamera).isNotEmpty()
+ assertThrows<ExecutionException> {
+ resultFuture.get(3, TimeUnit.SECONDS)
+ }
+ assertThat(resultFuture2.get(3, TimeUnit.SECONDS)).isNull()
+ }
+
@Test(expected = IllegalArgumentException::class)
fun fromCameraControlThrows_whenNotCamera2Impl() {
val wrongCameraControl =
CameraControlInternal.DEFAULT_EMPTY_INSTANCE
Camera2CameraControl.from(wrongCameraControl)
}
+
+ private fun ComboRequestListener.simulateRepeatingResult(
+ requests: Map<CaptureRequest.Key<*>, Any> = emptyMap(),
+ tags: Map<String, Any> = emptyMap(),
+ results: Map<CaptureResult.Key<*>, Any> = emptyMap(),
+ frameNumber: FrameNumber = FrameNumber(101L),
+ ) {
+ val requestMetadata = FakeRequestMetadata(
+ requestParameters = requests,
+ metadata = mapOf(
+ CAMERAX_TAG_BUNDLE to MutableTagBundle.create().also { tagBundle ->
+ tags.forEach { (tagKey, tagValue) ->
+ tagBundle.putTag(tagKey, tagValue)
+ }
+ }
+ ),
+ requestNumber = RequestNumber(1)
+ )
+ val resultMetaData = FakeFrameMetadata(
+ resultMetadata = results,
+ frameNumber = frameNumber,
+ )
+ fakeUseCaseThreads.sequentialExecutor.execute {
+ onComplete(
+ requestMetadata, frameNumber, FakeFrameInfo(
+ metadata = resultMetaData,
+ requestMetadata = requestMetadata,
+ )
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfoTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfoTest.kt
index aab5b2d..d2f18b7 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfoTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfoTest.kt
@@ -28,9 +28,9 @@
import androidx.camera.core.CameraState
import androidx.camera.core.ExposureState
import androidx.camera.core.ZoomState
-import androidx.camera.core.impl.CamcorderProfileProvider
import androidx.camera.core.impl.CameraCaptureCallback
import androidx.camera.core.impl.CameraInfoInternal
+import androidx.camera.core.impl.EncoderProfilesProvider
import androidx.camera.core.impl.Quirks
import androidx.camera.core.impl.Timebase
import androidx.lifecycle.LiveData
@@ -153,7 +153,7 @@
throw NotImplementedError("Not used in testing")
}
- override fun getCamcorderProfileProvider(): CamcorderProfileProvider {
+ override fun getEncoderProfilesProvider(): EncoderProfilesProvider {
throw NotImplementedError("Not used in testing")
}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCamera2CameraControlCompat.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCamera2CameraControlCompat.kt
index 79e9e2c..13cc26d 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCamera2CameraControlCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCamera2CameraControlCompat.kt
@@ -41,7 +41,7 @@
// No-op
}
- override fun applyAsync(camera: UseCaseCamera?): Deferred<Void?> {
+ override fun applyAsync(camera: UseCaseCamera?, cancelPreviousTask: Boolean): Deferred<Void?> {
return CompletableDeferred(null)
}
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraInfoAdapterCreator.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraInfoAdapterCreator.kt
index e98ffc8..1a796be 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraInfoAdapterCreator.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraInfoAdapterCreator.kt
@@ -98,7 +98,8 @@
FocusMeteringControl(
cameraProperties,
state3AControl,
- useCaseThreads
+ useCaseThreads,
+ FakeZoomCompat(),
).apply {
useCaseCamera = fakeUseCaseCamera
}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeEvCompCompat.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeEvCompCompat.kt
index a8d73d5..afd3de9 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeEvCompCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeEvCompCompat.kt
@@ -25,13 +25,17 @@
class FakeEvCompCompat constructor(
override val supported: Boolean = false,
override val range: Range<Int> = Range(0, 0),
- override val step: Rational = Rational.ZERO
+ override val step: Rational = Rational.ZERO,
) : EvCompCompat {
- override fun stopRunningTask() {
+ override fun stopRunningTask(throwable: Throwable) {
TODO("Not yet implemented")
}
- override fun applyAsync(evCompIndex: Int, camera: UseCaseCamera): Deferred<Int> {
+ override fun applyAsync(
+ evCompIndex: Int,
+ camera: UseCaseCamera,
+ cancelPreviousTask: Boolean,
+ ): Deferred<Int> {
TODO("Not yet implemented")
}
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
index 9ec74a1..d98a07d 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
@@ -59,6 +59,13 @@
// TODO: Further implement the methods in this class as needed
open class FakeUseCaseCameraRequestControl : UseCaseCameraRequestControl {
+
+ val addParameterCalls = mutableListOf<Map<CaptureRequest.Key<*>, Any>>()
+ var addParameterResult = CompletableDeferred(Unit)
+ var setConfigCalls = mutableListOf<RequestParameters>()
+ var setConfigResult = CompletableDeferred(Unit)
+ var setTorchResult = CompletableDeferred(Result3A(status = Result3A.Status.OK))
+
override fun addParametersAsync(
type: UseCaseCameraRequestControl.Type,
values: Map<CaptureRequest.Key<*>, Any>,
@@ -68,7 +75,8 @@
template: RequestTemplate?,
listeners: Set<Request.Listener>
): Deferred<Unit> {
- return CompletableDeferred(Unit)
+ addParameterCalls.add(values)
+ return addParameterResult
}
override fun setConfigAsync(
@@ -79,6 +87,7 @@
template: RequestTemplate?,
listeners: Set<Request.Listener>
): Deferred<Unit> {
+ setConfigCalls.add(RequestParameters(type, config, tags))
return CompletableDeferred(Unit)
}
@@ -87,7 +96,7 @@
}
override suspend fun setTorchAsync(enabled: Boolean): Deferred<Result3A> {
- return CompletableDeferred(Result3A(status = Result3A.Status.OK))
+ return setTorchResult
}
val focusMeteringCalls = mutableListOf<FocusMeteringParams>()
@@ -127,6 +136,12 @@
val awbRegions: List<MeteringRectangle> = emptyList(),
val afTriggerStartAeMode: AeMode? = null
)
+
+ data class RequestParameters(
+ val type: UseCaseCameraRequestControl.Type,
+ val config: Config?,
+ val tags: Map<String, Any> = emptyMap(),
+ )
}
// TODO: Further implement the methods in this class as needed
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeZoomCompat.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeZoomCompat.kt
index cabac1a..e48a1d9 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeZoomCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeZoomCompat.kt
@@ -16,16 +16,20 @@
package androidx.camera.camera2.pipe.integration.testing
+import android.graphics.Rect
import androidx.camera.camera2.pipe.integration.compat.ZoomCompat
import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera
class FakeZoomCompat constructor(
- override val minZoom: Float = 0f,
- override val maxZoom: Float = 0f,
+ override val minZoomRatio: Float = 0f,
+ override val maxZoomRatio: Float = 0f,
+ var croppedSensorArea: Rect = Rect(0, 0, 640, 480),
) : ZoomCompat {
var zoomRatio = 0f
override fun apply(zoomRatio: Float, camera: UseCaseCamera) {
this.zoomRatio = zoomRatio
}
+
+ override fun getCropSensorRegion() = croppedSensorArea
}
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
index 26cbb85..6f6f637 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraControllerSimulator.kt
@@ -21,6 +21,7 @@
import androidx.camera.camera2.pipe.CameraContext
import androidx.camera.camera2.pipe.CameraController
import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.GraphState.GraphStateError
import androidx.camera.camera2.pipe.StreamGraph
import androidx.camera.camera2.pipe.StreamId
@@ -45,6 +46,9 @@
private val graphListener: GraphListener,
private val streamGraph: StreamGraph
) : CameraController {
+ override val cameraId: CameraId
+ get() = graphConfig.camera
+
private val lock = Any()
private var currentSurfaceMap: Map<StreamId, Surface> = emptyMap()
private var currentGraphRequestProcessor: GraphRequestProcessor? = null
@@ -152,10 +156,23 @@
override fun stop() {
synchronized(lock) {
+ check(!closed) {
+ "Attempted to invoke stop after close."
+ }
started = false
}
}
+ override fun tryRestart() {
+ synchronized(lock) {
+ check(!closed) {
+ "Attempted to invoke restart after close."
+ }
+ stop()
+ start()
+ }
+ }
+
override fun close() {
synchronized(lock) {
closed = true
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
index eaaa2eb..1e1f6a3 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
@@ -24,10 +24,13 @@
import androidx.camera.camera2.pipe.CameraGraph
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.CameraStatusMonitor
import androidx.camera.camera2.pipe.StreamGraph
import androidx.camera.camera2.pipe.graph.GraphListener
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
/**
* The FakeCameraBackend implements [CameraBackend] and creates [CameraControllerSimulator]s.
@@ -43,6 +46,8 @@
override val id: CameraBackendId
get() = FAKE_CAMERA_BACKEND_ID
+ override val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
+ get() = MutableSharedFlow()
override fun awaitCameraIds(): List<CameraId> = fakeCameraIds
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
index 4f9485d..66cbd6f 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
@@ -17,12 +17,28 @@
import androidx.camera.camera2.pipe.graph.GraphListener
import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.flow.Flow
/** This is used to uniquely identify a specific backend implementation. */
@JvmInline
value class CameraBackendId(val value: String)
/**
+ * A CameraStatusMonitors monitors the status of the cameras, and emits updates when the status of
+ * cameras changes, for instance when the camera access priorities have changed or when a particular
+ * camera has become available.
+ */
+interface CameraStatusMonitor {
+ val cameraStatus: Flow<CameraStatus>
+
+ abstract class CameraStatus internal constructor() {
+ object CameraPrioritiesChanged : CameraStatus()
+
+ class CameraAvailable(val cameraId: CameraId) : CameraStatus()
+ }
+}
+
+/**
* A CameraBackend is used by [CameraPipe] to abstract out the lifecycle, state, and interactions
* with a set of camera devices in a standard way.
*
@@ -38,6 +54,12 @@
val id: CameraBackendId
/**
+ * A flow of camera statuses that provide camera status updates such as when the camera access
+ * priorities have changed, or a certain camera has become available.
+ */
+ val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
+
+ /**
* Read out a list of _openable_ [CameraId]s for this backend. The backend may be able to report
* Metadata for non-openable cameras. However, these cameras should not appear the list of
* cameras returned by [getCameraIds].
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
index 0eacef9..29dee61 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraController.kt
@@ -17,6 +17,7 @@
package androidx.camera.camera2.pipe
import android.view.Surface
+import androidx.camera.camera2.pipe.CameraController.ControllerState.CLOSED
import androidx.camera.camera2.pipe.graph.GraphListener
/**
@@ -35,8 +36,10 @@
* Once [close] is invoked, this instance should not respond to any additional events.
*/
interface CameraController {
+ val cameraId: CameraId
+
/**
- * Connect and start the underlying camera.This may be called on the main thread and should not
+ * Connect and start the underlying camera. This may be called on the main thread and should not
* make long blocking calls. This may be called opportunistically (eg, whenever a lifecycle
* indicates the camera should be in a running state)
*/
@@ -49,6 +52,13 @@
fun stop()
/**
+ * Restart the current session. This should basically perform stop() then start(). However, the
+ * implementation should handle its internal states correctly, and only restart when the
+ * conditions are appropriate.
+ */
+ fun tryRestart()
+
+ /**
* Close this instance. [start] and [stop] should not be invoked, and any additional calls will
* be ignored once this method returns. Depending on implementation the underlying camera
* connection may not be terminated immediately, depending on the [CameraBackend]
@@ -61,4 +71,40 @@
* missing from the [StreamGraph] that was used to create this [CameraController].
*/
fun updateSurfaceMap(surfaceMap: Map<StreamId, Surface>)
+
+ /**
+ * ControllerState indicates the internal state of a [CameraController]. These states are needed
+ * to make sure we only invoke [CameraController] methods under the right conditions.
+ *
+ * The following diagram illustrates the state transitions (all states also have a permissible
+ * transition to [CLOSED]).
+ *
+ * ```
+ * [STOPPED] --> [STARTED] --> [STOPPING] ---------.--------.
+ * ^ ^ | | |
+ * | | V V |
+ * | '---------[DISCONNECTED] [ERROR] |
+ * | |
+ * '-----------------------------------------------------'
+ * ```
+ */
+ abstract class ControllerState internal constructor() {
+ /** When the CameraController is started. This is set immediately as start() is called. */
+ object STARTED : ControllerState()
+
+ /** When the CameraController is stopping. This is set immediately as stop() is called. */
+ object STOPPING : ControllerState()
+
+ /** When the camera is stopped normally. */
+ object STOPPED : ControllerState()
+
+ /** When the camera is disconnected and can be later "reconnected". */
+ object DISCONNECTED : ControllerState()
+
+ /** When the camera shuts down with an unrecoverable error. */
+ object ERROR : ControllerState()
+
+ /** When the CameraController is closed, and no further operations can done on it. */
+ object CLOSED : ControllerState()
+ }
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
index 343a8cb..f78fd57 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
@@ -24,6 +24,7 @@
import androidx.camera.camera2.pipe.CameraGraph
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
import androidx.camera.camera2.pipe.StreamGraph
import androidx.camera.camera2.pipe.config.Camera2ControllerComponent
import androidx.camera.camera2.pipe.config.Camera2ControllerConfig
@@ -33,6 +34,7 @@
import javax.inject.Inject
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.flow.Flow
/** This is the default [CameraBackend] implementation for CameraPipe based on Camera2. */
@RequiresApi(21)
@@ -44,9 +46,12 @@
private val camera2MetadataCache: Camera2MetadataCache,
private val virtualCameraManager: VirtualCameraManager,
private val camera2CameraControllerComponent: Camera2ControllerComponent.Builder,
+ private val camera2CameraStatusMonitor: Camera2CameraStatusMonitor,
) : CameraBackend {
override val id: CameraBackendId
get() = CameraBackendId("CXCP-Camera2")
+ override val cameraStatus: Flow<CameraStatus>
+ get() = camera2CameraStatusMonitor.cameraStatus
override suspend fun getCameraIds(): List<CameraId>? = camera2DeviceCache.getCameraIds()
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
index 4b48fbc..5ddaf29 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraController.kt
@@ -17,16 +17,22 @@
package androidx.camera.camera2.pipe.compat
import android.view.Surface
+import androidx.annotation.GuardedBy
import androidx.annotation.RequiresApi
import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.CameraController.ControllerState
+import androidx.camera.camera2.pipe.CameraError
import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraSurfaceManager
import androidx.camera.camera2.pipe.StreamId
import androidx.camera.camera2.pipe.config.Camera2ControllerScope
+import androidx.camera.camera2.pipe.core.Log
import androidx.camera.camera2.pipe.core.TimeSource
import androidx.camera.camera2.pipe.graph.GraphListener
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
/**
@@ -52,79 +58,104 @@
private val cameraSurfaceManager: CameraSurfaceManager,
private val timeSource: TimeSource
) : CameraController {
- private var closed = false
+ override val cameraId: CameraId
+ get() = config.camera
+
+ private val lock = Any()
+
+ @GuardedBy("lock")
+ private var controllerState: ControllerState = ControllerState.STOPPED
+
private var currentCamera: VirtualCamera? = null
private var currentSession: CaptureSessionState? = null
private var currentSurfaceMap: Map<StreamId, Surface>? = null
- override fun start() {
- val camera =
- virtualCameraManager.open(
- config.camera, config.flags.allowMultipleActiveCameras, graphListener
- )
- synchronized(this) {
- if (closed) {
- return
- }
+ private var currentCameraStateJob: Job? = null
- check(currentCamera == null)
- check(currentSession == null)
-
- currentCamera = camera
- val session =
- CaptureSessionState(
- graphListener,
- captureSessionFactory,
- captureSequenceProcessorFactory,
- cameraSurfaceManager,
- timeSource,
- scope
- )
- currentSession = session
-
- val surfaces: Map<StreamId, Surface>? = currentSurfaceMap
- if (surfaces != null) {
- session.configureSurfaceMap(surfaces)
- }
+ override fun start(): Unit = synchronized(lock) {
+ if (controllerState == ControllerState.CLOSED) {
+ Log.info { "Ignoring start(): Camera2CameraController is already closed" }
+ return
+ } else if (controllerState == ControllerState.STARTED) {
+ Log.warn { "Ignoring start(): Camera2CameraController is already started" }
+ return
}
- scope.launch { bindSessionToCamera() }
+ val camera = virtualCameraManager.open(
+ config.camera,
+ config.flags.allowMultipleActiveCameras,
+ graphListener
+ )
+
+ check(currentCamera == null)
+ check(currentSession == null)
+
+ currentCamera = camera
+ val session = CaptureSessionState(
+ graphListener,
+ captureSessionFactory,
+ captureSequenceProcessorFactory,
+ cameraSurfaceManager,
+ timeSource,
+ scope
+ )
+ currentSession = session
+
+ val surfaces: Map<StreamId, Surface>? = currentSurfaceMap
+ if (surfaces != null) {
+ session.configureSurfaceMap(surfaces)
+ }
+
+ controllerState = ControllerState.STARTED
+ Log.debug { "Started Camera2CameraController" }
+ currentCameraStateJob = scope.launch { bindSessionToCamera() }
}
- override fun stop() {
- val camera: VirtualCamera?
- val session: CaptureSessionState?
- synchronized(this) {
- if (closed) {
- return
- }
-
- camera = currentCamera
- session = currentSession
-
- currentCamera = null
- currentSession = null
+ override fun stop(): Unit = synchronized(lock) {
+ if (controllerState == ControllerState.CLOSED) {
+ Log.warn { "Ignoring stop(): Camera2CameraController is already closed" }
+ return
+ } else if (controllerState == ControllerState.STOPPING ||
+ controllerState == ControllerState.STOPPED
+ ) {
+ Log.warn { "Ignoring stop(): CameraController already stopping or stopped" }
+ return
}
+ val camera = currentCamera
+ val session = currentSession
+
+ currentCamera = null
+ currentSession = null
+
+ controllerState = ControllerState.STOPPING
+ Log.debug { "Stopping Camera2CameraController" }
scope.launch {
session?.disconnect()
camera?.disconnect()
}
}
- override fun close() {
- val camera: VirtualCamera?
- val session: CaptureSessionState?
- synchronized(this) {
- if (closed) {
- return
- }
- closed = true
- camera = currentCamera
- session = currentSession
-
- currentCamera = null
- currentSession = null
+ override fun tryRestart(): Unit = synchronized(lock) {
+ if (controllerState != ControllerState.DISCONNECTED) {
+ Log.debug { "Ignoring restart(): CameraController is $controllerState" }
+ return
}
+ stop()
+ start()
+ }
+
+ override fun close(): Unit = synchronized(lock) {
+ if (controllerState == ControllerState.CLOSED) {
+ return
+ }
+ controllerState = ControllerState.CLOSED
+ Log.debug { "Closed Camera2CameraController" }
+
+ val camera = currentCamera
+ val session = currentSession
+
+ currentCamera = null
+ currentSession = null
scope.launch {
session?.disconnect()
@@ -134,33 +165,67 @@
override fun updateSurfaceMap(surfaceMap: Map<StreamId, Surface>) {
// TODO: Add logic to decide if / when to re-configure the Camera2 CaptureSession.
- synchronized(this) {
- if (closed) {
+ synchronized(lock) {
+ if (controllerState == ControllerState.CLOSED) {
return
}
currentSurfaceMap = surfaceMap
currentSession
- }
- ?.configureSurfaceMap(surfaceMap)
+ }?.configureSurfaceMap(surfaceMap)
}
private suspend fun bindSessionToCamera() {
val camera: VirtualCamera?
val session: CaptureSessionState?
- synchronized(this) {
+ synchronized(lock) {
camera = currentCamera
session = currentSession
}
if (camera != null && session != null) {
- camera.state.collect {
- if (it is CameraStateOpen) {
- session.cameraDevice = it.cameraDevice
- } else if (it is CameraStateClosing || it is CameraStateClosed) {
- session.disconnect()
+ camera.state.collect { cameraState ->
+ when (cameraState) {
+ is CameraStateOpen -> {
+ session.cameraDevice = cameraState.cameraDevice
+ }
+
+ is CameraStateClosing -> {
+ session.disconnect()
+ }
+
+ is CameraStateClosed -> {
+ session.disconnect()
+ onStateClosed(cameraState)
+ }
+
+ else -> {
+ // Do nothing
+ }
}
}
}
}
+
+ private fun onStateClosed(cameraState: CameraStateClosed) = synchronized(lock) {
+ if (cameraState.cameraErrorCode != null) {
+ if (cameraState.cameraErrorCode == CameraError.ERROR_CAMERA_DISCONNECTED ||
+ cameraState.cameraErrorCode == CameraError.ERROR_CAMERA_IN_USE ||
+ cameraState.cameraErrorCode == CameraError.ERROR_CAMERA_LIMIT_EXCEEDED
+ ) {
+ controllerState = ControllerState.DISCONNECTED
+ Log.debug { "Camera2CameraController is disconnected" }
+ } else {
+ controllerState = ControllerState.ERROR
+ Log.debug {
+ "Camera2CameraController encountered an " +
+ "unrecoverable error: ${cameraState.cameraErrorCode}"
+ }
+ }
+ } else {
+ controllerState = ControllerState.STOPPED
+ }
+ currentCameraStateJob?.cancel()
+ currentCameraStateJob = null
+ }
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt
new file mode 100644
index 0000000..0ab7e59
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraStatusMonitor.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2022 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.camera.camera2.pipe.compat
+
+import android.hardware.camera2.CameraManager
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraStatusMonitor
+import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
+import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.core.Threads
+import javax.inject.Inject
+import javax.inject.Provider
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.channels.onFailure
+import kotlinx.coroutines.channels.trySendBlocking
+import kotlinx.coroutines.flow.callbackFlow
+
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+internal class Camera2CameraStatusMonitor @Inject constructor(
+ cameraManager: Provider<CameraManager>,
+ threads: Threads
+) : CameraStatusMonitor {
+ override val cameraStatus = callbackFlow {
+ val manager = cameraManager.get()
+ val availabilityCallback = object : CameraManager.AvailabilityCallback() {
+ override fun onCameraAccessPrioritiesChanged() {
+ Log.debug { "Camera access priorities have changed" }
+ trySendBlocking(CameraStatus.CameraPrioritiesChanged)
+ .onFailure {
+ Log.warn { "Failed to emit CameraPrioritiesChanged" }
+ }
+ }
+
+ override fun onCameraAvailable(cameraId: String) {
+ Log.debug { "Camera $cameraId has become available" }
+ trySendBlocking(CameraStatus.CameraAvailable(CameraId.fromCamera2Id(cameraId)))
+ .onFailure {
+ Log.warn { "Failed to emit CameraAvailable($cameraId)" }
+ }
+ }
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ Api28Compat.registerAvailabilityCallback(
+ manager,
+ threads.lightweightExecutor,
+ availabilityCallback
+ )
+ } else {
+ manager.registerAvailabilityCallback(
+ availabilityCallback,
+ threads.camera2Handler
+ )
+ }
+
+ awaitClose { manager.unregisterAvailabilityCallback(availabilityCallback) }
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionWrapper.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionWrapper.kt
index 564a5bc..2698852 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionWrapper.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionWrapper.kt
@@ -18,6 +18,8 @@
package androidx.camera.camera2.pipe.compat
+import android.hardware.camera2.CameraAccessException
+import android.hardware.camera2.CameraAccessException.CAMERA_ERROR
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession
import android.hardware.camera2.CaptureRequest
@@ -354,10 +356,23 @@
"succeed."
}
- rethrowCamera2Exceptions {
+ var exceptionToThrow: Throwable? = null
+ try {
Api26Compat.finalizeOutputConfigurations(
- cameraCaptureSession, outputConfigs.map { it.unwrapAs(OutputConfiguration::class) })
+ cameraCaptureSession,
+ outputConfigs.map { it.unwrapAs(OutputConfiguration::class) })
+ } catch (e: CameraAccessException) {
+ // TODO(b/266734799): There is a possibility that we might finalize output
+ // configurations on a camera that's been disconnected. In such cases, we'll receive
+ // CameraAccessException.CAMERA_ERROR. Catch it for now, until we properly report and
+ // handle capture session errors.
+ if (e.reason != CAMERA_ERROR) {
+ exceptionToThrow = e
+ }
+ } catch (e: Throwable) {
+ exceptionToThrow = e
}
+ exceptionToThrow?.let { rethrowCamera2Exceptions { throw it } }
}
@Suppress("UNCHECKED_CAST")
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
index 8988b2b..151d702 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ExternalRequestProcessor.kt
@@ -50,6 +50,9 @@
GraphRequestProcessor.from(sequenceProcessor)
private var started = atomic(false)
+ override val cameraId: CameraId
+ get() = graphConfig.camera
+
override fun start() {
if (started.compareAndSet(expect = false, update = true)) {
graphListener.onGraphStarted(graphProcessor)
@@ -62,6 +65,11 @@
}
}
+ override fun tryRestart() {
+ // This is intentionally made a no-op for now as CameraPipe external doesn't support
+ // camera status monitoring and camera controller restart.
+ }
+
override fun close() {
graphProcessor.close()
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
index b870809..fe27798 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
@@ -21,6 +21,7 @@
import androidx.annotation.RequiresApi
import androidx.camera.camera2.pipe.CameraError
import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.core.Log
import androidx.camera.camera2.pipe.core.Permissions
import androidx.camera.camera2.pipe.core.Threads
import androidx.camera.camera2.pipe.core.WakeLock
@@ -206,6 +207,7 @@
// causing the application process to restart.
check(permissions.hasCameraPermission) { "Missing camera permissions!" }
+ Log.debug { "Opening $cameraId with retries..." }
val result = retryingCameraStateOpener.openCameraWithRetry(cameraId, graphListener)
if (result.cameraState == null) {
return OpenVirtualCameraResult(lastCameraError = result.errorCode)
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
index c7b6b1e..57d38e5 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
@@ -20,11 +20,13 @@
import androidx.camera.camera2.pipe.CameraBackend
import androidx.camera.camera2.pipe.CameraController
import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraStatusMonitor
import androidx.camera.camera2.pipe.StreamGraph
import androidx.camera.camera2.pipe.compat.Camera2Backend
import androidx.camera.camera2.pipe.compat.Camera2CameraAvailabilityMonitor
import androidx.camera.camera2.pipe.compat.Camera2CameraController
import androidx.camera.camera2.pipe.compat.Camera2CameraOpener
+import androidx.camera.camera2.pipe.compat.Camera2CameraStatusMonitor
import androidx.camera.camera2.pipe.compat.Camera2CaptureSequenceProcessorFactory
import androidx.camera.camera2.pipe.compat.Camera2CaptureSessionsModule
import androidx.camera.camera2.pipe.compat.Camera2MetadataCache
@@ -62,6 +64,11 @@
abstract fun bindCameraAvailabilityMonitor(
camera2CameraAvailabilityMonitor: Camera2CameraAvailabilityMonitor
): CameraAvailabilityMonitor
+
+ @Binds
+ abstract fun bindCameraStatusMonitor(
+ camera2CameraStatusMonitor: Camera2CameraStatusMonitor
+ ): CameraStatusMonitor
}
@Scope
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
index ce3a3ad..28bd09a 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
@@ -55,6 +55,9 @@
@Qualifier
internal annotation class CameraPipeContext
+@Qualifier
+internal annotation class ForGraphLifecycleManager
+
@Singleton
@Component(
modules =
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
index b93b659..6ca0561 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
@@ -21,15 +21,24 @@
package androidx.camera.camera2.pipe.config
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraContext
import androidx.camera.camera2.pipe.CameraController
import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.CameraStatusMonitor
import androidx.camera.camera2.pipe.RequestProcessor
+import androidx.camera.camera2.pipe.StreamGraph
import androidx.camera.camera2.pipe.compat.ExternalCameraController
import androidx.camera.camera2.pipe.graph.GraphListener
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
@CameraGraphScope
@Subcomponent(modules = [SharedCameraGraphModules::class, ExternalCameraGraphConfigModule::class])
@@ -49,6 +58,45 @@
private val cameraMetadata: CameraMetadata,
private val requestProcessor: RequestProcessor
) {
+ private val externalCameraBackend = object : CameraBackend {
+ override val id: CameraBackendId
+ get() = CameraBackendId("External")
+ override val cameraStatus: Flow<CameraStatusMonitor.CameraStatus>
+ get() = MutableSharedFlow()
+
+ override suspend fun getCameraIds(): List<CameraId>? {
+ throwUnsupportedOperationException()
+ }
+
+ override fun awaitCameraIds(): List<CameraId>? {
+ throwUnsupportedOperationException()
+ }
+
+ override fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata? {
+ throwUnsupportedOperationException()
+ }
+
+ override fun disconnectAllAsync(): Deferred<Unit> {
+ throwUnsupportedOperationException()
+ }
+
+ override fun shutdownAsync(): Deferred<Unit> {
+ throwUnsupportedOperationException()
+ }
+
+ override fun createCameraController(
+ cameraContext: CameraContext,
+ graphConfig: CameraGraph.Config,
+ graphListener: GraphListener,
+ streamGraph: StreamGraph
+ ): CameraController {
+ throwUnsupportedOperationException()
+ }
+
+ private fun throwUnsupportedOperationException(): Nothing =
+ throw UnsupportedOperationException("External CameraPipe should not use backends")
+ }
+
@Provides
fun provideCameraGraphConfig(): CameraGraph.Config = config
@@ -59,4 +107,8 @@
@Provides
fun provideGraphController(graphListener: GraphListener): CameraController =
ExternalCameraController(config, graphListener, requestProcessor)
+
+ @CameraGraphScope
+ @Provides
+ fun provideCameraBackend(): CameraBackend = externalCameraBackend
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraPipeComponent.kt
index 233200c..6068c13 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraPipeComponent.kt
@@ -25,4 +25,4 @@
@Component(modules = [ThreadConfigModule::class])
internal interface ExternalCameraPipeComponent {
fun cameraGraphBuilder(): ExternalCameraGraphComponent.Builder
-}
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
index 366f78c..586f399 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/graph/CameraGraphImpl.kt
@@ -18,6 +18,7 @@
import android.view.Surface
import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
import androidx.camera.camera2.pipe.CameraController
import androidx.camera.camera2.pipe.CameraGraph
import androidx.camera.camera2.pipe.CameraMetadata
@@ -31,6 +32,7 @@
import androidx.camera.camera2.pipe.core.TokenLockImpl
import androidx.camera.camera2.pipe.core.acquire
import androidx.camera.camera2.pipe.core.acquireOrNull
+import androidx.camera.camera2.pipe.internal.GraphLifecycleManager
import javax.inject.Inject
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.flow.StateFlow
@@ -44,10 +46,12 @@
constructor(
graphConfig: CameraGraph.Config,
metadata: CameraMetadata,
+ private val graphLifecycleManager: GraphLifecycleManager,
private val graphProcessor: GraphProcessor,
private val graphListener: GraphListener,
private val streamGraph: StreamGraphImpl,
private val surfaceGraph: SurfaceGraph,
+ private val cameraBackend: CameraBackend,
private val cameraController: CameraController,
private val graphState3A: GraphState3A,
private val listener3A: Listener3A
@@ -104,7 +108,7 @@
Debug.traceStart { "$this#start" }
Log.info { "Starting $this" }
graphListener.onGraphStarting()
- cameraController.start()
+ graphLifecycleManager.monitorAndStart(cameraBackend, cameraController)
Debug.traceStop()
}
@@ -112,7 +116,7 @@
Debug.traceStart { "$this#stop" }
Log.info { "Stopping $this" }
graphListener.onGraphStopping()
- cameraController.stop()
+ graphLifecycleManager.monitorAndStop(cameraBackend, cameraController)
Debug.traceStop()
}
@@ -146,7 +150,7 @@
Log.info { "Closing $this" }
sessionLock.close()
graphProcessor.close()
- cameraController.close()
+ graphLifecycleManager.monitorAndClose(cameraBackend, cameraController)
surfaceGraph.close()
Debug.traceStop()
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt
new file mode 100644
index 0000000..1429f76
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/GraphLifecycleManager.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2023 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.camera.camera2.pipe.internal
+
+import androidx.annotation.GuardedBy
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
+import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraStatusMonitor
+import androidx.camera.camera2.pipe.CameraStatusMonitor.CameraStatus
+import androidx.camera.camera2.pipe.core.Threads
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+
+/**
+ * GraphLifecycleManager is a CameraPipe-level lifecycle manager that does the following:
+ * - Oversees and executes the operations of [CameraController]`s. This means it will make sure the
+ * operations are atomic, and executed based on permissible state transitions.
+ * - Subscribe to [CameraStatusMonitor]s for camera status changes, basically “can attempt to
+ * restart signals”, from the respective camera backends, and then only restart
+ * [CameraController]s when the conditions are right.
+ * - Once we've determined that we can restart [CameraController]s, select the “suitable”
+ * [CameraController] to restart.
+ */
+@Singleton
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+internal class GraphLifecycleManager @Inject constructor(val threads: Threads) {
+ private val lock = Any()
+
+ private val scope = CoroutineScope(
+ threads.lightweightDispatcher.plus(CoroutineName("CXCP-GraphLifecycleManager"))
+ )
+
+ @GuardedBy("lock")
+ private val backendControllerMap =
+ mutableMapOf<CameraBackendId, LinkedHashSet<CameraController>>()
+
+ @GuardedBy("lock")
+ private val backendStatusCollectJobMap = mutableMapOf<CameraBackendId, Job>()
+
+ internal fun monitorAndStart(cameraBackend: CameraBackend, cameraController: CameraController) =
+ synchronized(lock) {
+ startMonitoring(cameraBackend, cameraController)
+ cameraController.start()
+ }
+
+ internal fun monitorAndStop(cameraBackend: CameraBackend, cameraController: CameraController) =
+ synchronized(lock) {
+ cameraController.stop()
+ stopMonitoring(cameraBackend, cameraController)
+ }
+
+ internal fun monitorAndClose(cameraBackend: CameraBackend, cameraController: CameraController) =
+ synchronized(lock) {
+ cameraController.close()
+ stopMonitoring(cameraBackend, cameraController)
+ }
+
+ @GuardedBy("lock")
+ private fun startMonitoring(cameraBackend: CameraBackend, cameraController: CameraController) {
+ if (backendControllerMap.containsKey(cameraBackend.id)) {
+ backendControllerMap[cameraBackend.id]?.add(cameraController)
+ return
+ }
+ backendControllerMap[cameraBackend.id] = linkedSetOf(cameraController)
+ backendStatusCollectJobMap[cameraBackend.id] = scope.launch {
+ cameraBackend.cameraStatus.collect { cameraStatus ->
+ when (cameraStatus) {
+ is CameraStatus.CameraPrioritiesChanged ->
+ tryRestartCameraController(cameraBackend)
+
+ is CameraStatus.CameraAvailable ->
+ tryRestartCameraController(cameraBackend, cameraStatus.cameraId)
+ }
+ }
+ }
+ }
+
+ @GuardedBy("lock")
+ private fun stopMonitoring(cameraBackend: CameraBackend, cameraController: CameraController) {
+ if (backendControllerMap.containsKey(cameraBackend.id)) {
+ val controllerSet = backendControllerMap[cameraBackend.id]
+ controllerSet?.remove(cameraController)
+ if (controllerSet?.size == 0) {
+ backendControllerMap.remove(cameraBackend.id)
+ backendStatusCollectJobMap[cameraBackend.id]?.cancel()
+ backendStatusCollectJobMap.remove(cameraBackend.id)
+ }
+ }
+ }
+
+ private fun tryRestartCameraController(
+ cameraBackend: CameraBackend,
+ cameraId: CameraId? = null,
+ ) = synchronized(lock) {
+ // Restart the last CameraController being tracked in each backend. The last
+ // CameraController would be the latest one being tracked, and should thus take priority
+ // over previous CameraControllers.
+ backendControllerMap[cameraBackend.id]?.findLast {
+ if (cameraId != null) {
+ it.cameraId == cameraId
+ } else {
+ true
+ }
+ }?.tryRestart()
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
index e377214..05af92f 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/CameraGraphImplTest.kt
@@ -30,6 +30,7 @@
import androidx.camera.camera2.pipe.Request
import androidx.camera.camera2.pipe.StreamFormat
import androidx.camera.camera2.pipe.internal.CameraBackendsImpl
+import androidx.camera.camera2.pipe.internal.GraphLifecycleManager
import androidx.camera.camera2.pipe.testing.CameraControllerSimulator
import androidx.camera.camera2.pipe.testing.FakeCameraBackend
import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
@@ -92,6 +93,7 @@
threads
)
val cameraContext = CameraBackendsImpl.CameraBackendContext(context, threads, backends)
+ val graphLifecycleManager = GraphLifecycleManager(threads)
val streamGraph = StreamGraphImpl(metadata, graphConfig)
cameraController =
CameraControllerSimulator(cameraContext, graphConfig, fakeGraphProcessor, streamGraph)
@@ -101,10 +103,12 @@
CameraGraphImpl(
graphConfig,
metadata,
+ graphLifecycleManager,
fakeGraphProcessor,
fakeGraphProcessor,
streamGraph,
surfaceGraph,
+ backend,
cameraController,
GraphState3A(),
Listener3A()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
index b637133..c49f98a 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeCameraController.kt
@@ -18,12 +18,15 @@
import android.view.Surface
import androidx.camera.camera2.pipe.CameraController
+import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.StreamId
internal class FakeCameraController : CameraController {
var started = false
var closed = false
var surfaceMap: Map<StreamId, Surface>? = null
+ override val cameraId: CameraId
+ get() = CameraId.fromCamera2Id("0")
override fun start() {
started = true
@@ -33,6 +36,11 @@
started = false
}
+ override fun tryRestart() {
+ stop()
+ start()
+ }
+
override fun close() {
closed = true
started = false
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProviderTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProviderTest.kt
deleted file mode 100644
index 6d48e3e7..0000000
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProviderTest.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.camera.camera2.internal
-
-import android.hardware.camera2.CameraCharacteristics
-import android.media.CamcorderProfile
-import android.util.Size
-import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat
-import androidx.camera.camera2.internal.compat.StreamConfigurationMapCompat
-import androidx.camera.core.CameraSelector
-import androidx.camera.core.impl.ImageFormatConstants
-import androidx.camera.testing.CameraUtil
-import androidx.test.filters.SdkSuppress
-import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assume.assumeTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@SmallTest
-@Suppress("DEPRECATION")
-@SdkSuppress(minSdkVersion = 21)
-public class Camera2CamcorderProfileProviderTest(private val quality: Int) {
- public companion object {
- @JvmStatic
- @Parameterized.Parameters
- public fun data(): Array<Array<Int>> = arrayOf(
- arrayOf(CamcorderProfile.QUALITY_LOW),
- arrayOf(CamcorderProfile.QUALITY_HIGH),
- arrayOf(CamcorderProfile.QUALITY_QCIF),
- arrayOf(CamcorderProfile.QUALITY_CIF),
- arrayOf(CamcorderProfile.QUALITY_480P),
- arrayOf(CamcorderProfile.QUALITY_720P),
- arrayOf(CamcorderProfile.QUALITY_1080P),
- arrayOf(CamcorderProfile.QUALITY_QVGA),
- arrayOf(CamcorderProfile.QUALITY_2160P),
- arrayOf(CamcorderProfile.QUALITY_VGA),
- arrayOf(CamcorderProfile.QUALITY_4KDCI),
- arrayOf(CamcorderProfile.QUALITY_QHD),
- arrayOf(CamcorderProfile.QUALITY_2K)
- )
- }
-
- private lateinit var camcorderProfileProvider: Camera2CamcorderProfileProvider
- private lateinit var cameraCharacteristics: CameraCharacteristicsCompat
- private var isLegacyCamera = false
- private var intCameraId = -1
-
- @Before
- public fun setup() {
- assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
-
- val cameraId = CameraUtil.getCameraIdWithLensFacing(CameraSelector.LENS_FACING_BACK)!!
- intCameraId = cameraId.toInt()
-
- cameraCharacteristics = CameraCharacteristicsCompat.toCameraCharacteristicsCompat(
- CameraUtil.getCameraCharacteristics(CameraSelector.LENS_FACING_BACK)!!
- )
- val hardwareLevel =
- cameraCharacteristics[CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL]
-
- isLegacyCamera = hardwareLevel != null && hardwareLevel == CameraCharacteristics
- .INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
-
- camcorderProfileProvider = Camera2CamcorderProfileProvider(cameraId, cameraCharacteristics)
- }
-
- @Test
- public fun nonLegacyCamera_hasProfile_returnSameResult() {
- assumeTrue(!isLegacyCamera)
-
- assertThat(camcorderProfileProvider.hasProfile(quality))
- .isEqualTo(CamcorderProfile.hasProfile(intCameraId, quality))
- }
-
- @Test
- public fun nonLegacyCamera_notHasProfile_getReturnNull() {
- assumeTrue(!isLegacyCamera)
- assumeTrue(!CamcorderProfile.hasProfile(intCameraId, quality))
-
- assertThat(camcorderProfileProvider.get(quality)).isNull()
- }
-
- @Test
- public fun nonLegacyCamera_hasProfile_getReturnSameQualityProfile() {
- assumeTrue(!isLegacyCamera)
- assumeTrue(CamcorderProfile.hasProfile(intCameraId, quality))
-
- val profileProxy = camcorderProfileProvider.get(quality)!!
- val profile = CamcorderProfile.get(intCameraId, quality)
- assertThat(profileProxy.quality).isEqualTo(profile.quality)
- }
-
- @Test
- public fun legacyCamera_notHasProfile_returnFalse() {
- assumeTrue(isLegacyCamera)
- assumeTrue(!CamcorderProfile.hasProfile(intCameraId, quality))
-
- assertThat(camcorderProfileProvider.hasProfile(quality)).isFalse()
- }
-
- @Test
- public fun legacyCamera_hasProfile_shouldCheckSupportedResolution() {
- assumeTrue(isLegacyCamera)
- assumeTrue(CamcorderProfile.hasProfile(intCameraId, quality))
-
- val videoSupportedResolutions = getVideoSupportedResolutions()
- val isResolutionSupported =
- videoSupportedResolutions.contains(CamcorderProfile.get(intCameraId, quality).size())
-
- assertThat(camcorderProfileProvider.hasProfile(quality)).isEqualTo(isResolutionSupported)
- }
-
- @Test
- public fun legacyCamera_notHasProfile_getReturnNull() {
- assumeTrue(isLegacyCamera)
- assumeTrue(!CamcorderProfile.hasProfile(intCameraId, quality))
-
- assertThat(camcorderProfileProvider.get(quality)).isNull()
- }
-
- @Test
- public fun legacyCamera_hasProfile_getShouldCheckSupportedResolution() {
- assumeTrue(isLegacyCamera)
- assumeTrue(CamcorderProfile.hasProfile(intCameraId, quality))
-
- val profile = CamcorderProfile.get(intCameraId, quality)
- val videoSupportedResolutions = getVideoSupportedResolutions()
- val isResolutionSupported = videoSupportedResolutions.contains(profile.size())
-
- val profileProxy = camcorderProfileProvider.get(quality)
- if (isResolutionSupported) {
- assertThat(profileProxy!!.quality).isEqualTo(profile.quality)
- } else {
- assertThat(profileProxy).isNull()
- }
- }
-
- private fun getVideoSupportedResolutions(): Array<Size> {
- val mapCompat = StreamConfigurationMapCompat.toStreamConfigurationMapCompat(
- cameraCharacteristics[CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP]!!
- )
- return mapCompat.getOutputSizes(ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE)
- ?: emptyArray()
- }
-
- private fun CamcorderProfile.size() = Size(videoFrameWidth, videoFrameHeight)
-}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProviderTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProviderTest.kt
index 8a87d6a..4376357 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProviderTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProviderTest.kt
@@ -17,16 +17,18 @@
package androidx.camera.camera2.internal
import android.media.CamcorderProfile
-import android.media.EncoderProfiles.VideoProfile.YUV_420
import android.media.EncoderProfiles.VideoProfile.HDR_NONE
+import android.media.EncoderProfiles.VideoProfile.YUV_420
import android.os.Build
+import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks
+import androidx.camera.camera2.internal.compat.quirk.InvalidVideoProfilesQuirk
import androidx.camera.core.CameraSelector
import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy.BIT_DEPTH_8
import androidx.camera.testing.CameraUtil
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
-import org.junit.Assume
+import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
@@ -68,7 +70,6 @@
@Before
fun setup() {
- skipTestOnProblematicBuildsOfCuttlefishApi33()
assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
cameraId = CameraUtil.getCameraIdWithLensFacing(CameraSelector.LENS_FACING_BACK)!!
@@ -156,6 +157,7 @@
@Test
fun afterApi33_hasSameContentAsEncoderProfiles() {
assumeTrue(CamcorderProfile.hasProfile(quality))
+ skipTestOnDevicesWithProblematicBuild()
val profiles = CamcorderProfile.getAll(cameraId, quality)
val video = profiles!!.videoProfiles[0]
@@ -184,13 +186,14 @@
assertThat(audioProxy.profile).isEqualTo(audio.profile)
}
- // TODO: removes after b/265613005 is fixed
- private fun skipTestOnProblematicBuildsOfCuttlefishApi33() {
- // Skip test for b/265613005
- Assume.assumeFalse(
- "Cuttlefish has null VideoProfile issue. Unable to test.",
- Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 33 &&
- Build.ID.startsWith("TP1A")
+ private fun skipTestOnDevicesWithProblematicBuild() {
+ // Skip test for b/265613005 and b/223439995
+ val hasVideoProfilesQuirk = DeviceQuirks.get(InvalidVideoProfilesQuirk::class.java) != null
+ val isProblematicCuttlefishBuild =
+ Build.MODEL.contains("Cuttlefish") && Build.ID.startsWith("TP1A")
+ assumeFalse(
+ "Skip test with null VideoProfile issue. Unable to test.",
+ hasVideoProfilesQuirk || isProblematicCuttlefishBuild
)
}
}
\ No newline at end of file
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProvider.java
deleted file mode 100644
index 4ad7dd3..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CamcorderProfileProvider.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.camera.camera2.internal;
-
-import android.media.CamcorderProfile;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
-import androidx.camera.camera2.internal.compat.quirk.CamcorderProfileResolutionQuirk;
-import androidx.camera.camera2.internal.compat.quirk.CameraQuirks;
-import androidx.camera.camera2.internal.compat.workaround.CamcorderProfileResolutionValidator;
-import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProvider;
-import androidx.camera.core.impl.CamcorderProfileProxy;
-
-/** An implementation that provides the {@link CamcorderProfileProxy}. */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public class Camera2CamcorderProfileProvider implements CamcorderProfileProvider {
- private static final String TAG = "Camera2CamcorderProfileProvider";
-
- private final boolean mHasValidCameraId;
- private final int mCameraId;
- private final CamcorderProfileResolutionValidator mCamcorderProfileResolutionValidator;
-
- public Camera2CamcorderProfileProvider(@NonNull String cameraId,
- @NonNull CameraCharacteristicsCompat cameraCharacteristics) {
- boolean hasValidCameraId = false;
- int intCameraId = -1;
- try {
- intCameraId = Integer.parseInt(cameraId);
- hasValidCameraId = true;
- } catch (NumberFormatException e) {
- Logger.w(TAG, "Camera id is not an integer: " + cameraId
- + ", unable to create CamcorderProfileProvider");
- }
- mHasValidCameraId = hasValidCameraId;
- mCameraId = intCameraId;
- CamcorderProfileResolutionQuirk quirk = CameraQuirks.get(cameraId, cameraCharacteristics)
- .get(CamcorderProfileResolutionQuirk.class);
- mCamcorderProfileResolutionValidator = new CamcorderProfileResolutionValidator(quirk);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasProfile(int quality) {
- if (!mHasValidCameraId) {
- return false;
- }
-
- if (!CamcorderProfile.hasProfile(mCameraId, quality)) {
- return false;
- }
-
- if (mCamcorderProfileResolutionValidator.hasQuirk()) {
- // Only get profile when quirk exist for performance concern.
- CamcorderProfileProxy profile = getProfileInternal(quality);
- return mCamcorderProfileResolutionValidator.hasValidVideoResolution(profile);
- }
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable
- public CamcorderProfileProxy get(int quality) {
- if (!mHasValidCameraId) {
- return null;
- }
-
- if (!CamcorderProfile.hasProfile(mCameraId, quality)) {
- return null;
- }
-
- CamcorderProfileProxy profile = getProfileInternal(quality);
- if (!mCamcorderProfileResolutionValidator.hasValidVideoResolution(profile)) {
- return null;
- }
- return profile;
- }
-
- @Nullable
- @SuppressWarnings("deprecation")
- private CamcorderProfileProxy getProfileInternal(int quality) {
- CamcorderProfile profile = null;
- try {
- profile = CamcorderProfile.get(mCameraId, quality);
- } catch (RuntimeException e) {
- // CamcorderProfile.get() will throw
- // - RuntimeException if not able to retrieve camcorder profile params.
- // - IllegalArgumentException if quality is not valid.
- Logger.w(TAG, "Unable to get CamcorderProfile by quality: " + quality, e);
- }
- return profile != null ? CamcorderProfileProxy.fromCamcorderProfile(profile) : null;
- }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
index 4cb23e3..bc62ecf 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
@@ -27,10 +27,12 @@
import androidx.annotation.RequiresApi;
import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
import androidx.camera.camera2.internal.compat.CameraManagerCompat;
+import androidx.camera.camera2.internal.concurrent.Camera2CameraCoordinator;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.InitializationException;
import androidx.camera.core.Logger;
+import androidx.camera.core.concurrent.CameraCoordinator;
import androidx.camera.core.impl.CameraFactory;
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.CameraStateRegistry;
@@ -50,6 +52,7 @@
public final class Camera2CameraFactory implements CameraFactory {
private static final String TAG = "Camera2CameraFactory";
private static final int DEFAULT_ALLOWED_CONCURRENT_OPEN_CAMERAS = 1;
+ private final CameraCoordinator mCameraCoordinator;
private final CameraThreadConfig mThreadConfig;
private final CameraStateRegistry mCameraStateRegistry;
private final CameraManagerCompat mCameraManager;
@@ -69,6 +72,7 @@
List<String> optimizedCameraIds = CameraSelectionOptimizer.getSelectedAvailableCameraIds(
this, availableCamerasSelector);
mAvailableCameraIds = getBackwardCompatibleCameraIds(optimizedCameraIds);
+ mCameraCoordinator = new Camera2CameraCoordinator(mCameraManager);
}
@Override
@@ -110,6 +114,12 @@
@NonNull
@Override
+ public CameraCoordinator getCameraCoordinator() {
+ return mCameraCoordinator;
+ }
+
+ @NonNull
+ @Override
public CameraManagerCompat getCameraManager() {
return mCameraManager;
}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
index df26798..a79d18b 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
@@ -54,9 +54,9 @@
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.Logger;
import androidx.camera.core.ZoomState;
-import androidx.camera.core.impl.CamcorderProfileProvider;
import androidx.camera.core.impl.CameraCaptureCallback;
import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.EncoderProfilesProvider;
import androidx.camera.core.impl.ImageOutputConfig.RotationValue;
import androidx.camera.core.impl.Quirks;
import androidx.camera.core.impl.Timebase;
@@ -115,7 +115,7 @@
@NonNull
private final Quirks mCameraQuirks;
@NonNull
- private final CamcorderProfileProvider mCamera2CamcorderProfileProvider;
+ private final EncoderProfilesProvider mCamera2EncoderProfilesProvider;
@NonNull
private final CameraManagerCompat mCameraManager;
@@ -131,8 +131,7 @@
mCameraCharacteristicsCompat = cameraManager.getCameraCharacteristicsCompat(mCameraId);
mCamera2CameraInfo = new Camera2CameraInfo(this);
mCameraQuirks = CameraQuirks.get(cameraId, mCameraCharacteristicsCompat);
- mCamera2CamcorderProfileProvider = new Camera2CamcorderProfileProvider(cameraId,
- mCameraCharacteristicsCompat);
+ mCamera2EncoderProfilesProvider = new Camera2EncoderProfilesProvider(cameraId);
mCameraStateLiveData = new RedirectableLiveData<>(
CameraState.create(CameraState.Type.CLOSED));
}
@@ -401,8 +400,8 @@
/** {@inheritDoc} */
@NonNull
@Override
- public CamcorderProfileProvider getCamcorderProfileProvider() {
- return mCamera2CamcorderProfileProvider;
+ public EncoderProfilesProvider getEncoderProfilesProvider() {
+ return mCamera2EncoderProfilesProvider;
}
@NonNull
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProvider.java
index a35596c..5103731 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProvider.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2EncoderProfilesProvider.java
@@ -24,6 +24,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks;
+import androidx.camera.camera2.internal.compat.quirk.InvalidVideoProfilesQuirk;
import androidx.camera.core.Logger;
import androidx.camera.core.impl.EncoderProfilesProvider;
import androidx.camera.core.impl.EncoderProfilesProxy;
@@ -80,23 +82,44 @@
}
@Nullable
- @SuppressWarnings("deprecation")
private EncoderProfilesProxy getProfilesInternal(int quality) {
if (Build.VERSION.SDK_INT >= 31) {
EncoderProfiles profiles = Api31Impl.getAll(mCameraId, quality);
- return profiles != null ? EncoderProfilesProxyCompat.from(profiles) : null;
- } else {
- CamcorderProfile profile = null;
- try {
- profile = CamcorderProfile.get(mIntCameraId, quality);
- } catch (RuntimeException e) {
- // CamcorderProfile.get() will throw
- // - RuntimeException if not able to retrieve camcorder profile params.
- // - IllegalArgumentException if quality is not valid.
- Logger.w(TAG, "Unable to get CamcorderProfile by quality: " + quality, e);
+ if (profiles == null) {
+ return null;
}
- return profile != null ? EncoderProfilesProxyCompat.from(profile) : null;
+
+ boolean isVideoProfilesInvalid = DeviceQuirks.get(InvalidVideoProfilesQuirk.class)
+ != null;
+ if (isVideoProfilesInvalid) {
+ Logger.d(TAG, "EncoderProfiles contains invalid video profiles, use "
+ + "CamcorderProfile to create EncoderProfilesProxy.");
+ } else {
+ try {
+ return EncoderProfilesProxyCompat.from(profiles);
+ } catch (NullPointerException e) {
+ Logger.w(TAG, "Failed to create EncoderProfilesProxy, EncoderProfiles might "
+ + " contain invalid video profiles. Use CamcorderProfile instead.", e);
+ }
+ }
}
+
+ return createProfilesFromCamcorderProfile(quality);
+ }
+
+ @Nullable
+ @SuppressWarnings("deprecation")
+ private EncoderProfilesProxy createProfilesFromCamcorderProfile(int quality) {
+ CamcorderProfile profile = null;
+ try {
+ profile = CamcorderProfile.get(mIntCameraId, quality);
+ } catch (RuntimeException e) {
+ // CamcorderProfile.get() will throw
+ // - RuntimeException if not able to retrieve camcorder profile params.
+ // - IllegalArgumentException if quality is not valid.
+ Logger.w(TAG, "Unable to get CamcorderProfile by quality: " + quality, e);
+ }
+ return profile != null ? EncoderProfilesProxyCompat.from(profile) : null;
}
@RequiresApi(31)
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirk.java
index 86a0c16..abeb482 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirk.java
@@ -25,8 +25,8 @@
import androidx.annotation.RequiresApi;
import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
import androidx.camera.camera2.internal.compat.StreamConfigurationMapCompat;
-import androidx.camera.camera2.internal.compat.workaround.CamcorderProfileResolutionValidator;
import androidx.camera.core.Logger;
+import androidx.camera.core.impl.EncoderProfilesResolutionValidator;
import androidx.camera.core.impl.ImageFormatConstants;
import androidx.camera.core.impl.quirk.ProfileResolutionQuirk;
@@ -52,7 +52,7 @@
* resolution is contained in the list returned.
* Device(s): All legacy devices
* @see CamcorderProfile#hasProfile
- * @see CamcorderProfileResolutionValidator
+ * @see EncoderProfilesResolutionValidator
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
public class CamcorderProfileResolutionQuirk implements ProfileResolutionQuirk {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
index 45aa1b8..ed4d62e 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
@@ -86,6 +86,9 @@
if (ExtraSupportedOutputSizeQuirk.load()) {
quirks.add(new ExtraSupportedOutputSizeQuirk());
}
+ if (InvalidVideoProfilesQuirk.load()) {
+ quirks.add(new InvalidVideoProfilesQuirk());
+ }
return quirks;
}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java
new file mode 100644
index 0000000..bb4c9e1
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/InvalidVideoProfilesQuirk.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2023 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.camera.camera2.internal.compat.quirk;
+
+import android.media.EncoderProfiles;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.Quirk;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Quirk denoting the video profile list returns by {@link EncoderProfiles} is invalid.
+ *
+ * <p>QuirkSummary
+ * Bug Id: 267727595
+ * Description: When using {@link EncoderProfiles} on TP1A or TD1A builds of Android API 33,
+ * {@link EncoderProfiles#getVideoProfiles()} returns a list with size one, but
+ * the single value in the list is null. This is not the expected behavior, and
+ * makes {@link EncoderProfiles} lack of video information.
+ * Device(s): Pixel 4 and above pixel devices with TP1A or TD1A builds (API 33).
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class InvalidVideoProfilesQuirk implements Quirk {
+
+ static final List<String> AFFECTED_MODELS = Arrays.asList(
+ "pixel 4",
+ "pixel 4a",
+ "pixel 4 xl",
+ "pixel 5",
+ "pixel 5a",
+ "pixel 6",
+ "pixel 6a",
+ "pixel 6 pro",
+ "pixel 7",
+ "pixel 7 pro"
+ );
+
+ static boolean load() {
+ return isAffectedModel() && isAffectedBuild();
+ }
+
+ private static boolean isAffectedModel() {
+ return AFFECTED_MODELS.contains(Build.MODEL.toLowerCase(Locale.US));
+ }
+
+ private static boolean isAffectedBuild() {
+ return isTp1aBuild() || isTd1aBuild();
+ }
+
+ private static boolean isTp1aBuild() {
+ return Build.ID.startsWith("TP1A");
+ }
+
+ private static boolean isTd1aBuild() {
+ return Build.ID.startsWith("TD1A");
+ }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidator.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidator.java
deleted file mode 100644
index e63fcda..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidator.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.camera.camera2.internal.compat.workaround;
-
-import android.media.CamcorderProfile;
-import android.util.Size;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.internal.compat.quirk.CamcorderProfileResolutionQuirk;
-import androidx.camera.core.impl.CamcorderProfileProxy;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Validates the video resolution of {@link CamcorderProfile}.
- *
- * @see CamcorderProfileResolutionQuirk
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public class CamcorderProfileResolutionValidator {
-
- private final CamcorderProfileResolutionQuirk mQuirk;
- private final Set<Size> mSupportedResolutions;
-
- public CamcorderProfileResolutionValidator(@Nullable CamcorderProfileResolutionQuirk quirk) {
- mQuirk = quirk;
- mSupportedResolutions = quirk != null ? new HashSet<>(quirk.getSupportedResolutions()) :
- Collections.emptySet();
- }
-
- /** Checks if this validator contains quirk. */
- public boolean hasQuirk() {
- return mQuirk != null;
- }
-
- /** Checks if the video resolution of CamcorderProfile is valid. */
- public boolean hasValidVideoResolution(@Nullable CamcorderProfileProxy profile) {
- if (profile == null) {
- return false;
- }
-
- if (mQuirk == null) {
- // Quirk doesn't exist, always valid.
- return true;
- }
-
- Size videoSize = new Size(profile.getVideoFrameWidth(), profile.getVideoFrameHeight());
- return mSupportedResolutions.contains(videoSize);
- }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java
new file mode 100644
index 0000000..e1f4760
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2023 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.camera.camera2.internal.concurrent;
+
+import android.hardware.camera2.CameraCharacteristics;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
+import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
+import androidx.camera.camera2.internal.compat.CameraManagerCompat;
+import androidx.camera.camera2.interop.Camera2CameraInfo;
+import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
+import androidx.camera.core.CameraInfo;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.Logger;
+import androidx.camera.core.concurrent.CameraCoordinator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation for {@link CameraCoordinator}.
+ */
+@RequiresApi(21)
+public class Camera2CameraCoordinator implements CameraCoordinator {
+
+ private static final String TAG = "Camera2CameraCoordinator";
+
+ @NonNull private final CameraManagerCompat mCameraManager;
+ @NonNull private Map<String, String> mConcurrentCameraIdMap;
+ @NonNull private Set<Set<String>> mConcurrentCameraIds;
+ @NonNull private final List<ConcurrentCameraModeListener> mConcurrentCameraModeListeners;
+
+ private boolean mIsConcurrentCameraModeOn;
+
+ public Camera2CameraCoordinator(@NonNull CameraManagerCompat cameraManager) {
+ mCameraManager = cameraManager;
+ mConcurrentCameraIdMap = new HashMap<>();
+ mConcurrentCameraIds = new HashSet<>();
+ mConcurrentCameraModeListeners = new ArrayList<>();
+ }
+
+ @Override
+ public void init() {
+ mConcurrentCameraIds = retrieveConcurrentCameraIds(mCameraManager);
+ for (Set<String> concurrentCameraIdList: mConcurrentCameraIds) {
+ List<String> cameraIdList = new ArrayList<>(concurrentCameraIdList);
+
+ // TODO(b/268531569): enumerate concurrent camera ids and convert to a map for
+ // paired camera id lookup.
+ mConcurrentCameraIdMap.put(cameraIdList.get(0), cameraIdList.get(1));
+ mConcurrentCameraIdMap.put(cameraIdList.get(1), cameraIdList.get(0));
+ }
+ }
+
+ @NonNull
+ @Override
+ public List<List<CameraSelector>> getConcurrentCameraSelectors() {
+ List<List<CameraSelector>> concurrentCameraSelectorLists = new ArrayList<>();
+ for (Set<String> concurrentCameraIdList: mConcurrentCameraIds) {
+ List<CameraSelector> cameraSelectors = new ArrayList<>();
+ for (String concurrentCameraId : concurrentCameraIdList) {
+ cameraSelectors.add(createCameraSelectorById(mCameraManager, concurrentCameraId));
+ }
+ concurrentCameraSelectorLists.add(cameraSelectors);
+ }
+ return concurrentCameraSelectorLists;
+ }
+
+ @Nullable
+ @Override
+ public String getPairedConcurrentCameraId(@NonNull String cameraId) {
+ if (mConcurrentCameraIdMap.containsKey(cameraId)) {
+ return mConcurrentCameraIdMap.get(cameraId);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isConcurrentCameraModeOn() {
+ return mIsConcurrentCameraModeOn;
+ }
+
+ @Override
+ public void setConcurrentCameraMode(boolean isConcurrentCameraModeOn) {
+ if (isConcurrentCameraModeOn != mIsConcurrentCameraModeOn) {
+ for (ConcurrentCameraModeListener listener : mConcurrentCameraModeListeners) {
+ listener.notifyConcurrentCameraModeUpdated(isConcurrentCameraModeOn);
+ }
+ }
+ mIsConcurrentCameraModeOn = isConcurrentCameraModeOn;
+ }
+
+ @Override
+ public void addListener(@NonNull ConcurrentCameraModeListener listener) {
+ mConcurrentCameraModeListeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(@NonNull ConcurrentCameraModeListener listener) {
+ mConcurrentCameraModeListeners.remove(listener);
+ }
+
+ @NonNull
+ private static Set<Set<String>> retrieveConcurrentCameraIds(
+ @NonNull CameraManagerCompat cameraManager) {
+ Set<Set<String>> map = new HashSet<>();
+ try {
+ map = cameraManager.getConcurrentCameraIds();
+ } catch (CameraAccessExceptionCompat e) {
+ Logger.e(TAG, "Failed to get concurrent camera ids");
+ }
+ return map;
+ }
+
+ @OptIn(markerClass = ExperimentalCamera2Interop.class)
+ private static CameraSelector createCameraSelectorById(
+ @NonNull CameraManagerCompat cameraManager,
+ @NonNull String cameraId) {
+ CameraSelector.Builder builder =
+ new CameraSelector.Builder().addCameraFilter(cameraInfos -> {
+ for (CameraInfo cameraInfo : cameraInfos) {
+ if (cameraId.equals(Camera2CameraInfo.from(cameraInfo).getCameraId())) {
+ return Collections.singletonList(cameraInfo);
+ }
+ }
+
+ throw new IllegalArgumentException("No camera can be find for id: " + cameraId);
+ });
+
+ try {
+ CameraCharacteristicsCompat cameraCharacteristics =
+ cameraManager.getCameraCharacteristicsCompat(cameraId);
+ Integer cameraLensFacing = cameraCharacteristics.get(
+ CameraCharacteristics.LENS_FACING);
+ builder.requireLensFacing(cameraLensFacing);
+ } catch (CameraAccessExceptionCompat e) {
+ throw new RuntimeException(e);
+ }
+
+ return builder.build();
+ }
+}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
index 760a818..1a822dd 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.kt
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package androidx.camera.camera2.internal
import android.content.Context
@@ -21,6 +22,10 @@
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraMetadata
import android.media.CamcorderProfile
+import android.media.CamcorderProfile.QUALITY_1080P
+import android.media.CamcorderProfile.QUALITY_2160P
+import android.media.CamcorderProfile.QUALITY_480P
+import android.media.CamcorderProfile.QUALITY_720P
import android.os.Build
import android.util.Pair
import android.util.Range
@@ -62,16 +67,16 @@
import androidx.camera.core.impl.utils.CompareSizesByArea
import androidx.camera.core.impl.utils.executor.CameraXExecutors
import androidx.camera.core.internal.utils.SizeUtil.RESOLUTION_VGA
-import androidx.camera.testing.CamcorderProfileUtil
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraXUtil
import androidx.camera.testing.Configs
+import androidx.camera.testing.EncoderProfilesUtil
import androidx.camera.testing.SurfaceTextureProvider
import androidx.camera.testing.SurfaceTextureProvider.SurfaceTextureCallback
-import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeEncoderProfilesProvider
import androidx.camera.testing.fakes.FakeUseCaseConfig
import androidx.camera.video.FallbackStrategy
import androidx.camera.video.MediaSpec
@@ -145,18 +150,17 @@
CamcorderProfile::class.java
)
private var cameraManagerCompat: CameraManagerCompat? = null
- private val profileUhd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_2160P, RECORD_SIZE.width, RECORD_SIZE.height
+ private val profileUhd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ RECORD_SIZE.width, RECORD_SIZE.height
)
- private val profileFhd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_1080P, 1920, 1080
+ private val profileFhd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ 1920, 1080
)
- private val profileHd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_720P, PREVIEW_SIZE.width, PREVIEW_SIZE.height
+ private val profileHd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ PREVIEW_SIZE.width, PREVIEW_SIZE.height
)
- private val profileSd = CamcorderProfileUtil.createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_480P, RESOLUTION_VGA.width,
- RESOLUTION_VGA.height
+ private val profileSd = EncoderProfilesUtil.createFakeEncoderProfilesProxy(
+ RESOLUTION_VGA.width, RESOLUTION_VGA.height
)
private val context = ApplicationProvider.getApplicationContext<Context>()
private var cameraFactory: FakeCameraFactory? = null
@@ -3052,15 +3056,12 @@
sensorOrientation,
CameraCharacteristics.LENS_FACING_BACK
).apply {
- camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
- .addProfile(
- CamcorderProfileUtil.asHighQuality(profileUhd),
- profileUhd,
- profileFhd,
- profileHd,
- profileSd,
- CamcorderProfileUtil.asLowQuality(profileSd)
- ).build()
+ encoderProfilesProvider = FakeEncoderProfilesProvider.Builder()
+ .add(QUALITY_2160P, profileUhd)
+ .add(QUALITY_1080P, profileFhd)
+ .add(QUALITY_720P, profileHd)
+ .add(QUALITY_480P, profileSd)
+ .build()
}
cameraFactory = FakeCameraFactory().apply {
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirkTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirkTest.kt
index f052a5a..baecee6 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirkTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/quirk/CamcorderProfileResolutionQuirkTest.kt
@@ -23,8 +23,8 @@
import android.os.Build
import android.util.Size
import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_1080P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_2160P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_1080P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_2160P
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -40,10 +40,10 @@
@RunWith(RobolectricTestRunner::class)
@DoNotInstrument
@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class CamcorderProfileResolutionQuirkTest {
+class CamcorderProfileResolutionQuirkTest {
@Test
- public fun loadByHardwareLevel() {
+ fun loadByHardwareLevel() {
var cameraCharacteristicsCompat =
createCameraCharacteristicsCompat(CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
assertThat(CamcorderProfileResolutionQuirk.load(cameraCharacteristicsCompat)).isFalse()
@@ -62,7 +62,7 @@
}
@Test
- public fun canGetCorrectSupportedSizes() {
+ fun canGetCorrectSupportedSizes() {
val cameraCharacteristicsCompat =
createCameraCharacteristicsCompat(
supportedSizes = arrayOf(
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidatorTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidatorTest.kt
deleted file mode 100644
index 5787efb..0000000
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/CamcorderProfileResolutionValidatorTest.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.camera.camera2.internal.compat.workaround
-
-import android.graphics.SurfaceTexture
-import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.params.StreamConfigurationMap
-import android.os.Build
-import android.util.Size
-import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat
-import androidx.camera.camera2.internal.compat.quirk.CamcorderProfileResolutionQuirk
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_2160P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_720P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_2160P
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers
-import org.mockito.Mockito
-import org.mockito.Mockito.`when`
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.internal.DoNotInstrument
-import org.robolectric.shadow.api.Shadow
-import org.robolectric.shadows.ShadowCameraCharacteristics
-
-@RunWith(RobolectricTestRunner::class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class CamcorderProfileResolutionValidatorTest {
-
- @Test
- public fun noQuirk_alwaysValid() {
- val validator = CamcorderProfileResolutionValidator(null)
-
- assertThat(validator.hasValidVideoResolution(PROFILE_2160P)).isTrue()
- assertThat(validator.hasValidVideoResolution(PROFILE_720P)).isTrue()
- }
-
- @Test
- public fun hasQuirk_shouldCheckSupportedResolutions() {
- val cameraCharacteristicsCompat = createCameraCharacteristicsCompat(
- supportedResolution = arrayOf(RESOLUTION_2160P)
- )
- val quirk = CamcorderProfileResolutionQuirk(cameraCharacteristicsCompat)
- val validator = CamcorderProfileResolutionValidator(quirk)
-
- assertThat(validator.hasValidVideoResolution(PROFILE_2160P)).isTrue()
- assertThat(validator.hasValidVideoResolution(PROFILE_720P)).isFalse()
- }
-
- @Test
- public fun nullProfile_notValid() {
- val cameraCharacteristicsCompat = createCameraCharacteristicsCompat(
- supportedResolution = arrayOf(RESOLUTION_2160P)
- )
- val quirk = CamcorderProfileResolutionQuirk(cameraCharacteristicsCompat)
- val validator = CamcorderProfileResolutionValidator(quirk)
-
- assertThat(validator.hasValidVideoResolution(null)).isFalse()
- }
-
- private fun createCameraCharacteristicsCompat(
- supportedResolution: Array<Size> = emptyArray()
- ): CameraCharacteristicsCompat {
- val characteristics = ShadowCameraCharacteristics.newCameraCharacteristics()
- val shadowCharacteristics = Shadow.extract<ShadowCameraCharacteristics>(characteristics)
-
- val mockMap = Mockito.mock(StreamConfigurationMap::class.java)
-
- // Before Android 23, use {@link SurfaceTexture} will finally mapped to 0x22 in
- // StreamConfigurationMap to retrieve the output sizes information.
- `when`(mockMap.getOutputSizes(ArgumentMatchers.any<Class<SurfaceTexture>>()))
- .thenReturn(supportedResolution)
- `when`(mockMap.getOutputSizes(ArgumentMatchers.anyInt()))
- .thenReturn(supportedResolution)
-
- shadowCharacteristics.set(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP, mockMap)
-
- return CameraCharacteristicsCompat.toCameraCharacteristicsCompat(characteristics)
- }
-}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt
new file mode 100644
index 0000000..4eae589
--- /dev/null
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2023 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.camera.camera2.internal.concurrent
+
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CameraDevice
+import android.hardware.camera2.CameraManager
+import android.os.Build
+import androidx.camera.camera2.internal.compat.CameraManagerCompat
+import androidx.camera.core.concurrent.CameraCoordinator
+import androidx.camera.core.impl.utils.MainThreadAsyncHandler
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(
+ minSdk = Build.VERSION_CODES.LOLLIPOP,
+ instrumentedPackages = ["androidx.camera.camera2.internal"]
+)
+class Camera2CameraCoordinatorTest {
+
+ private lateinit var cameraCoordinator: CameraCoordinator
+
+ @Before
+ fun setup() {
+ val fakeCameraImpl = FakeCameraManagerImpl()
+ val cameraCharacteristics0 = mock(CameraCharacteristics::class.java)
+ Mockito.`when`(cameraCharacteristics0.get(CameraCharacteristics.LENS_FACING))
+ .thenReturn(CameraCharacteristics.LENS_FACING_BACK)
+ val cameraCharacteristics1 = mock(CameraCharacteristics::class.java)
+ Mockito.`when`(cameraCharacteristics1.get(CameraCharacteristics.LENS_FACING))
+ .thenReturn(CameraCharacteristics.LENS_FACING_FRONT)
+ fakeCameraImpl.addCamera("0", cameraCharacteristics0)
+ fakeCameraImpl.addCamera("1", cameraCharacteristics1)
+ cameraCoordinator = Camera2CameraCoordinator(CameraManagerCompat.from(fakeCameraImpl))
+ cameraCoordinator.init()
+ }
+
+ @Test
+ fun getConcurrentCameraSelectors() {
+ assertThat(cameraCoordinator.concurrentCameraSelectors).isNotEmpty()
+ assertThat(cameraCoordinator.concurrentCameraSelectors[0]).isNotEmpty()
+ assertThat(cameraCoordinator.concurrentCameraSelectors[0][0].lensFacing)
+ .isEqualTo(CameraCharacteristics.LENS_FACING_BACK)
+ assertThat(cameraCoordinator.concurrentCameraSelectors[0][1].lensFacing)
+ .isEqualTo(CameraCharacteristics.LENS_FACING_FRONT)
+ }
+
+ @Test
+ fun getPairedCameraId() {
+ assertThat(cameraCoordinator.getPairedConcurrentCameraId("0")).isEqualTo("1")
+ assertThat(cameraCoordinator.getPairedConcurrentCameraId("1")).isEqualTo("0")
+ }
+
+ @Test
+ fun setAndIsConcurrentCameraMode() {
+ assertThat(cameraCoordinator.isConcurrentCameraModeOn).isFalse()
+ cameraCoordinator.setConcurrentCameraMode(true)
+ assertThat(cameraCoordinator.isConcurrentCameraModeOn).isTrue()
+ cameraCoordinator.setConcurrentCameraMode(false)
+ assertThat(cameraCoordinator.isConcurrentCameraModeOn).isFalse()
+ }
+
+ @Test
+ fun addAndRemoveListener() {
+ val listener = mock(CameraCoordinator.ConcurrentCameraModeListener::class.java)
+ cameraCoordinator.addListener(listener)
+ cameraCoordinator.setConcurrentCameraMode(true)
+ verify(listener).notifyConcurrentCameraModeUpdated(true)
+ cameraCoordinator.setConcurrentCameraMode(false)
+ verify(listener).notifyConcurrentCameraModeUpdated(false)
+
+ reset(listener)
+ cameraCoordinator.removeListener(listener)
+ cameraCoordinator.setConcurrentCameraMode(true)
+ verify(listener, never()).notifyConcurrentCameraModeUpdated(true)
+ }
+
+ private class FakeCameraManagerImpl : CameraManagerCompat.CameraManagerCompatImpl {
+
+ private val mCameraManagerImpl = CameraManagerCompat.CameraManagerCompatImpl.from(
+ ApplicationProvider.getApplicationContext(),
+ MainThreadAsyncHandler.getInstance()
+ )
+
+ private val mCameraIdCharacteristics = HashMap<String, CameraCharacteristics>()
+
+ fun addCamera(
+ cameraId: String,
+ cameraCharacteristics: CameraCharacteristics
+ ) {
+ mCameraIdCharacteristics[cameraId] = cameraCharacteristics
+ }
+
+ override fun getCameraIdList(): Array<String> {
+ return mCameraIdCharacteristics.keys.toTypedArray()
+ }
+
+ override fun getConcurrentCameraIds(): MutableSet<MutableSet<String>> {
+ return mutableSetOf(mCameraIdCharacteristics.keys)
+ }
+
+ override fun registerAvailabilityCallback(
+ executor: Executor,
+ callback: CameraManager.AvailabilityCallback
+ ) {
+ }
+
+ override fun unregisterAvailabilityCallback(callback: CameraManager.AvailabilityCallback) {
+ }
+
+ override fun getCameraCharacteristics(cameraId: String): CameraCharacteristics {
+ return mCameraIdCharacteristics[cameraId]!!
+ }
+
+ override fun openCamera(
+ cameraId: String,
+ executor: Executor,
+ callback: CameraDevice.StateCallback
+ ) {
+ }
+
+ override fun getCameraManager(): CameraManager {
+ return mCameraManagerImpl.cameraManager
+ }
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/CamcorderProfileProxyTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/CamcorderProfileProxyTest.kt
deleted file mode 100644
index ce31a22..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/CamcorderProfileProxyTest.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.camera.core.impl
-
-import android.media.CamcorderProfile
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assume.assumeTrue
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-@Suppress("DEPRECATION")
-@SdkSuppress(minSdkVersion = 21)
-public class CamcorderProfileProxyTest {
-
- @Test
- public fun createInstance() {
- // QUALITY_HIGH is guaranteed to be supported.
- assumeTrue(CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH))
-
- val profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)
- val profileProxy = CamcorderProfileProxy.fromCamcorderProfile(profile)
-
- assertThat(profileProxy.duration).isEqualTo(profile.duration)
- assertThat(profileProxy.quality).isEqualTo(profile.quality)
- assertThat(profileProxy.fileFormat).isEqualTo(profile.fileFormat)
- assertThat(profileProxy.videoCodec).isEqualTo(profile.videoCodec)
- assertThat(profileProxy.videoBitRate).isEqualTo(profile.videoBitRate)
- assertThat(profileProxy.videoFrameRate).isEqualTo(profile.videoFrameRate)
- assertThat(profileProxy.videoFrameWidth).isEqualTo(profile.videoFrameWidth)
- assertThat(profileProxy.videoFrameHeight).isEqualTo(profile.videoFrameHeight)
- assertThat(profileProxy.audioCodec).isEqualTo(profile.audioCodec)
- assertThat(profileProxy.audioBitRate).isEqualTo(profile.audioBitRate)
- assertThat(profileProxy.audioSampleRate).isEqualTo(profile.audioSampleRate)
- assertThat(profileProxy.audioChannels).isEqualTo(profile.audioChannels)
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraEffect.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraEffect.java
index 58183ca..7416ee1 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraEffect.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraEffect.java
@@ -17,11 +17,15 @@
import static androidx.core.util.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
+import androidx.camera.core.processing.SurfaceProcessorInternal;
+import androidx.camera.core.processing.SurfaceProcessorWithExecutor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -195,4 +199,21 @@
public ImageProcessor getImageProcessor() {
return mImageProcessor;
}
+
+ // --- Internal methods ---
+
+ /**
+ * Creates a {@link SurfaceProcessorInternal} instance.
+ *
+ * <p>Throws {@link IllegalArgumentException} if the effect does not contain a
+ * {@link SurfaceProcessor}.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @NonNull
+ public SurfaceProcessorInternal createSurfaceProcessorInternal() {
+ return new SurfaceProcessorWithExecutor(requireNonNull(getSurfaceProcessor()),
+ getExecutor());
+ }
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index d5f8971..75bbe4f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -340,9 +340,6 @@
@SuppressWarnings("WeakerAccess")
final Executor mSequentialIoExecutor;
- @Nullable
- private CameraEffect mCameraEffect;
-
/**
* Creates a new image capture use case from the given configuration.
*
@@ -1664,7 +1661,7 @@
Size resolution = streamSpec.getResolution();
checkState(mImagePipeline == null);
- mImagePipeline = new ImagePipeline(config, resolution, mCameraEffect);
+ mImagePipeline = new ImagePipeline(config, resolution, getEffect());
if (mTakePictureManager == null) {
// mTakePictureManager is reused when the Surface is reset.
@@ -1805,27 +1802,6 @@
return mImagePipeline != null && mTakePictureManager != null;
}
- /**
- * @hide
- */
- @MainThread
- @RestrictTo(Scope.LIBRARY_GROUP)
- public void setEffect(@Nullable CameraEffect cameraEffect) {
- checkMainThread();
- mCameraEffect = cameraEffect;
- }
-
- /**
- * @hide
- */
- @MainThread
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Nullable
- public CameraEffect getEffect() {
- checkMainThread();
- return mCameraEffect;
- }
-
@VisibleForTesting
@NonNull
TakePictureManager getTakePictureManager() {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index c2af128..72331e6 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -82,12 +82,10 @@
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.camera.core.internal.TargetConfig;
import androidx.camera.core.internal.ThreadConfig;
import androidx.camera.core.processing.Node;
import androidx.camera.core.processing.SurfaceEdge;
-import androidx.camera.core.processing.SurfaceProcessorInternal;
import androidx.camera.core.processing.SurfaceProcessorNode;
import androidx.core.util.Consumer;
import androidx.lifecycle.LifecycleOwner;
@@ -191,9 +189,6 @@
private Size mSurfaceSize;
@Nullable
- private SurfaceProcessorInternal mSurfaceProcessor;
-
- @Nullable
private SurfaceProcessorNode mNode;
/**
@@ -213,7 +208,7 @@
@NonNull StreamSpec streamSpec) {
// Build pipeline with node if processor is set. Eventually we will move all the code to
// createPipelineWithNode.
- if (mSurfaceProcessor != null) {
+ if (getEffect() != null) {
return createPipelineWithNode(cameraId, config, streamSpec);
}
@@ -251,14 +246,13 @@
@NonNull StreamSpec streamSpec) {
// Check arguments
checkMainThread();
- checkNotNull(mSurfaceProcessor);
- CameraInternal camera = getCamera();
- checkNotNull(camera);
+ CameraEffect effect = requireNonNull(getEffect());
+ CameraInternal camera = requireNonNull(getCamera());
clearPipeline();
// Create nodes and edges.
- mNode = new SurfaceProcessorNode(camera, mSurfaceProcessor);
+ mNode = new SurfaceProcessorNode(camera, effect.createSurfaceProcessorInternal());
// Make sure the previously created camera edge is cleared before creating a new one.
checkState(mCameraEdge == null);
mCameraEdge = new SurfaceEdge(
@@ -311,31 +305,6 @@
}
/**
- * Sets a {@link SurfaceProcessorInternal}.
- *
- * <p>Internal API invoked by {@link CameraUseCaseAdapter}. {@link #createPipeline} uses the
- * value to setup post-processing pipeline.
- *
- * @hide
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- public void setProcessor(@Nullable SurfaceProcessorInternal surfaceProcessor) {
- mSurfaceProcessor = surfaceProcessor;
- }
-
- /**
- * Gets the {@link SurfaceProcessorInternal} for testing.
- *
- * @hide
- */
- @Nullable
- @VisibleForTesting
- @RestrictTo(Scope.LIBRARY_GROUP)
- public SurfaceProcessorInternal getProcessor() {
- return mSurfaceProcessor;
- }
-
- /**
* Creates previously allocated {@link DeferrableSurface} include those allocated by nodes.
*/
private void clearPipeline() {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index ea17bcd..47c501d 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -147,6 +147,9 @@
@GuardedBy("mCameraLock")
private CameraInternal mCamera;
+ @Nullable
+ private CameraEffect mEffect;
+
////////////////////////////////////////////////////////////////////////////////////////////
// [UseCase attached dynamic] - Can change but is only available when the UseCase is attached.
////////////////////////////////////////////////////////////////////////////////////////////
@@ -791,6 +794,27 @@
}
/**
+ * Sets the {@link CameraEffect} associated with this use case.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ public void setEffect(@Nullable CameraEffect effect) {
+ mEffect = effect;
+ }
+
+ /**
+ * Gets the {@link CameraEffect} associated with this use case.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public CameraEffect getEffect() {
+ return mEffect;
+ }
+
+ /**
* Sets whether the producer writes camera transform to the {@link Surface}.
*
* @hide
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java b/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java
new file mode 100644
index 0000000..7ade18a
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2023 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.camera.core.concurrent;
+
+
+import android.hardware.camera2.CameraManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.impl.CameraStateRegistry;
+
+import java.util.List;
+
+/**
+ * Coordinator for concurrent camera.
+ *
+ * <p>It coordinates the order of camera device open and camera capture session configuration.
+ * All camera devices intended to be operated concurrently, must be opened before configuring
+ * sessions on any of the camera devices.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RequiresApi(21)
+public interface CameraCoordinator {
+
+ /**
+ * Initializes the map for concurrent camera ids and convert camera ids to camera selectors.
+ */
+ void init();
+
+ /**
+ * Returns concurrent camera selectors, which are converted from concurrent camera ids
+ * queried from {@link CameraManager#getConcurrentCameraIds()}.
+ *
+ * <p>This API is exposed to external users to select one combination of supported concurrent
+ * {@link CameraSelector}s to bind.
+ *
+ * @return List of list of {@link CameraSelector}.
+ */
+ @NonNull
+ List<List<CameraSelector>> getConcurrentCameraSelectors();
+
+ /**
+ * Returns paired camera id in concurrent mode.
+ *
+ * <p>The paired camera id dictionary is constructed when {@link CameraCoordinator#init()} is
+ * called. This internal API is used to look up paired camera id when coordinating device
+ * open and session config in {@link CameraStateRegistry}. Currently only dual cameras will
+ * be supported in concurrent mode.
+ *
+ * @param cameraId camera id.
+ * @return The paired camera id if exists or null if paired camera not exists.
+ */
+ @Nullable
+ String getPairedConcurrentCameraId(@NonNull String cameraId);
+
+ /**
+ * Returns concurrent camera mode.
+ *
+ * @return true if concurrent mode is on, otherwise returns false.
+ */
+ boolean isConcurrentCameraModeOn();
+
+ /**
+ * Sets concurrent camera mode.
+ *
+ * <p>This internal API will be called when user binds user cases to cameras, which will
+ * enable or disable concurrent camera mode based on the input config.
+ *
+ * @param enabled true if concurrent camera mode is enabled, otherwise false.
+ */
+ void setConcurrentCameraMode(boolean enabled);
+
+ /**
+ * Adds listener for concurrent camera mode update.
+ * @param listener
+ */
+ void addListener(@NonNull ConcurrentCameraModeListener listener);
+
+ /**
+ * Removes listener for concurrent camera mode update.
+ * @param listener
+ */
+ void removeListener(@NonNull ConcurrentCameraModeListener listener);
+
+ /**
+ * Interface for concurrent camera mode update.
+ *
+ * <p>Everytime user sets concurrent mode, the observer will be notified and update related
+ * states or parameters accordingly. E.g. in
+ * {@link CameraStateRegistry}, we will update the number of max
+ * allowed cameras if concurrent mode is set.
+ */
+ interface ConcurrentCameraModeListener {
+ void notifyConcurrentCameraModeUpdated(boolean isConcurrentCameraModeOn);
+ }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProvider.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProvider.java
deleted file mode 100644
index e8ed228..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProvider.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.camera.core.impl;
-
-import android.media.CamcorderProfile;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-/**
- * CamcorderProfileProvider is used to obtain the {@link CamcorderProfileProxy}.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public interface CamcorderProfileProvider {
-
- /**
- * Check if the quality is supported on this device.
- *
- * <p>The quality should be one of quality constants defined in {@link CamcorderProfile}.
- */
- boolean hasProfile(int quality);
-
- /**
- * Gets the {@link CamcorderProfileProxy} if the quality is supported on the device.
- *
- * <p>The quality should be one of quality constants defined in {@link CamcorderProfile}.
- *
- * @see #hasProfile(int)
- */
- @Nullable
- CamcorderProfileProxy get(int quality);
-
- /** An implementation that contains no data. */
- CamcorderProfileProvider EMPTY = new CamcorderProfileProvider() {
- @Override
- public boolean hasProfile(int quality) {
- return false;
- }
-
- @Nullable
- @Override
- public CamcorderProfileProxy get(int quality) {
- return null;
- }
- };
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java
deleted file mode 100644
index 325c32f..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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.camera.core.impl;
-
-import static android.media.MediaRecorder.AudioEncoder.AAC;
-import static android.media.MediaRecorder.AudioEncoder.AAC_ELD;
-import static android.media.MediaRecorder.AudioEncoder.AMR_NB;
-import static android.media.MediaRecorder.AudioEncoder.AMR_WB;
-import static android.media.MediaRecorder.AudioEncoder.HE_AAC;
-import static android.media.MediaRecorder.AudioEncoder.OPUS;
-import static android.media.MediaRecorder.AudioEncoder.VORBIS;
-import static android.media.MediaRecorder.VideoEncoder.H263;
-import static android.media.MediaRecorder.VideoEncoder.H264;
-import static android.media.MediaRecorder.VideoEncoder.HEVC;
-import static android.media.MediaRecorder.VideoEncoder.MPEG_4_SP;
-import static android.media.MediaRecorder.VideoEncoder.VP8;
-
-import android.media.CamcorderProfile;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.media.MediaRecorder;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-import com.google.auto.value.AutoValue;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * CamcorderProfileProxy defines the get methods that is mapping to the fields of
- * {@link CamcorderProfile}.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-@AutoValue
-public abstract class CamcorderProfileProxy {
-
- /** Constant representing no codec profile. */
- public static int CODEC_PROFILE_NONE = -1;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({H263, H264, HEVC, VP8, MPEG_4_SP, MediaRecorder.VideoEncoder.DEFAULT})
- @interface VideoEncoder {
- }
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({AAC, AAC_ELD, AMR_NB, AMR_WB, HE_AAC, OPUS, VORBIS,
- MediaRecorder.AudioEncoder.DEFAULT})
- @interface AudioEncoder {
- }
-
- /** Creates a CamcorderProfileProxy instance. */
- @NonNull
- public static CamcorderProfileProxy create(int duration,
- int quality,
- int fileFormat,
- @VideoEncoder int videoCodec,
- int videoBitRate,
- int videoFrameRate,
- int videoFrameWidth,
- int videoFrameHeight,
- @AudioEncoder int audioCodec,
- int audioBitRate,
- int audioSampleRate,
- int audioChannels) {
- return new AutoValue_CamcorderProfileProxy(
- duration,
- quality,
- fileFormat,
- videoCodec,
- videoBitRate,
- videoFrameRate,
- videoFrameWidth,
- videoFrameHeight,
- audioCodec,
- audioBitRate,
- audioSampleRate,
- audioChannels
- );
- }
-
- /** Creates a CamcorderProfileProxy instance from {@link CamcorderProfile}. */
- @NonNull
- public static CamcorderProfileProxy fromCamcorderProfile(
- @NonNull CamcorderProfile camcorderProfile) {
- return new AutoValue_CamcorderProfileProxy(
- camcorderProfile.duration,
- camcorderProfile.quality,
- camcorderProfile.fileFormat,
- camcorderProfile.videoCodec,
- camcorderProfile.videoBitRate,
- camcorderProfile.videoFrameRate,
- camcorderProfile.videoFrameWidth,
- camcorderProfile.videoFrameHeight,
- camcorderProfile.audioCodec,
- camcorderProfile.audioBitRate,
- camcorderProfile.audioSampleRate,
- camcorderProfile.audioChannels
- );
- }
-
- /** @see CamcorderProfile#duration */
- public abstract int getDuration();
-
- /** @see CamcorderProfile#quality */
- public abstract int getQuality();
-
- /** @see CamcorderProfile#fileFormat */
- public abstract int getFileFormat();
-
- /** @see CamcorderProfile#videoCodec */
- @VideoEncoder
- public abstract int getVideoCodec();
-
- /** @see CamcorderProfile#videoBitRate */
- public abstract int getVideoBitRate();
-
- /** @see CamcorderProfile#videoFrameRate */
- public abstract int getVideoFrameRate();
-
- /** @see CamcorderProfile#videoFrameWidth */
- public abstract int getVideoFrameWidth();
-
- /** @see CamcorderProfile#videoFrameHeight */
- public abstract int getVideoFrameHeight();
-
- /** @see CamcorderProfile#audioCodec */
- @AudioEncoder
- public abstract int getAudioCodec();
-
- /** @see CamcorderProfile#audioBitRate */
- public abstract int getAudioBitRate();
-
- /** @see CamcorderProfile#audioSampleRate */
- public abstract int getAudioSampleRate();
-
- /** @see CamcorderProfile#audioChannels */
- public abstract int getAudioChannels();
-
- /**
- * Returns a mime-type string for the video codec type returned by {@link #getVideoCodec()}.
- *
- * @return A mime-type string or {@code null} if the codec type is
- * {@link android.media.MediaRecorder.VideoEncoder#DEFAULT}, as this type is under-defined
- * and cannot be resolved to a specific mime type without more information.
- */
- @Nullable
- public String getVideoCodecMimeType() {
- // Mime-type definitions taken from
- // frameworks/av/media/libstagefright/foundation/MediaDefs.cpp
- switch (getVideoCodec()) {
- case H263:
- return MediaFormat.MIMETYPE_VIDEO_H263;
- case H264:
- return MediaFormat.MIMETYPE_VIDEO_AVC;
- case HEVC:
- return MediaFormat.MIMETYPE_VIDEO_HEVC;
- case VP8:
- return MediaFormat.MIMETYPE_VIDEO_VP8;
- case MPEG_4_SP:
- return MediaFormat.MIMETYPE_VIDEO_MPEG4;
- case MediaRecorder.VideoEncoder.DEFAULT:
- break;
- }
-
- return null;
- }
-
- /**
- * Returns a mime-type string for the audio codec type returned by {@link #getAudioCodec()}.
- *
- * @return A mime-type string or {@code null} if the codec type is
- * {@link android.media.MediaRecorder.AudioEncoder#DEFAULT}, as this type is under-defined
- * and cannot be resolved to a specific mime type without more information.
- */
- @Nullable
- public String getAudioCodecMimeType() {
- // Mime-type definitions taken from
- // frameworks/av/media/libstagefright/foundation/MediaDefs.cpp
- switch (getAudioCodec()) {
- case AAC: // Should use aac-profile LC
- case HE_AAC: // Should use aac-profile HE
- case AAC_ELD: // Should use aac-profile ELD
- return MediaFormat.MIMETYPE_AUDIO_AAC;
- case AMR_NB:
- return MediaFormat.MIMETYPE_AUDIO_AMR_NB;
- case AMR_WB:
- return MediaFormat.MIMETYPE_AUDIO_AMR_WB;
- case OPUS:
- return MediaFormat.MIMETYPE_AUDIO_OPUS;
- case VORBIS:
- return MediaFormat.MIMETYPE_AUDIO_VORBIS;
- case MediaRecorder.AudioEncoder.DEFAULT:
- break;
- }
-
- return null;
- }
-
- /**
- * Returns the required audio profile for the audio encoder given by {@link #getAudioCodec()}.
- *
- * <p>For example, this can be used to differentiate between AAC encoders
- * {@link android.media.MediaRecorder.AudioEncoder#AAC},
- * {@link android.media.MediaRecorder.AudioEncoder#AAC_ELD},
- * and {@link android.media.MediaRecorder.AudioEncoder#HE_AAC}.
- * Should be used with the {@link MediaCodecInfo.CodecProfileLevel#profile} field.
- *
- * @return The profile required by the audio codec. If no profile is required, returns
- * {@link #CODEC_PROFILE_NONE}.
- */
- public int getRequiredAudioProfile() {
- switch (getAudioCodec()) {
- case AAC:
- return MediaCodecInfo.CodecProfileLevel.AACObjectLC;
- case AAC_ELD:
- return MediaCodecInfo.CodecProfileLevel.AACObjectELD;
- case HE_AAC:
- return MediaCodecInfo.CodecProfileLevel.AACObjectHE;
- default:
- return CODEC_PROFILE_NONE;
- }
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraFactory.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraFactory.java
index 814ea36..4fe95d9 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraFactory.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraFactory.java
@@ -24,6 +24,7 @@
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.InitializationException;
+import androidx.camera.core.concurrent.CameraCoordinator;
import java.util.Set;
@@ -74,6 +75,14 @@
Set<String> getAvailableCameraIds();
/**
+ * Gets the {@link CameraCoordinator}.
+ *
+ * @return the instance of {@link CameraCoordinator}.
+ */
+ @Nullable
+ CameraCoordinator getCameraCoordinator();
+
+ /**
* Gets the camera manager instance that is used to access the camera API.
*
* <p>Notes that actual type of this camera manager depends on the implementation. While it
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
index 633c72c..1fb2f48 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
@@ -65,9 +65,9 @@
@NonNull
Quirks getCameraQuirks();
- /** Returns the {@link CamcorderProfileProvider} associated with this camera. */
+ /** Returns the {@link EncoderProfilesProvider} associated with this camera. */
@NonNull
- CamcorderProfileProvider getCamcorderProfileProvider();
+ EncoderProfilesProvider getEncoderProfilesProvider();
/** Returns the {@link Timebase} of frame output by this camera. */
@NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/compat/EncoderProfilesProxyCompat.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/compat/EncoderProfilesProxyCompat.java
index cd50106..a214fe1 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/compat/EncoderProfilesProxyCompat.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/compat/EncoderProfilesProxyCompat.java
@@ -22,6 +22,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
import androidx.camera.core.impl.EncoderProfilesProxy;
/**
@@ -31,6 +32,8 @@
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
public final class EncoderProfilesProxyCompat {
+ private static final String TAG = "EncoderProfilesProxyCompat";
+
/** Creates an EncoderProfilesProxy instance from {@link EncoderProfiles}. */
@RequiresApi(31)
@NonNull
@@ -50,13 +53,11 @@
@NonNull
public static EncoderProfilesProxy from(@NonNull CamcorderProfile camcorderProfile) {
if (Build.VERSION.SDK_INT >= 31) {
- throw new RuntimeException(
- "Should not use from(CamcorderProfile) on API " + Build.VERSION.SDK_INT
- + ". CamcorderProfile is deprecated on API 31, use "
- + "from(EncoderProfiles) instead.");
- } else {
- return EncoderProfilesProxyCompatBaseImpl.from(camcorderProfile);
+ Logger.w(TAG, "Should use from(EncoderProfiles) on API " + Build.VERSION.SDK_INT
+ + "instead. CamcorderProfile is deprecated on API 31.");
}
+
+ return EncoderProfilesProxyCompatBaseImpl.from(camcorderProfile);
}
// Class should not be instantiated.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index f6b3836..924d3a4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -58,7 +58,6 @@
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.core.processing.SurfaceProcessorWithExecutor;
import androidx.camera.core.streamsharing.StreamSharing;
import androidx.core.util.Preconditions;
@@ -545,18 +544,9 @@
// Set effects on the UseCases. This also removes existing effects if necessary.
for (UseCase useCase : useCases) {
if (useCase instanceof Preview) {
- Preview preview = ((Preview) useCase);
- CameraEffect effect = effectsByTargets.get(CameraEffect.PREVIEW);
- if (effect == null) {
- preview.setProcessor(null);
- continue;
- }
- preview.setProcessor(new SurfaceProcessorWithExecutor(
- requireNonNull(effect.getSurfaceProcessor()),
- effect.getExecutor()));
+ useCase.setEffect(effectsByTargets.get(CameraEffect.PREVIEW));
} else if (useCase instanceof ImageCapture) {
- ImageCapture imageCapture = ((ImageCapture) useCase);
- imageCapture.setEffect(effectsByTargets.get(CameraEffect.IMAGE_CAPTURE));
+ useCase.setEffect(effectsByTargets.get(CameraEffect.IMAGE_CAPTURE));
}
}
}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
index 9ce2398..e1271ec 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
@@ -39,7 +39,6 @@
import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
import androidx.camera.core.internal.CameraUseCaseAdapter
import androidx.camera.core.internal.utils.SizeUtil
-import androidx.camera.core.processing.SurfaceProcessorInternal
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraXUtil
import androidx.camera.testing.fakes.FakeAppConfig
@@ -47,6 +46,7 @@
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessorInternal
import androidx.camera.testing.fakes.FakeUseCase
import androidx.test.core.app.ApplicationProvider
@@ -75,7 +75,7 @@
)
class PreviewTest {
- var cameraUseCaseAdapter: CameraUseCaseAdapter? = null
+ private var cameraUseCaseAdapter: CameraUseCaseAdapter? = null
private lateinit var appSurface: Surface
private lateinit var appSurfaceTexture: SurfaceTexture
@@ -84,6 +84,8 @@
private lateinit var cameraXConfig: CameraXConfig
private lateinit var context: Context
private lateinit var previewToDetach: Preview
+ private lateinit var processor: FakeSurfaceProcessorInternal
+ private lateinit var effect: CameraEffect
@Before
@Throws(ExecutionException::class, InterruptedException::class)
@@ -109,6 +111,8 @@
).setCameraFactoryProvider(cameraFactoryProvider).build()
context = ApplicationProvider.getApplicationContext<Context>()
CameraXUtil.initialize(context, cameraXConfig).get()
+ processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
+ effect = FakeSurfaceEffect(processor)
}
@After
@@ -123,6 +127,7 @@
if (::previewToDetach.isInitialized) {
previewToDetach.onUnbind()
}
+ processor.release()
CameraXUtil.shutdown().get()
}
@@ -233,11 +238,10 @@
@Test
fun createSurfaceRequestWithProcessor_noCameraTransform() {
// Arrange: attach Preview without a SurfaceProvider.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
var transformationInfo: TransformationInfo? = null
// Act: create pipeline in Preview and provide Surface.
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
preview.mCurrentSurfaceRequest!!.setTransformationInfoListener(mainThreadExecutor()) {
transformationInfo = it
}
@@ -265,31 +269,24 @@
@Test
fun backCameraWithProcessor_notMirrored() {
- // Arrange.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
// Act: create pipeline
- val preview = createPreview(processor, backCamera)
+ val preview = createPreview(effect, backCamera)
// Assert
assertThat(preview.cameraEdge.mirroring).isFalse()
}
@Test
fun frontCameraWithProcessor_mirrored() {
- // Arrange.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
// Act: create pipeline
- val preview = createPreview(processor, frontCamera)
+ val preview = createPreview(effect, frontCamera)
// Assert
assertThat(preview.cameraEdge.mirroring).isTrue()
}
@Test
fun setTargetRotationWithProcessor_rotationChangesOnSurfaceEdge() {
- // Arrange.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
-
// Act: create pipeline
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
// Act: update target rotation
preview.targetRotation = Surface.ROTATION_0
shadowOf(getMainLooper()).idle()
@@ -306,8 +303,7 @@
@Test
fun invalidateAppSurfaceRequestWithProcessing_cameraNotReset() {
// Arrange: create Preview with processing.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor(), false)
- val surfaceRequest = createPreview(processor).mCurrentSurfaceRequest
+ val surfaceRequest = createPreview(effect).mCurrentSurfaceRequest
// Act: invalidate.
surfaceRequest!!.invalidate()
shadowOf(getMainLooper()).idle()
@@ -318,8 +314,7 @@
@Test
fun invalidateNodeSurfaceRequest_cameraReset() {
// Arrange: create Preview with processing.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor(), false)
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
// Act: invalidate.
processor.surfaceRequest!!.invalidate()
shadowOf(getMainLooper()).idle()
@@ -342,8 +337,7 @@
@Test
fun invalidateWhenDetached_deferrableSurfaceClosed() {
// Arrange: create Preview with processing then detach.
- val processor = FakeSurfaceProcessorInternal(mainThreadExecutor(), false)
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
val surfaceRequest = processor.surfaceRequest!!
preview.unbindFromCamera(backCamera)
// Act: invalidate.
@@ -358,7 +352,7 @@
fun hasCameraTransform_rotationDegreesNotFlipped() {
// Act: create preview with hasCameraTransform == true
val preview = createPreview(
- FakeSurfaceProcessorInternal(mainThreadExecutor()),
+ effect,
frontCamera,
targetRotation = Surface.ROTATION_90
)
@@ -371,7 +365,7 @@
fun noCameraTransform_rotationDegreesFlipped() {
// Act: create preview with hasCameraTransform == false
val preview = createPreview(
- FakeSurfaceProcessorInternal(mainThreadExecutor()),
+ effect,
frontCamera,
hasCameraTransform = false,
targetRotation = Surface.ROTATION_90
@@ -384,7 +378,7 @@
fun setNoCameraTransform_propagatesToCameraEdge() {
// Act: create preview with hasCameraTransform == false
val preview = createPreview(
- FakeSurfaceProcessorInternal(mainThreadExecutor()),
+ effect,
hasCameraTransform = false,
targetRotation = Surface.ROTATION_90
)
@@ -397,7 +391,7 @@
fun frontCameraWithoutCameraTransform_noMirroring() {
// Act: create preview with hasCameraTransform == false
val preview = createPreview(
- FakeSurfaceProcessorInternal(mainThreadExecutor()),
+ effect,
frontCamera,
hasCameraTransform = false,
targetRotation = Surface.ROTATION_90
@@ -408,23 +402,13 @@
@Test
fun cameraEdgeHasTransformByDefault() {
- assertThat(
- createPreview(
- FakeSurfaceProcessorInternal(mainThreadExecutor())
- ).cameraEdge.hasCameraTransform()
- ).isTrue()
+ assertThat(createPreview(effect).cameraEdge.hasCameraTransform()).isTrue()
}
@Test
fun bindAndUnbindPreview_surfacesPropagated() {
- // Arrange.
- val processor = FakeSurfaceProcessorInternal(
- mainThreadExecutor(),
- false
- )
-
// Act: create pipeline in Preview and provide Surface.
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
val surfaceRequest = preview.mCurrentSurfaceRequest!!
var appSurfaceReadyToRelease = false
surfaceRequest.provideSurface(appSurface, mainThreadExecutor()) {
@@ -450,21 +434,13 @@
assertThat(processor.isReleased).isTrue()
assertThat(processor.isOutputSurfaceRequestedToClose[PREVIEW]).isTrue()
assertThat(processor.isInputSurfaceReleased).isTrue()
- assertThat(appSurfaceReadyToRelease).isFalse()
-
- // Act: close SurfaceOutput
- processor.surfaceOutputs[CameraEffect.PREVIEW]!!.close()
- shadowOf(getMainLooper()).idle()
assertThat(appSurfaceReadyToRelease).isTrue()
}
@Test
fun invokedErrorListener_recreatePipeline() {
// Arrange: create pipeline and get a reference of the SessionConfig.
- val processor = FakeSurfaceProcessorInternal(
- mainThreadExecutor()
- )
- val preview = createPreview(processor)
+ val preview = createPreview(effect)
val originalSessionConfig = preview.sessionConfig
// Act: invoke the error listener.
@@ -666,7 +642,7 @@
}
private fun createPreview(
- surfaceProcessor: SurfaceProcessorInternal? = null,
+ effect: CameraEffect? = null,
camera: FakeCamera = backCamera,
hasCameraTransform: Boolean = true,
targetRotation: Int = Surface.ROTATION_0
@@ -675,7 +651,7 @@
.setTargetRotation(targetRotation)
.build()
previewToDetach.hasCameraTransform = hasCameraTransform
- previewToDetach.processor = surfaceProcessor
+ previewToDetach.effect = effect
previewToDetach.setSurfaceProvider(CameraXExecutors.directExecutor()) {}
val previewConfig = PreviewConfig(
cameraXConfig.getUseCaseConfigFactoryProvider(null)!!.newInstance(context).getConfig(
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/UseCaseGroupTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/UseCaseGroupTest.kt
index 035cbfa0..7d877d1 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/UseCaseGroupTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/UseCaseGroupTest.kt
@@ -22,7 +22,7 @@
import androidx.camera.core.CameraEffect.VIDEO_CAPTURE
import androidx.camera.core.UseCaseGroup.Builder.getHumanReadableTargets
import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import androidx.camera.testing.fakes.FakePreviewEffect
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessor
import androidx.camera.testing.fakes.FakeUseCase
import com.google.common.truth.Truth.assertThat
@@ -43,7 +43,7 @@
@Test
fun duplicateTargets_throwsException() {
// Arrange.
- val previewEffect = FakePreviewEffect(
+ val previewEffect = FakeSurfaceEffect(
CameraXExecutors.mainThreadExecutor(),
FakeSurfaceProcessor(CameraXExecutors.mainThreadExecutor())
)
@@ -61,8 +61,8 @@
// Assert.
assertThat(message).isEqualTo(
- "Effects androidx.camera.testing.fakes.FakePreviewEffect " +
- "and androidx.camera.testing.fakes.FakePreviewEffect " +
+ "Effects androidx.camera.testing.fakes.FakeSurfaceEffect " +
+ "and androidx.camera.testing.fakes.FakeSurfaceEffect " +
"contain duplicate targets PREVIEW."
)
}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
index 898c3b7..b8e92f5 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
@@ -41,11 +41,10 @@
import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
import androidx.camera.core.internal.CameraUseCaseAdapter.CameraException
import androidx.camera.core.processing.DefaultSurfaceProcessor
-import androidx.camera.core.processing.SurfaceProcessorWithExecutor
import androidx.camera.core.streamsharing.StreamSharing
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
-import androidx.camera.testing.fakes.FakePreviewEffect
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessor
import androidx.camera.testing.fakes.FakeSurfaceProcessorInternal
import androidx.camera.testing.fakes.FakeUseCase
@@ -88,6 +87,7 @@
private lateinit var fakeCameraDeviceSurfaceManager: FakeCameraDeviceSurfaceManager
private lateinit var fakeCamera: FakeCamera
private lateinit var useCaseConfigFactory: UseCaseConfigFactory
+ private lateinit var previewEffect: FakeSurfaceEffect
private val fakeCameraSet = LinkedHashSet<CameraInternal>()
private val imageEffect = GrayscaleImageEffect()
private val preview = Preview.Builder().build()
@@ -104,7 +104,11 @@
fakeCameraSet.add(fakeCamera)
surfaceProcessor = FakeSurfaceProcessor(mainThreadExecutor())
executor = Executors.newSingleThreadExecutor()
- effects = listOf(FakePreviewEffect(executor, surfaceProcessor), imageEffect)
+ previewEffect = FakeSurfaceEffect(
+ executor,
+ surfaceProcessor
+ )
+ effects = listOf(previewEffect, imageEffect)
adapter = CameraUseCaseAdapter(
fakeCameraSet,
fakeCameraDeviceSurfaceManager,
@@ -824,17 +828,14 @@
// Act: update use cases with effects.
CameraUseCaseAdapter.updateEffects(effects, useCases)
- // Assert: preview has processor wrapped with the right executor.
- val previewProcessor = preview.processor as SurfaceProcessorWithExecutor
- assertThat(previewProcessor.processor).isEqualTo(surfaceProcessor)
- assertThat(previewProcessor.executor).isEqualTo(executor)
- // Assert: imageCapture has the effect set.
+ // Assert: UseCase have effects
+ assertThat(preview.effect).isEqualTo(previewEffect)
assertThat(imageCapture.effect).isEqualTo(imageEffect)
// Act: update again with no effects.
CameraUseCaseAdapter.updateEffects(listOf(), useCases)
// Assert: use cases no longer has effects.
- assertThat(preview.processor).isNull()
+ assertThat(preview.effect).isNull()
assertThat(imageCapture.effect).isNull()
}
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
index 8cb0c37..0c38d7a 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
@@ -30,14 +30,13 @@
import androidx.camera.core.concurrent.SingleCameraConfig
import androidx.camera.core.impl.CameraFactory
import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
-import androidx.camera.core.processing.SurfaceProcessorWithExecutor
import androidx.camera.testing.fakes.FakeAppConfig
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
import androidx.camera.testing.fakes.FakeLifecycleOwner
-import androidx.camera.testing.fakes.FakePreviewEffect
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessor
import androidx.camera.testing.fakes.FakeUseCaseConfigFactory
import androidx.concurrent.futures.await
@@ -81,7 +80,10 @@
// Arrange.
ProcessCameraProvider.configureInstance(FakeAppConfig.create())
val surfaceProcessor = FakeSurfaceProcessor(mainThreadExecutor())
- val effect = FakePreviewEffect(mainThreadExecutor(), surfaceProcessor)
+ val effect = FakeSurfaceEffect(
+ mainThreadExecutor(),
+ surfaceProcessor
+ )
val preview = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
val useCaseGroup = UseCaseGroup.Builder().addUseCase(preview).addEffect(effect).build()
@@ -94,8 +96,7 @@
)
// Assert.
- val useCaseProcessor = (preview.processor as SurfaceProcessorWithExecutor).processor
- assertThat(useCaseProcessor).isEqualTo(surfaceProcessor)
+ assertThat(preview.effect).isEqualTo(effect)
}
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CamcorderProfileUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CamcorderProfileUtil.java
deleted file mode 100644
index 923a59b..0000000
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CamcorderProfileUtil.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.camera.testing;
-
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder;
-import android.util.Size;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CamcorderProfileProxy;
-
-/**
- * Utility methods for testing {@link CamcorderProfile} related classes, including predefined
- * resolutions, attributes and {@link CamcorderProfileProxy}, which can be used directly on the
- * unit tests.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public final class CamcorderProfileUtil {
-
- private CamcorderProfileUtil() {
- }
-
- /** Resolution for QCIF. */
- public static final Size RESOLUTION_QCIF = new Size(176, 144);
- /** Resolution for QVGA. */
- public static final Size RESOLUTION_QVGA = new Size(320, 240);
- /** Resolution for CIF. */
- public static final Size RESOLUTION_CIF = new Size(352, 288);
- /** Resolution for VGA. */
- public static final Size RESOLUTION_VGA = new Size(640, 480);
- /** Resolution for 480P. */
- public static final Size RESOLUTION_480P = new Size(720, 480); /* 640, 704 or 720 x 480 */
- /** Resolution for 720P. */
- public static final Size RESOLUTION_720P = new Size(1280, 720);
- /** Resolution for 1080P. */
- public static final Size RESOLUTION_1080P = new Size(1920, 1080); /* 1920 x 1080 or 1088 */
- /** Resolution for 2K. */
- public static final Size RESOLUTION_2K = new Size(2048, 1080);
- /** Resolution for QHD. */
- public static final Size RESOLUTION_QHD = new Size(2560, 1440);
- /** Resolution for 2160P. */
- public static final Size RESOLUTION_2160P = new Size(3840, 2160);
- /** Resolution for 4KDCI. */
- public static final Size RESOLUTION_4KDCI = new Size(4096, 2160);
-
- /** Default duration. */
- public static final int DEFAULT_DURATION = 30;
- /** Default output format. */
- public static final int DEFAULT_OUTPUT_FORMAT = MediaRecorder.OutputFormat.MPEG_4;
- /** Default video codec. */
- public static final int DEFAULT_VIDEO_CODEC = MediaRecorder.VideoEncoder.H264;
- /** Default video bitrate. */
- public static final int DEFAULT_VIDEO_BITRATE = 8 * 1024 * 1024;
- /** Default video frame rate. */
- public static final int DEFAULT_VIDEO_FRAME_RATE = 30;
- /** Default audio codec. */
- public static final int DEFAULT_AUDIO_CODEC = MediaRecorder.AudioEncoder.AAC;
- /** Default audio bitrate. */
- public static final int DEFAULT_AUDIO_BITRATE = 192_000;
- /** Default audio sample rate. */
- public static final int DEFAULT_AUDIO_SAMPLE_RATE = 48_000;
- /** Default channel count. */
- public static final int DEFAULT_AUDIO_CHANNELS = 1;
-
- public static final CamcorderProfileProxy PROFILE_QCIF = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_QCIF,
- RESOLUTION_QCIF.getWidth(),
- RESOLUTION_QCIF.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_QVGA = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_QVGA,
- RESOLUTION_QVGA.getWidth(),
- RESOLUTION_QVGA.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_CIF = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_CIF,
- RESOLUTION_CIF.getWidth(),
- RESOLUTION_CIF.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_VGA = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_VGA,
- RESOLUTION_VGA.getWidth(),
- RESOLUTION_VGA.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_480P = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_480P,
- RESOLUTION_480P.getWidth(),
- RESOLUTION_480P.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_720P = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_720P,
- RESOLUTION_720P.getWidth(),
- RESOLUTION_720P.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_1080P = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_1080P,
- RESOLUTION_1080P.getWidth(),
- RESOLUTION_1080P.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_2K = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_2K,
- RESOLUTION_2K.getWidth(),
- RESOLUTION_2K.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_QHD = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_QHD,
- RESOLUTION_QHD.getWidth(),
- RESOLUTION_QHD.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_2160P = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_2160P,
- RESOLUTION_2160P.getWidth(),
- RESOLUTION_2160P.getHeight()
- );
-
- public static final CamcorderProfileProxy PROFILE_4KDCI = createCamcorderProfileProxy(
- CamcorderProfile.QUALITY_4KDCI,
- RESOLUTION_4KDCI.getWidth(),
- RESOLUTION_4KDCI.getHeight()
- );
-
- /** A utility method to create a CamcorderProfileProxy with some default values. */
- @NonNull
- public static CamcorderProfileProxy createCamcorderProfileProxy(
- int quality,
- int videoFrameWidth,
- int videoFrameHeight
- ) {
- return CamcorderProfileProxy.create(
- DEFAULT_DURATION,
- quality,
- DEFAULT_OUTPUT_FORMAT,
- DEFAULT_VIDEO_CODEC,
- DEFAULT_VIDEO_BITRATE,
- DEFAULT_VIDEO_FRAME_RATE,
- videoFrameWidth,
- videoFrameHeight,
- DEFAULT_AUDIO_CODEC,
- DEFAULT_AUDIO_BITRATE,
- DEFAULT_AUDIO_SAMPLE_RATE,
- DEFAULT_AUDIO_CHANNELS
- );
- }
-
- /**
- * Copies a CamcorderProfileProxy and sets the quality to
- * {@link CamcorderProfile#QUALITY_HIGH}.
- */
- @NonNull
- public static CamcorderProfileProxy asHighQuality(@NonNull CamcorderProfileProxy profile) {
- return asQuality(profile, CamcorderProfile.QUALITY_HIGH);
- }
-
- /**
- * Copies a CamcorderProfileProxy and sets the quality to
- * {@link CamcorderProfile#QUALITY_LOW}.
- */
- @NonNull
- public static CamcorderProfileProxy asLowQuality(@NonNull CamcorderProfileProxy profile) {
- return asQuality(profile, CamcorderProfile.QUALITY_LOW);
- }
-
- private static CamcorderProfileProxy asQuality(@NonNull CamcorderProfileProxy profile,
- int quality) {
- return CamcorderProfileProxy.create(
- profile.getDuration(),
- quality,
- profile.getFileFormat(),
- profile.getVideoCodec(),
- profile.getVideoBitRate(),
- profile.getVideoFrameRate(),
- profile.getVideoFrameWidth(),
- profile.getVideoFrameHeight(),
- profile.getAudioCodec(),
- profile.getAudioBitRate(),
- profile.getAudioSampleRate(),
- profile.getAudioChannels()
- );
- }
-}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamcorderProfileProvider.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamcorderProfileProvider.java
deleted file mode 100644
index f59107f..0000000
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamcorderProfileProvider.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.camera.testing.fakes;
-
-import android.media.CameraProfile;
-import android.util.SparseArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CamcorderProfileProvider;
-import androidx.camera.core.impl.CamcorderProfileProxy;
-
-/**
- * A fake implementation of the {@link CamcorderProfileProvider} and used for test.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public class FakeCamcorderProfileProvider implements CamcorderProfileProvider {
-
- private final SparseArray<CamcorderProfileProxy> mQualityToProfileMap;
-
- FakeCamcorderProfileProvider(@NonNull SparseArray<CamcorderProfileProxy> qualityToProfileMap) {
- mQualityToProfileMap = qualityToProfileMap;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable
- public CamcorderProfileProxy get(int quality) {
- return mQualityToProfileMap.get(quality);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasProfile(int quality) {
- return mQualityToProfileMap.get(quality) != null;
- }
-
- /**
- * The builder to create a FakeCamcorderProfileProvider instance.
- */
- @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
- public static class Builder {
- private final SparseArray<CamcorderProfileProxy> mQualityToProfileMap = new SparseArray<>();
-
- /**
- * Sets the camera id and corresponding profiles.
- *
- * <p>In normal case, the {@link CameraProfile#QUALITY_HIGH} and
- * {@link CameraProfile#QUALITY_LOW} should be added in order to follow the contract of
- * CamcorderProfile.
- */
- @NonNull
- public Builder addProfile(@NonNull CamcorderProfileProxy ...camcorderProfiles) {
- for (CamcorderProfileProxy camcorderProfile : camcorderProfiles) {
- mQualityToProfileMap.put(camcorderProfile.getQuality(), camcorderProfile);
- }
- return this;
- }
-
- /** Builds the FakeCamcorderProfileProvider instance. */
- @NonNull
- public FakeCamcorderProfileProvider build() {
- return new FakeCamcorderProfileProvider(mQualityToProfileMap.clone());
- }
- }
-}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
index 08a26e7..ea0e9f8 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraFactory.java
@@ -23,6 +23,7 @@
import androidx.annotation.RestrictTo.Scope;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
+import androidx.camera.core.concurrent.CameraCoordinator;
import androidx.camera.core.impl.CameraFactory;
import androidx.camera.core.impl.CameraInternal;
import androidx.core.util.Pair;
@@ -58,6 +59,9 @@
@Nullable
private Object mCameraManager = null;
+ @Nullable
+ private CameraCoordinator mCameraCoordinator = null;
+
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
final Map<String, Pair<Integer, Callable<CameraInternal>>> mCameraMap = new HashMap<>();
@@ -170,6 +174,16 @@
return filteredCameraIds;
}
+ @Nullable
+ @Override
+ public CameraCoordinator getCameraCoordinator() {
+ return mCameraCoordinator;
+ }
+
+ public void setCameraCoordinator(@Nullable CameraCoordinator cameraCoordinator) {
+ mCameraCoordinator = cameraCoordinator;
+ }
+
public void setCameraManager(@Nullable Object cameraManager) {
mCameraManager = cameraManager;
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
index d15ce7a..77cfb2b 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraInfoInternal.java
@@ -30,9 +30,9 @@
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.TorchState;
import androidx.camera.core.ZoomState;
-import androidx.camera.core.impl.CamcorderProfileProvider;
import androidx.camera.core.impl.CameraCaptureCallback;
import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.EncoderProfilesProvider;
import androidx.camera.core.impl.ImageOutputConfig.RotationValue;
import androidx.camera.core.impl.Quirk;
import androidx.camera.core.impl.Quirks;
@@ -70,7 +70,7 @@
// Leave uninitialized to support camera-core:1.0.0 dependencies.
// Can be initialized during class init once there are no more pinned dependencies on
// camera-core:1.0.0
- private CamcorderProfileProvider mCamcorderProfileProvider;
+ private EncoderProfilesProvider mEncoderProfilesProvider;
private boolean mIsPrivateReprocessingSupported = false;
private float mIntrinsicZoomRatio = 1.0F;
@@ -173,9 +173,9 @@
@NonNull
@Override
- public CamcorderProfileProvider getCamcorderProfileProvider() {
- return mCamcorderProfileProvider == null ? CamcorderProfileProvider.EMPTY :
- mCamcorderProfileProvider;
+ public EncoderProfilesProvider getEncoderProfilesProvider() {
+ return mEncoderProfilesProvider == null ? EncoderProfilesProvider.EMPTY :
+ mEncoderProfilesProvider;
}
@NonNull
@@ -242,10 +242,10 @@
mImplementationType = implementationType;
}
- /** Set the CamcorderProfileProvider for testing */
- public void setCamcorderProfileProvider(
- @NonNull CamcorderProfileProvider camcorderProfileProvider) {
- mCamcorderProfileProvider = Preconditions.checkNotNull(camcorderProfileProvider);
+ /** Set the EncoderProfilesProvider for testing */
+ public void setEncoderProfilesProvider(
+ @NonNull EncoderProfilesProvider encoderProfilesProvider) {
+ mEncoderProfilesProvider = Preconditions.checkNotNull(encoderProfilesProvider);
}
/** Set the timebase for testing */
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakePreviewEffect.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakePreviewEffect.java
deleted file mode 100644
index e1a6ea9..0000000
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakePreviewEffect.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2022 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.camera.testing.fakes;
-
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.CameraEffect;
-import androidx.camera.core.SurfaceProcessor;
-
-import java.util.concurrent.Executor;
-
-/**
- * A fake {@link CameraEffect} with {@link SurfaceProcessor}.
- */
-@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-public class FakePreviewEffect extends CameraEffect {
- public FakePreviewEffect(
- @NonNull Executor processorExecutor,
- @NonNull SurfaceProcessor surfaceProcessor) {
- super(PREVIEW, processorExecutor, surfaceProcessor);
- }
-}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSurfaceEffect.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSurfaceEffect.java
new file mode 100644
index 0000000..b792c7a
--- /dev/null
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSurfaceEffect.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 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.camera.testing.fakes;
+
+import static androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor;
+
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.CameraEffect;
+import androidx.camera.core.SurfaceProcessor;
+import androidx.camera.core.processing.SurfaceProcessorInternal;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A fake {@link CameraEffect} with {@link SurfaceProcessor}.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+public class FakeSurfaceEffect extends CameraEffect {
+
+ private SurfaceProcessorInternal mSurfaceProcessorInternal;
+
+ public FakeSurfaceEffect(
+ @NonNull Executor processorExecutor,
+ @NonNull SurfaceProcessor surfaceProcessor) {
+ super(PREVIEW, processorExecutor, surfaceProcessor);
+ }
+
+ /**
+ * Create a fake {@link CameraEffect} the {@link #createSurfaceProcessorInternal} value
+ * overridden.
+ *
+ * <p> This is helpful when we want to make sure the {@link SurfaceProcessorInternal} is
+ * released properly.
+ */
+ public FakeSurfaceEffect(@NonNull SurfaceProcessorInternal surfaceProcessorInternal) {
+ super(PREVIEW, mainThreadExecutor(), surfaceProcessorInternal);
+ mSurfaceProcessorInternal = surfaceProcessorInternal;
+ }
+
+ @NonNull
+ @Override
+ public SurfaceProcessorInternal createSurfaceProcessorInternal() {
+ if (mSurfaceProcessorInternal != null) {
+ return mSurfaceProcessorInternal;
+ } else {
+ return super.createSurfaceProcessorInternal();
+ }
+ }
+}
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/AudioChecker.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/AudioChecker.kt
index dbd3371..4a6f310 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/AudioChecker.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/AudioChecker.kt
@@ -24,7 +24,7 @@
import androidx.camera.testing.CameraUtil
import androidx.camera.video.internal.AudioSource
import androidx.camera.video.internal.FakeBufferProvider
-import androidx.camera.video.internal.config.AudioSourceSettingsCamcorderProfileResolver
+import androidx.camera.video.internal.config.AudioSourceSettingsAudioProfileResolver
import androidx.camera.video.internal.encoder.FakeInputBuffer
import androidx.concurrent.futures.await
import kotlinx.coroutines.CompletableDeferred
@@ -56,16 +56,16 @@
cameraSelector: CameraSelector,
qualitySelector: QualitySelector
) = runBlocking {
- // Get audio source settings from CamcorderProfile
+ // Get audio source settings from EncoderProfiles
val cameraInfo =
CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
val videoCapabilities = VideoCapabilities.from(cameraInfo)
val quality = qualitySelector.getPrioritizedQualities(cameraInfo).first()
// Get a config using the default audio spec.
val audioSourceSettings =
- AudioSourceSettingsCamcorderProfileResolver(
+ AudioSourceSettingsAudioProfileResolver(
AudioSpec.builder().build(),
- videoCapabilities.getProfile(quality)!!
+ videoCapabilities.getProfiles(quality)!!.defaultAudioProfile!!
).get()
val audioSource = AudioSource(audioSourceSettings, CameraXExecutors.ioExecutor(), null)
try {
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
index 7892f10..1261cd5 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
@@ -25,10 +25,11 @@
import androidx.camera.core.CameraSelector.DEFAULT_BACK_CAMERA
import androidx.camera.core.CameraSelector.DEFAULT_FRONT_CAMERA
import androidx.camera.core.CameraXConfig
-import androidx.camera.core.impl.CamcorderProfileProxy
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy
import androidx.camera.testing.CameraPipeConfigTestRule
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraXUtil
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy
import androidx.camera.video.internal.compat.quirk.DeviceQuirks
import androidx.camera.video.internal.compat.quirk.MediaCodecInfoReportIncorrectInfoQuirk
import androidx.test.core.app.ApplicationProvider
@@ -86,11 +87,11 @@
}
@Test
- fun mediaCodecInfoShouldSupportCamcorderProfileSizes() {
+ fun mediaCodecInfoShouldSupportEncoderProfilesSizes() {
assumeTrue(DeviceQuirks.get(MediaCodecInfoReportIncorrectInfoQuirk::class.java) == null)
// Arrange: Collect all supported profiles from default back/front camera.
- val supportedProfiles = mutableListOf<CamcorderProfileProxy>()
+ val supportedProfiles = mutableListOf<VideoValidatedEncoderProfilesProxy>()
supportedProfiles.addAll(getSupportedProfiles(DEFAULT_BACK_CAMERA))
supportedProfiles.addAll(getSupportedProfiles(DEFAULT_FRONT_CAMERA))
assumeTrue(supportedProfiles.isNotEmpty())
@@ -99,7 +100,11 @@
// Arrange: Find the codec and its video capabilities.
// If mime is null, skip the test instead of failing it since this isn't the purpose
// of the test.
- val mime = profile.videoCodecMimeType ?: return@forEach
+ val videoProfile = profile.defaultVideoProfile
+ val mime = videoProfile.mediaType
+ if (mime == VideoProfileProxy.MEDIA_TYPE_NONE) {
+ return@forEach
+ }
val capabilities = MediaCodec.createEncoderByType(mime).let { codec ->
try {
codec.codecInfo.getCapabilitiesForType(mime).videoCapabilities
@@ -109,7 +114,7 @@
}
// Act.
- val (width, height) = profile.videoFrameWidth to profile.videoFrameHeight
+ val (width, height) = videoProfile.width to videoProfile.height
val supportedWidths = capabilities.supportedWidths
val supportedHeights = capabilities.supportedHeights
val supportedWidthsForHeight = capabilities.getWidthsForHeightQuietly(height)
@@ -128,14 +133,16 @@
}
}
- private fun getSupportedProfiles(cameraSelector: CameraSelector): List<CamcorderProfileProxy> {
+ private fun getSupportedProfiles(
+ cameraSelector: CameraSelector
+ ): List<VideoValidatedEncoderProfilesProxy> {
if (!CameraUtil.hasCameraWithLensFacing(cameraSelector.lensFacing!!)) {
return emptyList()
}
val cameraInfo = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
val videoCapabilities = VideoCapabilities.from(cameraInfo)
return videoCapabilities.supportedQualities
- .mapNotNull { videoCapabilities.getProfile(it) }
+ .mapNotNull { videoCapabilities.getProfiles(it) }
}
private fun android.util.Range<Int>.toClosed() = Range.closed(lower, upper)
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/SupportedQualitiesVerificationTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/SupportedQualitiesVerificationTest.kt
index 66b2c8e..be254c5 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/SupportedQualitiesVerificationTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/SupportedQualitiesVerificationTest.kt
@@ -37,6 +37,7 @@
import androidx.camera.camera2.Camera2Config
import androidx.camera.camera2.pipe.integration.CameraPipeConfig
import androidx.camera.core.Camera
+import androidx.camera.core.CameraEffect
import androidx.camera.core.CameraInfo
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraXConfig
@@ -47,6 +48,7 @@
import androidx.camera.testing.CameraPipeConfigTestRule
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.fakes.FakeLifecycleOwner
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.core.util.Consumer
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.LargeTest
@@ -187,14 +189,14 @@
fun qualityOptionCanRecordVideo_enableSurfaceProcessor() {
assumeSuccessfulSurfaceProcessing()
- testQualityOptionRecordVideo(surfaceProcessor = createSurfaceProcessor())
+ testQualityOptionRecordVideo(effect = createEffect())
}
- private fun testQualityOptionRecordVideo(surfaceProcessor: SurfaceProcessorInternal? = null) {
+ private fun testQualityOptionRecordVideo(effect: CameraEffect? = null) {
// Arrange.
val recorder = Recorder.Builder().setQualitySelector(QualitySelector.from(quality)).build()
val videoCapture = VideoCapture.withOutput(recorder)
- videoCapture.setProcessor(surfaceProcessor)
+ videoCapture.effect = effect
val file = File.createTempFile("CameraX", ".tmp").apply { deleteOnExit() }
val latchForRecordingStatus = CountDownLatch(5)
val latchForRecordingFinalized = CountDownLatch(1)
@@ -239,8 +241,13 @@
file.delete()
}
- private fun createSurfaceProcessor(): SurfaceProcessorInternal =
- DefaultSurfaceProcessor.Factory.newInstance().apply { surfaceProcessorsToRelease.add(this) }
+ private fun createEffect(): CameraEffect {
+ val fakeSurfaceProcessor = DefaultSurfaceProcessor.Factory.newInstance()
+ surfaceProcessorsToRelease.add(fakeSurfaceProcessor)
+ return FakeSurfaceEffect(
+ fakeSurfaceProcessor
+ )
+ }
/** Skips tests which will enable surface processing and encounter device specific issues. */
private fun assumeSuccessfulSurfaceProcessing() {
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolverTest.kt
similarity index 70%
rename from camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt
rename to camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolverTest.kt
index df98596..68d64f6 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolverTest.kt
@@ -48,7 +48,7 @@
@RunWith(Parameterized::class)
@SmallTest
@SdkSuppress(minSdkVersion = 21)
-class AudioEncoderConfigCamcorderProfileResolverTest(
+class AudioEncoderConfigAudioProfileResolverTest(
private val implName: String,
private val cameraConfig: CameraXConfig
) {
@@ -103,38 +103,49 @@
@Test
fun defaultAudioSpecAndAudioSourceProducesValidSettings() {
val supportedProfiles = videoCapabilities.supportedQualities.map {
- videoCapabilities.getProfile(it)!!
+ videoCapabilities.getProfiles(it)!!
}
- supportedProfiles.forEach {
+ for (encoderProfiles in supportedProfiles) {
+ val audioProfile = encoderProfiles.defaultAudioProfile ?: continue
+
val sourceSettings =
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, it).get()
- val config = AudioEncoderConfigCamcorderProfileResolver(
- it.audioCodecMimeType!!,
- it.requiredAudioProfile,
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ audioProfile
+ ).get()
+ val config = AudioEncoderConfigAudioProfileResolver(
+ audioProfile.mediaType,
+ audioProfile.profile,
timebase,
defaultAudioSpec,
sourceSettings,
- it
+ audioProfile
).get()
- assertThat(config.mimeType).isEqualTo(it.audioCodecMimeType)
- assertThat(config.bitrate).isEqualTo(it.audioBitRate)
- assertThat(config.sampleRate).isEqualTo(it.audioSampleRate)
- assertThat(config.channelCount).isEqualTo(it.audioChannels)
+ assertThat(config.mimeType).isEqualTo(audioProfile.mediaType)
+ assertThat(config.bitrate).isEqualTo(audioProfile.bitrate)
+ assertThat(config.sampleRate).isEqualTo(audioProfile.sampleRate)
+ assertThat(config.channelCount).isEqualTo(audioProfile.channels)
}
}
@Test
fun increasedChannelCountIncreasesBitrate() {
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val profile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(profile != null)
+
// Get default channel count
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
val defaultSourceSettings =
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ profile!!
+ ).get()
val defaultConfig =
- AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
defaultAudioSpec,
defaultSourceSettings,
@@ -145,9 +156,9 @@
val higherChannelCountSourceSettings =
defaultSourceSettings.toBuilder().setChannelCount(defaultChannelCount * 2).build()
- val higherChannelCountConfig = AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ val higherChannelCountConfig = AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
defaultAudioSpec,
higherChannelCountSourceSettings,
@@ -159,14 +170,20 @@
@Test
fun increasedSampleRateIncreasesBitrate() {
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val profile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(profile != null)
+
// Get default sample rate
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
val defaultSourceSettings =
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ profile!!
+ ).get()
val defaultConfig =
- AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
defaultAudioSpec,
defaultSourceSettings,
@@ -177,9 +194,9 @@
val higherSampleRateSourceSettings =
defaultSourceSettings.toBuilder().setChannelCount(defaultSampleRate * 2).build()
- val higherSampleRateConfig = AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ val higherSampleRateConfig = AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
defaultAudioSpec,
higherSampleRateSourceSettings,
@@ -191,11 +208,17 @@
@Test
fun bitrateRangeInVideoSpecClampsBitrate() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val defaultSourceSettings =
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val profile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(profile != null)
- val defaultBitrate = profile.audioBitRate
+ val defaultSourceSettings =
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ profile!!
+ ).get()
+
+ val defaultBitrate = profile.bitrate
// Create audio spec with limit 20% higher than default.
val higherBitrate = (defaultBitrate * 1.2).toInt()
@@ -207,9 +230,9 @@
val lowerAudioSpec = AudioSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
assertThat(
- AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
higherAudioSpec,
defaultSourceSettings,
@@ -218,9 +241,9 @@
).isEqualTo(higherBitrate)
assertThat(
- AudioEncoderConfigCamcorderProfileResolver(
- profile.audioCodecMimeType!!,
- profile.requiredAudioProfile,
+ AudioEncoderConfigAudioProfileResolver(
+ profile.mediaType,
+ profile.profile,
timebase,
lowerAudioSpec,
defaultSourceSettings,
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolverTest.kt
similarity index 74%
rename from camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt
rename to camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolverTest.kt
index 5d67a7a..13e4086 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolverTest.kt
@@ -51,7 +51,7 @@
@RunWith(Parameterized::class)
@SmallTest
@SdkSuppress(minSdkVersion = 21)
-class AudioSourceSettingsCamcorderProfileResolverTest(
+class AudioSourceSettingsAudioProfileResolverTest(
private val implName: String,
private val cameraConfig: CameraXConfig
) {
@@ -106,9 +106,17 @@
@Test
fun defaultAudioSpecResolvesToSupportedSettings() {
- val resolvedSettings = videoCapabilities.supportedQualities.map {
- val camcorderProfile = videoCapabilities.getProfile(it)
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, camcorderProfile!!).get()
+ val resolvedSettings = videoCapabilities.supportedQualities.mapNotNull {
+ val encoderProfiles = videoCapabilities.getProfiles(it)!!
+ val audioProfile = encoderProfiles.defaultAudioProfile
+ if (audioProfile == null) {
+ null
+ } else {
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ audioProfile
+ ).get()
+ }
}
resolvedSettings.forEach {
@@ -131,9 +139,17 @@
)
val resolvedSettings = videoCapabilities.supportedQualities.flatMap { quality ->
- val camcorderProfile = videoCapabilities.getProfile(quality)
- audioSpecs.map {
- AudioSourceSettingsCamcorderProfileResolver(it, camcorderProfile!!).get()
+ val encoderProfiles = videoCapabilities.getProfiles(quality)!!
+ val audioProfile = encoderProfiles.defaultAudioProfile
+ if (audioProfile == null) {
+ emptyList()
+ } else {
+ audioSpecs.map {
+ AudioSourceSettingsAudioProfileResolver(
+ it,
+ audioProfile
+ ).get()
+ }
}
}
@@ -149,21 +165,27 @@
}
@Test
- fun sampleRateCanOverrideCamcorderProfile_ifSupported() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+ fun sampleRateCanOverrideEncoderProfiles_ifSupported() {
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val audioProfile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(audioProfile != null)
+
// Get a config using the default audio spec to retrieve the source format
// Note: This relies on resolution of sample rate and source format being independent.
// If a dependency between the two is introduced, this will stop working and will
// need to be rewritten.
- val autoCamcorderProfileConfig =
- AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile!!).get()
+ val autoEncoderProfileConfig =
+ AudioSourceSettingsAudioProfileResolver(
+ defaultAudioSpec,
+ audioProfile!!
+ ).get()
// Try to find a sample rate that is supported, but not the
- // sample rate advertised by CamcorderProfile
+ // sample rate advertised by EncoderProfiles
val nonReportedSampleRate = AudioSource.COMMON_SAMPLE_RATES.firstOrNull {
- it != profile.audioSampleRate && AudioSource.isSettingsSupported(
+ it != audioProfile.sampleRate && AudioSource.isSettingsSupported(
it,
- profile.audioChannels,
- autoCamcorderProfileConfig.audioFormat
+ audioProfile.channels,
+ autoEncoderProfileConfig.audioFormat
)
}
Assume.assumeTrue(
@@ -176,20 +198,26 @@
AudioSpec.builder().setSampleRate(Range(nonReportedSampleRate!!, nonReportedSampleRate))
.build()
val resolvedSampleRate =
- AudioSourceSettingsCamcorderProfileResolver(audioSpec, profile).get().sampleRate
+ AudioSourceSettingsAudioProfileResolver(
+ audioSpec,
+ audioProfile
+ ).get().sampleRate
- assertThat(resolvedSampleRate).isNotEqualTo(profile.audioSampleRate)
+ assertThat(resolvedSampleRate).isNotEqualTo(audioProfile.sampleRate)
assertThat(resolvedSampleRate).isEqualTo(nonReportedSampleRate)
}
@Test
fun audioSpecDefaultProducesValidSourceEnum() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val audioProfile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(audioProfile != null)
+
val audioSpec = AudioSpec.builder().build()
val resolvedAudioSourceEnum =
- AudioSourceSettingsCamcorderProfileResolver(
+ AudioSourceSettingsAudioProfileResolver(
audioSpec,
- profile!!
+ audioProfile!!
).get().audioSource
assertThat(resolvedAudioSourceEnum).isAnyOf(
@@ -200,12 +228,15 @@
@Test
fun audioSpecDefaultProducesValidSourceFormat() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+ val encoderProfiles = videoCapabilities.getProfiles(Quality.HIGHEST)!!
+ val audioProfile = encoderProfiles.defaultAudioProfile
+ Assume.assumeTrue(audioProfile != null)
+
val audioSpec = AudioSpec.builder().build()
val resolvedAudioSourceFormat =
- AudioSourceSettingsCamcorderProfileResolver(
+ AudioSourceSettingsAudioProfileResolver(
audioSpec,
- profile!!
+ audioProfile!!
).get().audioFormat
assertThat(resolvedAudioSourceFormat).isNotEqualTo(AudioFormat.ENCODING_INVALID)
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt
index 066adfd..afdaa23 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt
@@ -18,7 +18,7 @@
import android.util.Range
import androidx.camera.core.impl.Timebase
-import androidx.camera.testing.CamcorderProfileUtil
+import androidx.camera.testing.EncoderProfilesUtil
import androidx.camera.video.VideoSpec
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -44,9 +44,9 @@
@Test
fun defaultVideoSpecProducesValidSettings_forDifferentSurfaceSizes() {
- val surfaceSizeCif = CamcorderProfileUtil.RESOLUTION_CIF
- val surfaceSize720p = CamcorderProfileUtil.RESOLUTION_720P
- val surfaceSize1080p = CamcorderProfileUtil.RESOLUTION_1080P
+ val surfaceSizeCif = EncoderProfilesUtil.RESOLUTION_CIF
+ val surfaceSize720p = EncoderProfilesUtil.RESOLUTION_720P
+ val surfaceSize1080p = EncoderProfilesUtil.RESOLUTION_1080P
val expectedFrameRateRange = Range(FRAME_RATE_30, FRAME_RATE_30)
@@ -96,7 +96,7 @@
@Test
fun bitrateRangeInVideoSpecClampsBitrate() {
- val surfaceSize720p = CamcorderProfileUtil.RESOLUTION_720P
+ val surfaceSize720p = EncoderProfilesUtil.RESOLUTION_720P
// Get default bit rate for this size
val defaultConfig =
@@ -144,7 +144,7 @@
// Give a VideoSpec with a frame rate higher than 30
val videoSpec =
VideoSpec.builder().setFrameRate(Range(FRAME_RATE_60, FRAME_RATE_60)).build()
- val size = CamcorderProfileUtil.RESOLUTION_1080P
+ val size = EncoderProfilesUtil.RESOLUTION_1080P
assertThat(
VideoEncoderConfigDefaultResolver(
@@ -164,7 +164,7 @@
// Give a VideoSpec with a frame rate higher than 30
val videoSpec =
VideoSpec.builder().setFrameRate(Range(FRAME_RATE_60, FRAME_RATE_60)).build()
- val size = CamcorderProfileUtil.RESOLUTION_1080P
+ val size = EncoderProfilesUtil.RESOLUTION_1080P
val expectedFrameRateRange = Range(FRAME_RATE_30, FRAME_RATE_30)
@@ -187,7 +187,7 @@
// Give a VideoSpec with a frame rate higher than 30
val videoSpec =
VideoSpec.builder().setFrameRate(Range(FRAME_RATE_30, FRAME_RATE_45)).build()
- val size = CamcorderProfileUtil.RESOLUTION_1080P
+ val size = EncoderProfilesUtil.RESOLUTION_1080P
val expectedFrameRateRange = Range(FRAME_RATE_30, FRAME_RATE_60)
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolverTest.kt
similarity index 71%
rename from camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt
rename to camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolverTest.kt
index 1a555f6..1719d00 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolverTest.kt
@@ -49,7 +49,7 @@
@RunWith(Parameterized::class)
@SmallTest
@SdkSuppress(minSdkVersion = 21)
-class VideoEncoderConfigCamcorderProfileResolverTest(
+class VideoEncoderConfigVideoProfileResolverTest(
private val implName: String,
private val cameraConfig: CameraXConfig
) {
@@ -103,33 +103,34 @@
@Test
fun defaultVideoSpecProducesValidSettings_forSurfaceSizeEquivalentToQuality() {
val supportedProfiles = videoCapabilities.supportedQualities.map {
- videoCapabilities.getProfile(it)!!
+ videoCapabilities.getProfiles(it)!!
}
supportedProfiles.forEach {
- val config = VideoEncoderConfigCamcorderProfileResolver(
- it.videoCodecMimeType!!,
+ val videoProfile = it.defaultVideoProfile
+ val config = VideoEncoderConfigVideoProfileResolver(
+ videoProfile.mediaType,
timebase,
defaultVideoSpec,
- Size(it.videoFrameWidth, it.videoFrameHeight),
- it,
+ Size(videoProfile.width, videoProfile.height),
+ videoProfile,
/*expectedFrameRateRange=*/null
).get()
- assertThat(config.mimeType).isEqualTo(it.videoCodecMimeType)
- assertThat(config.bitrate).isEqualTo(it.videoBitRate)
- assertThat(config.resolution).isEqualTo(Size(it.videoFrameWidth, it.videoFrameHeight))
- assertThat(config.frameRate).isEqualTo(it.videoFrameRate)
+ assertThat(config.mimeType).isEqualTo(videoProfile.mediaType)
+ assertThat(config.bitrate).isEqualTo(videoProfile.bitrate)
+ assertThat(config.resolution).isEqualTo(Size(videoProfile.width, videoProfile.height))
+ assertThat(config.frameRate).isEqualTo(videoProfile.frameRate)
}
}
@Test
fun bitrateIncreasesOrDecreasesWithIncreaseOrDecreaseInSurfaceSize() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ val profile = videoCapabilities.getProfiles(Quality.HIGHEST)!!.defaultVideoProfile
+ val surfaceSize = Size(profile.width, profile.height)
- val defaultBitrate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val defaultBitrate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -141,8 +142,8 @@
val decreasedSurfaceSize = Size(surfaceSize.width - 100, surfaceSize.height - 100)
assertThat(
- VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
increasedSurfaceSize,
@@ -152,8 +153,8 @@
).isGreaterThan(defaultBitrate)
assertThat(
- VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
decreasedSurfaceSize,
@@ -165,11 +166,11 @@
@Test
fun bitrateRangeInVideoSpecClampsBitrate() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ val profile = videoCapabilities.getProfiles(Quality.HIGHEST)!!.defaultVideoProfile
+ val surfaceSize = Size(profile.width, profile.height)
- val defaultBitrate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val defaultBitrate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -187,8 +188,8 @@
val lowerVideoSpec = VideoSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
assertThat(
- VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
higherVideoSpec,
surfaceSize,
@@ -198,8 +199,8 @@
).isEqualTo(higherBitrate)
assertThat(
- VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
lowerVideoSpec,
surfaceSize,
@@ -211,15 +212,15 @@
@Test
fun resolvedFrameRateIsClampedToOperatingRate() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ val profile = videoCapabilities.getProfiles(Quality.HIGHEST)!!.defaultVideoProfile
+ val surfaceSize = Size(profile.width, profile.height)
// Construct operating ranges that are both lower and higher than the profile FPS
- val lowerOperatingRange = Range(profile.videoFrameRate / 4, profile.videoFrameRate / 2)
- val higherOperatingRange = Range(profile.videoFrameRate * 2, profile.videoFrameRate * 4)
+ val lowerOperatingRange = Range(profile.frameRate / 4, profile.frameRate / 2)
+ val higherOperatingRange = Range(profile.frameRate * 2, profile.frameRate * 4)
- val clampedDownFrameRate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val clampedDownFrameRate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -227,8 +228,8 @@
lowerOperatingRange
).get().frameRate
- val clampedUpFrameRate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val clampedUpFrameRate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -242,14 +243,14 @@
@Test
fun resolvedFrameRateInsideOperatingRangeIsUnchanged() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ val profile = videoCapabilities.getProfiles(Quality.HIGHEST)!!.defaultVideoProfile
+ val surfaceSize = Size(profile.width, profile.height)
// Construct a range that includes the profile FPS
- val operatingRange = Range(profile.videoFrameRate / 2, profile.videoFrameRate * 2)
+ val operatingRange = Range(profile.frameRate / 2, profile.frameRate * 2)
- val resolvedFrameRate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val resolvedFrameRate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -257,20 +258,20 @@
operatingRange
).get().frameRate
- assertThat(resolvedFrameRate).isEqualTo(profile.videoFrameRate)
+ assertThat(resolvedFrameRate).isEqualTo(profile.frameRate)
}
@Test
fun bitrateScalesWithFrameRateOperatingRange() {
- val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
- val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+ val profile = videoCapabilities.getProfiles(Quality.HIGHEST)!!.defaultVideoProfile
+ val surfaceSize = Size(profile.width, profile.height)
// Construct a range which is constant and half the profile FPS
- val operatingFrameRate = profile.videoFrameRate / 2
+ val operatingFrameRate = profile.frameRate / 2
val operatingRange = Range(operatingFrameRate, operatingFrameRate)
- val resolvedBitrate = VideoEncoderConfigCamcorderProfileResolver(
- profile.videoCodecMimeType!!,
+ val resolvedBitrate = VideoEncoderConfigVideoProfileResolver(
+ profile.mediaType,
timebase,
defaultVideoSpec,
surfaceSize,
@@ -279,8 +280,7 @@
).get().bitrate
assertThat(resolvedBitrate).isEqualTo(
- (profile.videoBitRate *
- (operatingFrameRate.toDouble() / profile.videoFrameRate)).toInt()
+ (profile.bitrate * (operatingFrameRate.toDouble() / profile.frameRate)).toInt()
)
}
}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/workaround/EncoderFinderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/workaround/EncoderFinderTest.kt
index 72350dc..4af3517 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/workaround/EncoderFinderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/workaround/EncoderFinderTest.kt
@@ -37,7 +37,7 @@
import androidx.camera.video.VideoSpec
import androidx.camera.video.internal.compat.quirk.DeviceQuirks
import androidx.camera.video.internal.compat.quirk.MediaCodecInfoReportIncorrectInfoQuirk
-import androidx.camera.video.internal.config.VideoEncoderConfigCamcorderProfileResolver
+import androidx.camera.video.internal.config.VideoEncoderConfigVideoProfileResolver
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
@@ -144,7 +144,7 @@
@LabTestRule.LabTestOnly
@Test
- fun findEncoderForFormat_CamcorderProfile() {
+ fun findEncoderForFormat_EncoderProfiles() {
// Arrange.
val cameraInfo = camera.cameraInfo as CameraInfoInternal
val resolution = QualitySelector.getResolution(cameraInfo, quality)
@@ -153,18 +153,18 @@
resolution != null
)
- val camcorderProfile = VideoCapabilities.from(cameraInfo).getProfile(quality)
- val camcorderProfileVideoMime = camcorderProfile!!.videoCodecMimeType!!
+ val encoderProfiles = VideoCapabilities.from(cameraInfo).getProfiles(quality)
+ val videoProfile = encoderProfiles!!.defaultVideoProfile
val videoSpec =
VideoSpec.builder().setQualitySelector(QualitySelector.from(quality)).build()
- val mediaFormat = VideoEncoderConfigCamcorderProfileResolver(
- camcorderProfileVideoMime,
+ val mediaFormat = VideoEncoderConfigVideoProfileResolver(
+ videoProfile.mediaType,
timebase,
videoSpec,
resolution!!,
- camcorderProfile,
+ videoProfile,
/*expectedFrameRateRange=*/null
).get().toMediaFormat()
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java b/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
index ae10a14..a48f442 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
@@ -27,7 +27,8 @@
import androidx.annotation.RestrictTo;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.core.util.Preconditions;
import java.util.ArrayList;
@@ -139,8 +140,9 @@
@Nullable
public static Size getResolution(@NonNull CameraInfo cameraInfo, @NonNull Quality quality) {
checkQualityConstantsOrThrow(quality);
- CamcorderProfileProxy profile = VideoCapabilities.from(cameraInfo).getProfile(quality);
- return profile != null ? getProfileVideoSize(profile) : null;
+ VideoValidatedEncoderProfilesProxy profiles =
+ VideoCapabilities.from(cameraInfo).getProfiles(quality);
+ return profiles != null ? getProfileVideoSize(profiles) : null;
}
/**
@@ -156,7 +158,7 @@
Map<Quality, Size> map = new HashMap<>();
for (Quality supportedQuality : videoCapabilities.getSupportedQualities()) {
map.put(supportedQuality, getProfileVideoSize(
- requireNonNull(videoCapabilities.getProfile(supportedQuality))));
+ requireNonNull(videoCapabilities.getProfiles(supportedQuality))));
}
return map;
}
@@ -404,8 +406,9 @@
}
@NonNull
- private static Size getProfileVideoSize(@NonNull CamcorderProfileProxy profile) {
- return new Size(profile.getVideoFrameWidth(), profile.getVideoFrameHeight());
+ private static Size getProfileVideoSize(@NonNull VideoValidatedEncoderProfilesProxy profiles) {
+ VideoProfileProxy videoProfile = profiles.getDefaultVideoProfile();
+ return new Size(videoProfile.getWidth(), videoProfile.getHeight());
}
private static void checkQualityConstantsOrThrow(@NonNull List<Quality> qualities) {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
index 701b88d..78f4a24 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
@@ -59,7 +59,6 @@
import androidx.camera.core.AspectRatio;
import androidx.camera.core.Logger;
import androidx.camera.core.SurfaceRequest;
-import androidx.camera.core.impl.CamcorderProfileProxy;
import androidx.camera.core.impl.MutableStateObservable;
import androidx.camera.core.impl.Observable;
import androidx.camera.core.impl.StateObservable;
@@ -74,6 +73,7 @@
import androidx.camera.video.StreamInfo.StreamState;
import androidx.camera.video.internal.AudioSource;
import androidx.camera.video.internal.AudioSourceAccessException;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.compat.Api26Impl;
import androidx.camera.video.internal.compat.quirk.DeactivateEncoderSurfaceBeforeStopEncoderQuirk;
import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
@@ -346,7 +346,7 @@
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
boolean mInProgressRecordingStopping = false;
private SurfaceRequest.TransformationInfo mSurfaceTransformationInfo = null;
- private CamcorderProfileProxy mResolvedCamcorderProfile = null;
+ private VideoValidatedEncoderProfilesProxy mResolvedEncoderProfiles = null;
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
final List<ListenableFuture<Void>> mEncodingFutures = new ArrayList<>();
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
@@ -1041,17 +1041,17 @@
surfaceRequest.setTransformationInfoListener(mSequentialExecutor,
(transformationInfo) -> mSurfaceTransformationInfo = transformationInfo);
Size surfaceSize = surfaceRequest.getResolution();
- // Fetch and cache nearest camcorder profile, if one exists.
+ // Fetch and cache nearest encoder profiles, if one exists.
VideoCapabilities capabilities =
VideoCapabilities.from(surfaceRequest.getCamera().getCameraInfo());
Quality highestSupportedQuality = capabilities.findHighestSupportedQualityFor(surfaceSize);
Logger.d(TAG, "Using supported quality of " + highestSupportedQuality
+ " for surface size " + surfaceSize);
if (highestSupportedQuality != Quality.NONE) {
- mResolvedCamcorderProfile = capabilities.getProfile(highestSupportedQuality);
- if (mResolvedCamcorderProfile == null) {
+ mResolvedEncoderProfiles = capabilities.getProfiles(highestSupportedQuality);
+ if (mResolvedEncoderProfiles == null) {
throw new AssertionError("Camera advertised available quality but did not "
- + "produce CamcorderProfile for advertised quality.");
+ + "produce EncoderProfiles for advertised quality.");
}
}
setupVideo(surfaceRequest, videoSourceTimebase);
@@ -1071,7 +1071,7 @@
MediaSpec mediaSpec = getObservableData(mMediaSpec);
ListenableFuture<Encoder> configureFuture =
videoEncoderSession.configure(request, timebase, mediaSpec,
- mResolvedCamcorderProfile);
+ mResolvedEncoderProfiles);
mVideoEncoderSession = videoEncoderSession;
Futures.addCallback(configureFuture, new FutureCallback<Encoder>() {
@Override
@@ -1237,7 +1237,7 @@
throws AudioSourceAccessException, InvalidConfigException {
MediaSpec mediaSpec = getObservableData(mMediaSpec);
// Resolve the audio mime info
- MimeInfo audioMimeInfo = resolveAudioMimeInfo(mediaSpec, mResolvedCamcorderProfile);
+ MimeInfo audioMimeInfo = resolveAudioMimeInfo(mediaSpec, mResolvedEncoderProfiles);
Timebase audioSourceTimebase = Timebase.UPTIME;
// Select and create the audio source
@@ -1377,7 +1377,7 @@
MediaSpec mediaSpec = getObservableData(mMediaSpec);
int muxerOutputFormat =
mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO
- ? supportedMuxerFormatOrDefaultFrom(mResolvedCamcorderProfile,
+ ? supportedMuxerFormatOrDefaultFrom(mResolvedEncoderProfiles,
MediaSpec.outputFormatToMuxerFormat(
MEDIA_SPEC_DEFAULT.getOutputFormat()))
: MediaSpec.outputFormatToMuxerFormat(mediaSpec.getOutputFormat());
@@ -2566,9 +2566,9 @@
}
private static int supportedMuxerFormatOrDefaultFrom(
- @Nullable CamcorderProfileProxy profileProxy, int defaultMuxerFormat) {
- if (profileProxy != null) {
- switch (profileProxy.getFileFormat()) {
+ @Nullable VideoValidatedEncoderProfilesProxy profilesProxy, int defaultMuxerFormat) {
+ if (profilesProxy != null) {
+ switch (profilesProxy.getRecommendedFileFormat()) {
case MediaRecorder.OutputFormat.MPEG_4:
return MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
case MediaRecorder.OutputFormat.WEBM:
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
index dfd3af6..a28a713 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
@@ -25,10 +25,14 @@
import androidx.annotation.RestrictTo.Scope;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProvider;
-import androidx.camera.core.impl.CamcorderProfileProxy;
import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.EncoderProfilesProvider;
+import androidx.camera.core.impl.EncoderProfilesProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy;
+import androidx.camera.core.impl.Quirks;
+import androidx.camera.core.impl.ResolutionValidatedEncoderProfilesProvider;
import androidx.camera.core.impl.utils.CompareSizesByArea;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
import androidx.camera.video.internal.compat.quirk.VideoQualityQuirk;
import androidx.core.util.Preconditions;
@@ -54,55 +58,61 @@
private static final String TAG = "VideoCapabilities";
/**
- * The supported @link CamcorderProfileProxy} map from quality to CamcorderProfileProxy. The
- * order is from size large to small.
+ * Maps quality to supported {@link VideoValidatedEncoderProfilesProxy}. The order is from
+ * size large to small.
*/
- private final Map<Quality, CamcorderProfileProxy> mSupportedProfileMap = new LinkedHashMap<>();
+ private final Map<Quality, VideoValidatedEncoderProfilesProxy> mSupportedProfilesMap =
+ new LinkedHashMap<>();
private final TreeMap<Size, Quality> mAreaSortedSizeToQualityMap =
new TreeMap<>(new CompareSizesByArea());
- private final CamcorderProfileProxy mHighestProfile;
- private final CamcorderProfileProxy mLowestProfile;
+ private final VideoValidatedEncoderProfilesProxy mHighestProfiles;
+ private final VideoValidatedEncoderProfilesProxy mLowestProfiles;
+ private final EncoderProfilesProvider mEncoderProfilesProvider;
/**
* Creates a VideoCapabilities.
*
* @param cameraInfoInternal the cameraInfo
* @throws IllegalArgumentException if unable to get the capability information from the
- * CameraInfo.
+ * CameraInfo.
*/
VideoCapabilities(@NonNull CameraInfoInternal cameraInfoInternal) {
- CamcorderProfileProvider camcorderProfileProvider =
- cameraInfoInternal.getCamcorderProfileProvider();
+ Quirks cameraQuirks = cameraInfoInternal.getCameraQuirks();
+ mEncoderProfilesProvider = new ResolutionValidatedEncoderProfilesProvider(
+ cameraInfoInternal.getEncoderProfilesProvider(), cameraQuirks);
// Construct supported profile map
for (Quality quality : Quality.getSortedQualities()) {
- // SortedQualities is from size large to small
- Preconditions.checkState(quality instanceof Quality.ConstantQuality,
- "Currently only support ConstantQuality");
- int qualityValue = ((Quality.ConstantQuality) quality).getValue();
-
- // Get CamcorderProfile
- if (!camcorderProfileProvider.hasProfile(qualityValue) || !isDeviceValidQuality(
- cameraInfoInternal, quality)) {
+ EncoderProfilesProxy profiles = getEncoderProfiles(cameraInfoInternal, quality);
+ if (profiles == null) {
continue;
}
- CamcorderProfileProxy profile =
- Preconditions.checkNotNull(camcorderProfileProvider.get(qualityValue));
- Size profileSize = new Size(profile.getVideoFrameWidth(),
- profile.getVideoFrameHeight());
- Logger.d(TAG, "profile = " + profile);
- mSupportedProfileMap.put(quality, profile);
- mAreaSortedSizeToQualityMap.put(profileSize, quality);
+
+ // Validate that EncoderProfiles contain video information
+ Logger.d(TAG, "profiles = " + profiles);
+ VideoValidatedEncoderProfilesProxy validatedProfiles = toValidatedProfiles(profiles);
+ if (validatedProfiles == null) {
+ Logger.w(TAG, "EncoderProfiles of quality " + quality + " has no video "
+ + "validated profiles.");
+ continue;
+ }
+
+ VideoProfileProxy videoProfile = validatedProfiles.getDefaultVideoProfile();
+ Size size = new Size(videoProfile.getWidth(), videoProfile.getHeight());
+ mAreaSortedSizeToQualityMap.put(size, quality);
+
+ // SortedQualities is from size large to small
+ mSupportedProfilesMap.put(quality, validatedProfiles);
}
- if (mSupportedProfileMap.isEmpty()) {
- Logger.e(TAG, "No supported CamcorderProfile");
- mLowestProfile = null;
- mHighestProfile = null;
+ if (mSupportedProfilesMap.isEmpty()) {
+ Logger.e(TAG, "No supported EncoderProfiles");
+ mLowestProfiles = null;
+ mHighestProfiles = null;
} else {
- Deque<CamcorderProfileProxy> profileQueue = new ArrayDeque<>(
- mSupportedProfileMap.values());
- mHighestProfile = profileQueue.peekFirst();
- mLowestProfile = profileQueue.peekLast();
+ Deque<VideoValidatedEncoderProfilesProxy> profileQueue = new ArrayDeque<>(
+ mSupportedProfilesMap.values());
+ mHighestProfiles = profileQueue.peekFirst();
+ mLowestProfiles = profileQueue.peekLast();
}
}
@@ -116,77 +126,78 @@
* Gets all supported qualities on the device.
*
* <p>The returned list is sorted by quality size from large to small. For the qualities in
- * the returned list, calling {@link #getProfile(Quality)} with these qualities will return a
+ * the returned list, calling {@link #getProfiles(Quality)} with these qualities will return a
* non-null result.
*
* <p>Note: Constants {@link Quality#HIGHEST} and {@link Quality#LOWEST} are not included.
*/
@NonNull
public List<Quality> getSupportedQualities() {
- return new ArrayList<>(mSupportedProfileMap.keySet());
+ return new ArrayList<>(mSupportedProfilesMap.keySet());
}
/**
* Checks if the quality is supported.
*
* @param quality one of the quality constants. Possible values include
- * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link Quality#SD},
- * {@link Quality#HD}, {@link Quality#FHD}, or {@link Quality#UHD}.
+ * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link Quality#SD},
+ * {@link Quality#HD}, {@link Quality#FHD}, or {@link Quality#UHD}.
* @return {@code true} if the quality is supported; {@code false} otherwise.
* @throws IllegalArgumentException if not a quality constant.
*/
public boolean isQualitySupported(@NonNull Quality quality) {
checkQualityConstantsOrThrow(quality);
- return getProfile(quality) != null;
+ return getProfiles(quality) != null;
}
/**
- * Gets the corresponding {@link CamcorderProfileProxy} of the input quality.
+ * Gets the corresponding {@link VideoValidatedEncoderProfilesProxy} of the input quality.
*
* @param quality one of the quality constants. Possible values include
- * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD},
- * {@link Quality#FHD}, or {@link Quality#UHD}.
- * @return the CamcorderProfileProxy
+ * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link Quality#SD},
+ * {@link Quality#HD}, {@link Quality#FHD}, or {@link Quality#UHD}.
+ * @return the VideoValidatedEncoderProfilesProxy
* @throws IllegalArgumentException if not a quality constant
*/
@Nullable
- public CamcorderProfileProxy getProfile(@NonNull Quality quality) {
+ public VideoValidatedEncoderProfilesProxy getProfiles(@NonNull Quality quality) {
checkQualityConstantsOrThrow(quality);
if (quality == Quality.HIGHEST) {
- return mHighestProfile;
+ return mHighestProfiles;
} else if (quality == Quality.LOWEST) {
- return mLowestProfile;
+ return mLowestProfiles;
}
- return mSupportedProfileMap.get(quality);
+ return mSupportedProfilesMap.get(quality);
}
/**
- * Finds the supported CamcorderProfileProxy with the resolution nearest to the given
+ * Finds the supported EncoderProfilesProxy with the resolution nearest to the given
* {@link Size}.
*
- * <p>The supported CamcorderProfileProxy means the corresponding {@link Quality} is also
- * supported. If the size aligns exactly with the pixel count of a CamcorderProfileProxy, that
- * CamcorderProfileProxy will be selected. If the size falls between two
- * CamcorderProfileProxy, the higher resolution will always be selected. Otherwise, the
- * nearest CamcorderProfileProxy will be selected, whether that CamcorderProfileProxy's
- * resolution is above or below the given size.
+ * <p>The supported EncoderProfilesProxy means the corresponding {@link Quality} is also
+ * supported. If the size aligns exactly with the pixel count of an EncoderProfilesProxy, that
+ * EncoderProfilesProxy will be selected. If the size falls between two EncoderProfilesProxy,
+ * the higher resolution will always be selected. Otherwise, the nearest EncoderProfilesProxy
+ * will be selected, whether that EncoderProfilesProxy's resolution is above or below the
+ * given size.
*
* @see #findHighestSupportedQualityFor(Size)
*/
@Nullable
- public CamcorderProfileProxy findHighestSupportedCamcorderProfileFor(@NonNull Size size) {
- CamcorderProfileProxy camcorderProfile = null;
+ public VideoValidatedEncoderProfilesProxy findHighestSupportedEncoderProfilesFor(
+ @NonNull Size size) {
+ VideoValidatedEncoderProfilesProxy encoderProfiles = null;
Quality highestSupportedQuality = findHighestSupportedQualityFor(size);
Logger.d(TAG,
"Using supported quality of " + highestSupportedQuality + " for size " + size);
if (highestSupportedQuality != Quality.NONE) {
- camcorderProfile = getProfile(highestSupportedQuality);
- if (camcorderProfile == null) {
+ encoderProfiles = getProfiles(highestSupportedQuality);
+ if (encoderProfiles == null) {
throw new AssertionError("Camera advertised available quality but did not "
- + "produce CamcorderProfile for advertised quality.");
+ + "produce EncoderProfiles for advertised quality.");
}
}
- return camcorderProfile;
+ return encoderProfiles;
}
/**
@@ -196,6 +207,7 @@
* will be selected. If the size falls between two qualities, the higher quality will always
* be selected. Otherwise, the nearest single quality will be selected, whether that
* quality's size is above or below the given size.
+ *
* @param size The size representing the number of pixels for comparison. Pixels are assumed
* to be square.
* @return The quality constant defined in {@link Quality}. If no qualities are supported,
@@ -238,4 +250,30 @@
return true;
}
+ @Nullable
+ private EncoderProfilesProxy getEncoderProfiles(@NonNull CameraInfoInternal cameraInfo,
+ @NonNull Quality quality) {
+ Preconditions.checkState(quality instanceof Quality.ConstantQuality,
+ "Currently only support ConstantQuality");
+ int qualityValue = ((Quality.ConstantQuality) quality).getValue();
+
+ if (!mEncoderProfilesProvider.hasProfile(qualityValue) || !isDeviceValidQuality(cameraInfo,
+ quality)) {
+ return null;
+ }
+
+ return mEncoderProfilesProvider.getAll(qualityValue);
+ }
+
+ @Nullable
+ private VideoValidatedEncoderProfilesProxy toValidatedProfiles(
+ @NonNull EncoderProfilesProxy profiles) {
+ // According to the document, the first profile is the default video profile.
+ List<VideoProfileProxy> videoProfiles = profiles.getVideoProfiles();
+ if (videoProfiles.isEmpty()) {
+ return null;
+ }
+
+ return VideoValidatedEncoderProfilesProxy.from(profiles);
+ }
}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
index 1d5fad6..3c0a5fa 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
@@ -73,7 +73,6 @@
import androidx.camera.core.SurfaceRequest;
import androidx.camera.core.UseCase;
import androidx.camera.core.ViewPort;
-import androidx.camera.core.impl.CamcorderProfileProxy;
import androidx.camera.core.impl.CameraCaptureCallback;
import androidx.camera.core.impl.CameraCaptureResult;
import androidx.camera.core.impl.CameraInfoInternal;
@@ -101,10 +100,10 @@
import androidx.camera.core.internal.ThreadConfig;
import androidx.camera.core.processing.DefaultSurfaceProcessor;
import androidx.camera.core.processing.SurfaceEdge;
-import androidx.camera.core.processing.SurfaceProcessorInternal;
import androidx.camera.core.processing.SurfaceProcessorNode;
import androidx.camera.video.StreamInfo.StreamState;
import androidx.camera.video.impl.VideoCaptureConfig;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
import androidx.camera.video.internal.compat.quirk.ExtraSupportedResolutionQuirk;
import androidx.camera.video.internal.compat.quirk.ImageCaptureFailedWhenVideoCaptureIsBoundQuirk;
@@ -194,8 +193,6 @@
@SuppressWarnings("WeakerAccess") // Synthetic access
VideoOutput.SourceState mSourceState = VideoOutput.SourceState.INACTIVE;
@Nullable
- private SurfaceProcessorInternal mSurfaceProcessor;
- @Nullable
private SurfaceProcessorNode mNode;
@Nullable
private VideoEncoderInfo mVideoEncoderInfo;
@@ -311,21 +308,6 @@
}
/**
- * Sets a {@link SurfaceProcessorInternal}.
- *
- * <p>The processor is used to setup post-processing pipeline.
- *
- * <p>Note: the value will only be used when VideoCapture is bound. Calling this method after
- * VideoCapture is bound takes no effect until VideoCapture is rebound.
- *
- * @hide
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- public void setProcessor(@Nullable SurfaceProcessorInternal surfaceProcessor) {
- mSurfaceProcessor = surfaceProcessor;
- }
-
- /**
* {@inheritDoc}
*
* @hide
@@ -719,10 +701,10 @@
@Nullable
private SurfaceProcessorNode createNodeIfNeeded(boolean isCropNeeded) {
- if (mSurfaceProcessor != null || ENABLE_SURFACE_PROCESSING_BY_QUIRK || isCropNeeded) {
+ if (getEffect() != null || ENABLE_SURFACE_PROCESSING_BY_QUIRK || isCropNeeded) {
Logger.d(TAG, "Surface processing is enabled.");
return new SurfaceProcessorNode(requireNonNull(getCamera()),
- mSurfaceProcessor != null ? mSurfaceProcessor :
+ getEffect() != null ? getEffect().createSurfaceProcessorInternal() :
DefaultSurfaceProcessor.Factory.newInstance());
}
return null;
@@ -897,11 +879,11 @@
return mVideoEncoderInfo;
}
- // Find the nearest CamcorderProfile
- CamcorderProfileProxy camcorderProfileProxy =
- videoCapabilities.findHighestSupportedCamcorderProfileFor(resolution);
+ // Find the nearest EncoderProfiles
+ VideoValidatedEncoderProfilesProxy encoderProfiles =
+ videoCapabilities.findHighestSupportedEncoderProfilesFor(resolution);
VideoEncoderInfo videoEncoderInfo = resolveVideoEncoderInfo(videoEncoderInfoFinder,
- camcorderProfileProxy, mediaSpec, resolution, targetFps);
+ encoderProfiles, mediaSpec, resolution, targetFps);
if (videoEncoderInfo == null) {
// If VideoCapture cannot find videoEncoderInfo, it means that VideoOutput should
// also not be able to find the encoder. VideoCapture will not handle this situation
@@ -910,9 +892,9 @@
return null;
}
- Size profileSize = camcorderProfileProxy != null ? new Size(
- camcorderProfileProxy.getVideoFrameWidth(),
- camcorderProfileProxy.getVideoFrameHeight()) : null;
+ Size profileSize = encoderProfiles != null ? new Size(
+ encoderProfiles.getDefaultVideoProfile().getWidth(),
+ encoderProfiles.getDefaultVideoProfile().getHeight()) : null;
videoEncoderInfo = VideoEncoderInfoWrapper.from(videoEncoderInfo, profileSize);
// Cache the VideoEncoderInfo as it should be the same when recreating the pipeline.
@@ -926,12 +908,12 @@
@Nullable
private static VideoEncoderInfo resolveVideoEncoderInfo(
@NonNull Function<VideoEncoderConfig, VideoEncoderInfo> videoEncoderInfoFinder,
- @Nullable CamcorderProfileProxy camcorderProfileProxy,
+ @Nullable VideoValidatedEncoderProfilesProxy encoderProfiles,
@NonNull MediaSpec mediaSpec,
@NonNull Size resolution,
@NonNull Range<Integer> targetFps) {
// Resolve the VideoEncoderConfig
- MimeInfo videoMimeInfo = resolveVideoMimeInfo(mediaSpec, camcorderProfileProxy);
+ MimeInfo videoMimeInfo = resolveVideoMimeInfo(mediaSpec, encoderProfiles);
VideoEncoderConfig videoEncoderConfig = resolveVideoEncoderConfig(
videoMimeInfo,
// Timebase won't affect the found EncoderInfo so give a arbitrary one.
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoEncoderSession.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoEncoderSession.java
index abc597f..9b9d46c 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoEncoderSession.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoEncoderSession.java
@@ -16,8 +16,9 @@
package androidx.camera.video;
-import android.util.Range;
-import android.util.Size;
+import static androidx.camera.video.internal.config.VideoConfigUtil.resolveVideoEncoderConfig;
+import static androidx.camera.video.internal.config.VideoConfigUtil.resolveVideoMimeInfo;
+
import android.view.Surface;
import androidx.annotation.NonNull;
@@ -25,21 +26,18 @@
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
import androidx.camera.core.SurfaceRequest;
-import androidx.camera.core.impl.CamcorderProfileProxy;
import androidx.camera.core.impl.Timebase;
import androidx.camera.core.impl.annotation.ExecutedBy;
import androidx.camera.core.impl.utils.futures.FutureCallback;
import androidx.camera.core.impl.utils.futures.Futures;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.config.MimeInfo;
-import androidx.camera.video.internal.config.VideoEncoderConfigCamcorderProfileResolver;
-import androidx.camera.video.internal.config.VideoEncoderConfigDefaultResolver;
import androidx.camera.video.internal.encoder.Encoder;
import androidx.camera.video.internal.encoder.Encoder.SurfaceInput.OnSurfaceUpdateListener;
import androidx.camera.video.internal.encoder.EncoderFactory;
import androidx.camera.video.internal.encoder.InvalidConfigException;
import androidx.camera.video.internal.encoder.VideoEncoderConfig;
import androidx.concurrent.futures.CallbackToFutureAdapter;
-import androidx.core.util.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
@@ -109,7 +107,7 @@
@ExecutedBy("mSequentialExecutor")
ListenableFuture<Encoder> configure(@NonNull SurfaceRequest surfaceRequest,
@NonNull Timebase timebase, @NonNull MediaSpec mediaSpec,
- @Nullable CamcorderProfileProxy resolvedCamcorderProfile) {
+ @Nullable VideoValidatedEncoderProfilesProxy resolvedEncoderProfiles) {
switch (mVideoEncoderState) {
case NOT_INITIALIZED:
mVideoEncoderState = VideoEncoderState.INITIALIZING;
@@ -127,7 +125,7 @@
ListenableFuture<Encoder> configureFuture = CallbackToFutureAdapter.getFuture(
completer -> {
configureVideoEncoderInternal(surfaceRequest, timebase,
- resolvedCamcorderProfile,
+ resolvedEncoderProfiles,
mediaSpec, completer);
return "ConfigureVideoEncoderFuture " + VideoEncoderSession.this;
});
@@ -286,10 +284,10 @@
@ExecutedBy("mSequentialExecutor")
private void configureVideoEncoderInternal(@NonNull SurfaceRequest surfaceRequest,
@NonNull Timebase timebase,
- @Nullable CamcorderProfileProxy resolvedCamcorderProfile,
+ @Nullable VideoValidatedEncoderProfilesProxy resolvedEncoderProfiles,
@NonNull MediaSpec mediaSpec,
@NonNull CallbackToFutureAdapter.Completer<Encoder> configureCompleter) {
- MimeInfo videoMimeInfo = resolveVideoMimeInfo(resolvedCamcorderProfile, mediaSpec);
+ MimeInfo videoMimeInfo = resolveVideoMimeInfo(mediaSpec, resolvedEncoderProfiles);
// The VideoSpec from mediaSpec only contains settings requested by the recorder, but
// the actual settings may need to differ depending on the FPS chosen by the camera.
@@ -371,69 +369,6 @@
}
}
- @ExecutedBy("mSequentialExecutor")
- private MimeInfo resolveVideoMimeInfo(@Nullable CamcorderProfileProxy resolvedCamcorderProfile,
- @NonNull MediaSpec mediaSpec) {
- String mediaSpecVideoMime = MediaSpec.outputFormatToVideoMime(mediaSpec.getOutputFormat());
- String resolvedVideoMime = mediaSpecVideoMime;
- boolean camcorderProfileIsCompatible = false;
- if (resolvedCamcorderProfile != null) {
- String camcorderProfileVideoMime = resolvedCamcorderProfile.getVideoCodecMimeType();
- // Use camcorder profile settings if the media spec's output format
- // is set to auto or happens to match the CamcorderProfile's output format.
- if (camcorderProfileVideoMime == null) {
- Logger.d(TAG, "CamcorderProfile contains undefined VIDEO mime type so cannot be "
- + "used. May rely on fallback defaults to derive settings "
- + "[chosen mime type: " + resolvedVideoMime + "]");
- } else if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
- camcorderProfileIsCompatible = true;
- resolvedVideoMime = camcorderProfileVideoMime;
- Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using CamcorderProfile "
- + "to derive VIDEO settings [mime type: " + resolvedVideoMime + "]");
- } else if (Objects.equals(mediaSpecVideoMime, camcorderProfileVideoMime)) {
- camcorderProfileIsCompatible = true;
- resolvedVideoMime = camcorderProfileVideoMime;
- Logger.d(TAG, "MediaSpec video mime matches CamcorderProfile. Using "
- + "CamcorderProfile to derive VIDEO settings [mime type: "
- + resolvedVideoMime + "]");
- } else {
- Logger.d(TAG, "MediaSpec video mime does not match CamcorderProfile, so "
- + "CamcorderProfile settings cannot be used. May rely on fallback "
- + "defaults to derive VIDEO settings [CamcorderProfile mime type: "
- + camcorderProfileVideoMime + ", chosen mime type: " + resolvedVideoMime
- + "]");
- }
- } else {
- Logger.d(TAG, "No CamcorderProfile present. May rely on fallback defaults to derive "
- + "VIDEO settings [chosen mime type: " + resolvedVideoMime + "]");
- }
-
- MimeInfo.Builder mimeInfoBuilder = MimeInfo.builder(resolvedVideoMime);
- if (camcorderProfileIsCompatible) {
- mimeInfoBuilder.setCompatibleCamcorderProfile(resolvedCamcorderProfile);
- }
-
- return mimeInfoBuilder.build();
- }
-
- @NonNull
- private static VideoEncoderConfig resolveVideoEncoderConfig(@NonNull MimeInfo videoMimeInfo,
- @NonNull Timebase timebase, @NonNull VideoSpec videoSpec, @NonNull Size surfaceSize,
- @Nullable Range<Integer> expectedFrameRateRange) {
- Supplier<VideoEncoderConfig> configSupplier;
- if (videoMimeInfo.getCompatibleCamcorderProfile() != null) {
- configSupplier = new VideoEncoderConfigCamcorderProfileResolver(
- videoMimeInfo.getMimeType(), timebase, videoSpec, surfaceSize,
- videoMimeInfo.getCompatibleCamcorderProfile(),
- expectedFrameRateRange);
- } else {
- configSupplier = new VideoEncoderConfigDefaultResolver(videoMimeInfo.getMimeType(),
- timebase, videoSpec, surfaceSize, expectedFrameRateRange);
- }
-
- return configSupplier.get();
- }
-
@NonNull
@Override
public String toString() {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/ReportedVideoQualityNotSupportedQuirk.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/ReportedVideoQualityNotSupportedQuirk.java
index acf2bd5..d4bf9fe 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/ReportedVideoQualityNotSupportedQuirk.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/ReportedVideoQualityNotSupportedQuirk.java
@@ -25,7 +25,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CamcorderProfileProvider;
import androidx.camera.core.impl.CameraInfoInternal;
import androidx.camera.video.Quality;
@@ -33,7 +32,7 @@
import java.util.Locale;
/**
- * Quirk where qualities reported as available by {@link CamcorderProfileProvider#hasProfile(int)}
+ * Quirk where qualities reported as available by {@link CamcorderProfile#hasProfile(int)}
* does not work on the device, and should not be used.
*
* <p>QuirkSummary
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java
index 61bea4c..9979dd5 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java
@@ -16,6 +16,8 @@
package androidx.camera.video.internal.config;
+import static java.util.Objects.requireNonNull;
+
import android.util.Range;
import android.util.Rational;
@@ -23,11 +25,12 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.AudioProfileProxy;
import androidx.camera.core.impl.Timebase;
import androidx.camera.video.AudioSpec;
import androidx.camera.video.MediaSpec;
import androidx.camera.video.internal.AudioSource;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.encoder.AudioEncoderConfig;
import androidx.core.util.Supplier;
@@ -60,48 +63,48 @@
* Resolves the audio mime information into a {@link MimeInfo}.
*
* @param mediaSpec the media spec to resolve the mime info.
- * @param camcorderProfile the camcorder profile to resolve the mime info. It can be null if
- * there is no relevant camcorder profile.
+ * @param encoderProfiles the encoder profiles to resolve the mime info. It can be null if
+ * there is no relevant encoder profiles.
* @return the audio MimeInfo.
*/
@NonNull
public static MimeInfo resolveAudioMimeInfo(@NonNull MediaSpec mediaSpec,
- @Nullable CamcorderProfileProxy camcorderProfile) {
+ @Nullable VideoValidatedEncoderProfilesProxy encoderProfiles) {
String mediaSpecAudioMime = MediaSpec.outputFormatToAudioMime(mediaSpec.getOutputFormat());
int mediaSpecAudioProfile =
MediaSpec.outputFormatToAudioProfile(mediaSpec.getOutputFormat());
String resolvedAudioMime = mediaSpecAudioMime;
int resolvedAudioProfile = mediaSpecAudioProfile;
- boolean camcorderProfileIsCompatible = false;
- if (camcorderProfile != null) {
- String camcorderProfileAudioMime = camcorderProfile.getAudioCodecMimeType();
- int camcorderProfileAudioProfile = camcorderProfile.getRequiredAudioProfile();
+ boolean encoderProfilesIsCompatible = false;
+ if (encoderProfiles != null && encoderProfiles.getDefaultAudioProfile() != null) {
+ AudioProfileProxy audioProfile = encoderProfiles.getDefaultAudioProfile();
+ String encoderProfileAudioMime = audioProfile.getMediaType();
+ int encoderProfileAudioProfile = audioProfile.getProfile();
- if (camcorderProfileAudioMime == null) {
- Logger.d(TAG, "CamcorderProfile contains undefined AUDIO mime type so cannot be "
+ if (Objects.equals(encoderProfileAudioMime, AudioProfileProxy.MEDIA_TYPE_NONE)) {
+ Logger.d(TAG, "EncoderProfiles contains undefined AUDIO mime type so cannot be "
+ "used. May rely on fallback defaults to derive settings [chosen mime "
+ "type: "
+ resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
} else if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
- camcorderProfileIsCompatible = true;
- resolvedAudioMime = camcorderProfileAudioMime;
- resolvedAudioProfile = camcorderProfileAudioProfile;
- Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using CamcorderProfile "
+ encoderProfilesIsCompatible = true;
+ resolvedAudioMime = encoderProfileAudioMime;
+ resolvedAudioProfile = encoderProfileAudioProfile;
+ Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using EncoderProfiles "
+ "to derive AUDIO settings [mime type: "
+ resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
- } else if (Objects.equals(mediaSpecAudioMime, camcorderProfileAudioMime)
- && mediaSpecAudioProfile == camcorderProfileAudioProfile) {
- camcorderProfileIsCompatible = true;
- resolvedAudioMime = camcorderProfileAudioMime;
- resolvedAudioProfile = camcorderProfileAudioProfile;
- Logger.d(TAG, "MediaSpec audio mime/profile matches CamcorderProfile. "
- + "Using CamcorderProfile to derive AUDIO settings [mime type: "
+ } else if (Objects.equals(mediaSpecAudioMime, encoderProfileAudioMime)
+ && mediaSpecAudioProfile == encoderProfileAudioProfile) {
+ encoderProfilesIsCompatible = true;
+ resolvedAudioMime = encoderProfileAudioMime;
+ Logger.d(TAG, "MediaSpec audio mime/profile matches EncoderProfiles. "
+ + "Using EncoderProfiles to derive AUDIO settings [mime type: "
+ resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
} else {
- Logger.d(TAG, "MediaSpec audio mime or profile does not match CamcorderProfile, so "
- + "CamcorderProfile settings cannot be used. May rely on fallback "
- + "defaults to derive AUDIO settings [CamcorderProfile mime type: "
- + camcorderProfileAudioMime + "(profile: " + camcorderProfileAudioProfile
+ Logger.d(TAG, "MediaSpec audio mime or profile does not match EncoderProfiles, so "
+ + "EncoderProfiles settings cannot be used. May rely on fallback defaults"
+ + " to derive AUDIO settings [EncoderProfiles mime type: "
+ + encoderProfileAudioMime + "(profile: " + encoderProfileAudioProfile
+ "), chosen mime type: "
+ resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
}
@@ -109,8 +112,8 @@
MimeInfo.Builder mimeInfoBuilder = MimeInfo.builder(resolvedAudioMime)
.setProfile(resolvedAudioProfile);
- if (camcorderProfileIsCompatible) {
- mimeInfoBuilder.setCompatibleCamcorderProfile(camcorderProfile);
+ if (encoderProfilesIsCompatible) {
+ mimeInfoBuilder.setCompatibleEncoderProfiles(encoderProfiles);
}
return mimeInfoBuilder.build();
@@ -127,9 +130,10 @@
public static AudioSource.Settings resolveAudioSourceSettings(@NonNull MimeInfo audioMimeInfo,
@NonNull AudioSpec audioSpec) {
Supplier<AudioSource.Settings> settingsSupplier;
- if (audioMimeInfo.getCompatibleCamcorderProfile() != null) {
- settingsSupplier = new AudioSourceSettingsCamcorderProfileResolver(audioSpec,
- audioMimeInfo.getCompatibleCamcorderProfile());
+ VideoValidatedEncoderProfilesProxy profiles = audioMimeInfo.getCompatibleEncoderProfiles();
+ if (profiles != null) {
+ AudioProfileProxy audioProfile = requireNonNull(profiles.getDefaultAudioProfile());
+ settingsSupplier = new AudioSourceSettingsAudioProfileResolver(audioSpec, audioProfile);
} else {
settingsSupplier = new AudioSourceSettingsDefaultResolver(audioSpec);
}
@@ -151,10 +155,12 @@
@NonNull Timebase inputTimebase, @NonNull AudioSource.Settings audioSourceSettings,
@NonNull AudioSpec audioSpec) {
Supplier<AudioEncoderConfig> configSupplier;
- if (audioMimeInfo.getCompatibleCamcorderProfile() != null) {
- configSupplier = new AudioEncoderConfigCamcorderProfileResolver(
+ VideoValidatedEncoderProfilesProxy profiles = audioMimeInfo.getCompatibleEncoderProfiles();
+ if (profiles != null) {
+ AudioProfileProxy audioProfile = requireNonNull(profiles.getDefaultAudioProfile());
+ configSupplier = new AudioEncoderConfigAudioProfileResolver(
audioMimeInfo.getMimeType(), audioMimeInfo.getProfile(), inputTimebase,
- audioSpec, audioSourceSettings, audioMimeInfo.getCompatibleCamcorderProfile());
+ audioSpec, audioSourceSettings, audioProfile);
} else {
configSupplier = new AudioEncoderConfigDefaultResolver(audioMimeInfo.getMimeType(),
audioMimeInfo.getProfile(), inputTimebase, audioSpec, audioSourceSettings);
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolver.java
similarity index 76%
rename from camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java
rename to camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolver.java
index 21d59a3..167050f 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigAudioProfileResolver.java
@@ -22,7 +22,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.AudioProfileProxy;
import androidx.camera.core.impl.Timebase;
import androidx.camera.video.AudioSpec;
import androidx.camera.video.internal.AudioSource;
@@ -32,23 +32,23 @@
/**
* An {@link AudioEncoderConfig} supplier that resolves requested encoder settings from an
* {@link AudioSpec} for the given {@link AudioSource.Settings} using the provided
- * {@link CamcorderProfileProxy}.
+ * {@link AudioProfileProxy}.
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public final class AudioEncoderConfigCamcorderProfileResolver implements
+public final class AudioEncoderConfigAudioProfileResolver implements
Supplier<AudioEncoderConfig> {
- private static final String TAG = "AudioEncCmcrdrPrflRslvr";
+ private static final String TAG = "AudioEncAdPrflRslvr";
private final String mMimeType;
private final Timebase mInputTimebase;
private final int mAudioProfile;
private final AudioSpec mAudioSpec;
private final AudioSource.Settings mAudioSourceSettings;
- private final CamcorderProfileProxy mCamcorderProfile;
+ private final AudioProfileProxy mAudioProfileProxy;
/**
- * Constructor for an AudioEncoderConfigCamcorderProfileResolver.
+ * Constructor for an AudioEncoderConfigAudioProfileResolver.
*
* @param mimeType The mime type for the audio encoder
* @param audioProfile The profile required for the audio encoder
@@ -56,30 +56,30 @@
* @param audioSpec The {@link AudioSpec} which defines the settings that should be
* used with the audio encoder.
* @param audioSourceSettings The settings used to configure the source of audio.
- * @param camcorderProfile The {@link CamcorderProfileProxy} used to resolve automatic and
+ * @param audioProfileProxy The {@link AudioProfileProxy} used to resolve automatic and
* range settings.
*/
- public AudioEncoderConfigCamcorderProfileResolver(@NonNull String mimeType,
+ public AudioEncoderConfigAudioProfileResolver(@NonNull String mimeType,
int audioProfile, @NonNull Timebase inputTimebase, @NonNull AudioSpec audioSpec,
@NonNull AudioSource.Settings audioSourceSettings,
- @NonNull CamcorderProfileProxy camcorderProfile) {
+ @NonNull AudioProfileProxy audioProfileProxy) {
mMimeType = mimeType;
mAudioProfile = audioProfile;
mInputTimebase = inputTimebase;
mAudioSpec = audioSpec;
mAudioSourceSettings = audioSourceSettings;
- mCamcorderProfile = camcorderProfile;
+ mAudioProfileProxy = audioProfileProxy;
}
@Override
@NonNull
public AudioEncoderConfig get() {
- Logger.d(TAG, "Using resolved AUDIO bitrate from CamcorderProfile");
+ Logger.d(TAG, "Using resolved AUDIO bitrate from AudioProfile");
Range<Integer> audioSpecBitrateRange = mAudioSpec.getBitrate();
int resolvedBitrate = AudioConfigUtil.scaleAndClampBitrate(
- mCamcorderProfile.getAudioBitRate(),
- mAudioSourceSettings.getChannelCount(), mCamcorderProfile.getAudioChannels(),
- mAudioSourceSettings.getSampleRate(), mCamcorderProfile.getAudioSampleRate(),
+ mAudioProfileProxy.getBitrate(),
+ mAudioSourceSettings.getChannelCount(), mAudioProfileProxy.getChannels(),
+ mAudioSourceSettings.getSampleRate(), mAudioProfileProxy.getSampleRate(),
audioSpecBitrateRange);
return AudioEncoderConfig.builder()
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolver.java
similarity index 64%
rename from camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java
rename to camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolver.java
index 8d6de0f..4b29d22 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsAudioProfileResolver.java
@@ -21,36 +21,36 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.AudioProfileProxy;
import androidx.camera.video.AudioSpec;
import androidx.camera.video.internal.AudioSource;
import androidx.core.util.Supplier;
/**
* An {@link AudioSource.Settings} supplier that resolves requested source settings from an
- * {@link AudioSpec} using a {@link CamcorderProfileProxy}.
+ * {@link AudioSpec} using an {@link AudioProfileProxy}.
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public final class AudioSourceSettingsCamcorderProfileResolver implements
+public final class AudioSourceSettingsAudioProfileResolver implements
Supplier<AudioSource.Settings> {
- private static final String TAG = "AudioSrcCmcrdrPrflRslvr";
+ private static final String TAG = "AudioSrcAdPrflRslvr";
private final AudioSpec mAudioSpec;
- private final CamcorderProfileProxy mCamcorderProfile;
+ private final AudioProfileProxy mAudioProfile;
/**
- * Constructor for an AudioSourceSettingsCamcorderProfileResolver.
+ * Constructor for an AudioSourceSettingsAudioProfileResolver.
*
- * @param camcorderProfile The {@link CamcorderProfileProxy} used to resolve automatic and
- * range settings.
- * @param audioSpec The {@link AudioSpec} which defines the settings that should be
- * used with the audio source.
+ * @param audioProfile The {@link AudioProfileProxy} used to resolve automatic and range
+ * settings.
+ * @param audioSpec The {@link AudioSpec} which defines the settings that should be used
+ * with the audio source.
*/
- public AudioSourceSettingsCamcorderProfileResolver(@NonNull AudioSpec audioSpec,
- @NonNull CamcorderProfileProxy camcorderProfile) {
+ public AudioSourceSettingsAudioProfileResolver(@NonNull AudioSpec audioSpec,
+ @NonNull AudioProfileProxy audioProfile) {
mAudioSpec = audioSpec;
- mCamcorderProfile = camcorderProfile;
+ mAudioProfile = audioProfile;
}
@Override
@@ -67,25 +67,25 @@
Range<Integer> audioSpecSampleRate = mAudioSpec.getSampleRate();
int resolvedSampleRate;
int resolvedChannelCount;
- int camcorderProfileChannelCount = mCamcorderProfile.getAudioChannels();
+ int audioProfileChannelCount = mAudioProfile.getChannels();
if (audioSpecChannelCount == AudioSpec.CHANNEL_COUNT_AUTO) {
- resolvedChannelCount = camcorderProfileChannelCount;
- Logger.d(TAG, "Resolved AUDIO channel count from CamcorderProfile: "
+ resolvedChannelCount = audioProfileChannelCount;
+ Logger.d(TAG, "Resolved AUDIO channel count from AudioProfile: "
+ resolvedChannelCount);
} else {
resolvedChannelCount = audioSpecChannelCount;
- Logger.d(TAG, "Media spec AUDIO channel count overrides CamcorderProfile "
- + "[CamcorderProfile channel count: " + camcorderProfileChannelCount
+ Logger.d(TAG, "Media spec AUDIO channel count overrides AudioProfile "
+ + "[AudioProfile channel count: " + audioProfileChannelCount
+ ", Resolved Channel Count: " + resolvedChannelCount + "]");
}
- int camcorderProfileAudioSampleRate = mCamcorderProfile.getAudioSampleRate();
+ int audioProfileSampleRate = mAudioProfile.getSampleRate();
resolvedSampleRate = AudioConfigUtil.selectSampleRateOrNearestSupported(
audioSpecSampleRate, resolvedChannelCount, resolvedSourceFormat,
- camcorderProfileAudioSampleRate);
+ audioProfileSampleRate);
Logger.d(TAG, "Using resolved AUDIO sample rate or nearest supported from "
- + "CamcorderProfile: " + resolvedSampleRate + "Hz. [CamcorderProfile sample rate: "
- + camcorderProfileAudioSampleRate + "Hz]");
+ + "AudioProfile: " + resolvedSampleRate + "Hz. [AudioProfile sample rate: "
+ + audioProfileSampleRate + "Hz]");
return AudioSource.Settings.builder()
.setAudioSource(resolvedAudioSource)
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java
index 4fbbd71..983626b 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java
@@ -19,7 +19,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.encoder.EncoderConfig;
import com.google.auto.value.AutoValue;
@@ -29,8 +29,9 @@
*
* <p>The information included in this class can include the mime type, profile and any
* compatible configuration types that can be used to resolve settings, such as
- * {@link androidx.camera.core.impl.CamcorderProfileProxy}.
+ * {@link VideoValidatedEncoderProfilesProxy}.
*/
+@SuppressWarnings("NullableProblems") // Problem from AutoValue generated class.
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
@AutoValue
public abstract class MimeInfo {
@@ -49,12 +50,13 @@
public abstract int getProfile();
/**
- * Returns compatible {@link CamcorderProfileProxy} that can be used to resolve settings.
+ * Returns compatible {@link VideoValidatedEncoderProfilesProxy} that can be used to resolve
+ * settings.
*
- * <p>If no camcorder profile is provided, returns {@code null}
+ * <p>If no EncoderProfiles is provided, returns {@code null}
*/
@Nullable
- public abstract CamcorderProfileProxy getCompatibleCamcorderProfile();
+ public abstract VideoValidatedEncoderProfilesProxy getCompatibleEncoderProfiles();
/** Creates a builder for the given mime type */
@NonNull
@@ -76,10 +78,10 @@
@NonNull
public abstract Builder setProfile(int profile);
- /** Sets a compatible camcorder profile */
+ /** Sets a compatible EncoderProfiles */
@NonNull
- public abstract Builder setCompatibleCamcorderProfile(
- @Nullable CamcorderProfileProxy camcorderProfile);
+ public abstract Builder setCompatibleEncoderProfiles(
+ @Nullable VideoValidatedEncoderProfilesProxy encoderProfiles);
/** Builds the {@link androidx.camera.video.internal.config.MimeInfo}. */
@NonNull
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java
index 16416a7..8d3be191 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java
@@ -24,10 +24,11 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy;
import androidx.camera.core.impl.Timebase;
import androidx.camera.video.MediaSpec;
import androidx.camera.video.VideoSpec;
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy;
import androidx.camera.video.internal.encoder.VideoEncoderConfig;
import androidx.core.util.Supplier;
@@ -48,51 +49,51 @@
* Resolves the video mime information into a {@link MimeInfo}.
*
* @param mediaSpec the media spec to resolve the mime info.
- * @param camcorderProfile the camcorder profile to resolve the mime info. It can be null if
- * there is no relevant camcorder profile.
+ * @param encoderProfiles the encoder profiles to resolve the mime info. It can be null if
+ * there is no relevant encoder profiles.
* @return the video MimeInfo.
*/
@NonNull
public static MimeInfo resolveVideoMimeInfo(@NonNull MediaSpec mediaSpec,
- @Nullable CamcorderProfileProxy camcorderProfile) {
+ @Nullable VideoValidatedEncoderProfilesProxy encoderProfiles) {
String mediaSpecVideoMime = MediaSpec.outputFormatToVideoMime(mediaSpec.getOutputFormat());
String resolvedVideoMime = mediaSpecVideoMime;
- boolean camcorderProfileIsCompatible = false;
- if (camcorderProfile != null) {
- String camcorderProfileVideoMime = camcorderProfile.getVideoCodecMimeType();
- // Use camcorder profile settings if the media spec's output format
- // is set to auto or happens to match the CamcorderProfile's output format.
- if (camcorderProfileVideoMime == null) {
- Logger.d(TAG, "CamcorderProfile contains undefined VIDEO mime type so cannot be "
+ boolean encoderProfilesIsCompatible = false;
+ if (encoderProfiles != null) {
+ VideoProfileProxy videoProfile = encoderProfiles.getDefaultVideoProfile();
+ String encoderProfilesVideoMime = videoProfile.getMediaType();
+ // Use EncoderProfiles settings if the media spec's output format is set to auto or
+ // happens to match the EncoderProfiles' output format.
+ if (Objects.equals(encoderProfilesVideoMime, VideoProfileProxy.MEDIA_TYPE_NONE)) {
+ Logger.d(TAG, "EncoderProfiles contains undefined VIDEO mime type so cannot be "
+ "used. May rely on fallback defaults to derive settings [chosen mime "
+ "type: " + resolvedVideoMime + "]");
} else if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
- camcorderProfileIsCompatible = true;
- resolvedVideoMime = camcorderProfileVideoMime;
- Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using CamcorderProfile "
+ encoderProfilesIsCompatible = true;
+ resolvedVideoMime = encoderProfilesVideoMime;
+ Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using EncoderProfiles "
+ "to derive VIDEO settings [mime type: " + resolvedVideoMime + "]");
- } else if (Objects.equals(mediaSpecVideoMime, camcorderProfileVideoMime)) {
- camcorderProfileIsCompatible = true;
- resolvedVideoMime = camcorderProfileVideoMime;
- Logger.d(TAG, "MediaSpec video mime matches CamcorderProfile. Using "
- + "CamcorderProfile to derive VIDEO settings [mime type: "
+ } else if (Objects.equals(mediaSpecVideoMime, encoderProfilesVideoMime)) {
+ encoderProfilesIsCompatible = true;
+ resolvedVideoMime = encoderProfilesVideoMime;
+ Logger.d(TAG, "MediaSpec video mime matches EncoderProfiles. Using "
+ + "EncoderProfiles to derive VIDEO settings [mime type: "
+ resolvedVideoMime + "]");
} else {
- Logger.d(TAG, "MediaSpec video mime does not match CamcorderProfile, so "
- + "CamcorderProfile settings cannot be used. May rely on fallback "
- + "defaults to derive VIDEO settings [CamcorderProfile mime type: "
- + camcorderProfileVideoMime + ", chosen mime type: "
+ Logger.d(TAG, "MediaSpec video mime does not match EncoderProfiles, so "
+ + "EncoderProfiles settings cannot be used. May rely on fallback "
+ + "defaults to derive VIDEO settings [EncoderProfiles mime type: "
+ + encoderProfilesVideoMime + ", chosen mime type: "
+ resolvedVideoMime + "]");
}
} else {
- Logger.d(TAG,
- "No CamcorderProfile present. May rely on fallback defaults to derive VIDEO "
- + "settings [chosen mime type: " + resolvedVideoMime + "]");
+ Logger.d(TAG, "No EncoderProfiles present. May rely on fallback defaults to derive "
+ + "VIDEO settings [chosen mime type: " + resolvedVideoMime + "]");
}
MimeInfo.Builder mimeInfoBuilder = MimeInfo.builder(resolvedVideoMime);
- if (camcorderProfileIsCompatible) {
- mimeInfoBuilder.setCompatibleCamcorderProfile(camcorderProfile);
+ if (encoderProfilesIsCompatible) {
+ mimeInfoBuilder.setCompatibleEncoderProfiles(encoderProfiles);
}
return mimeInfoBuilder.build();
@@ -113,11 +114,11 @@
@NonNull Timebase inputTimebase, @NonNull VideoSpec videoSpec,
@NonNull Size surfaceSize, @Nullable Range<Integer> expectedFrameRateRange) {
Supplier<VideoEncoderConfig> configSupplier;
- if (videoMimeInfo.getCompatibleCamcorderProfile() != null) {
- configSupplier = new VideoEncoderConfigCamcorderProfileResolver(
+ VideoValidatedEncoderProfilesProxy profiles = videoMimeInfo.getCompatibleEncoderProfiles();
+ if (profiles != null) {
+ configSupplier = new VideoEncoderConfigVideoProfileResolver(
videoMimeInfo.getMimeType(), inputTimebase, videoSpec, surfaceSize,
- videoMimeInfo.getCompatibleCamcorderProfile(),
- expectedFrameRateRange);
+ profiles.getDefaultVideoProfile(), expectedFrameRateRange);
} else {
configSupplier = new VideoEncoderConfigDefaultResolver(videoMimeInfo.getMimeType(),
inputTimebase, videoSpec, surfaceSize, expectedFrameRateRange);
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolver.java
similarity index 72%
rename from camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java
rename to camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolver.java
index 5020129..0009f26 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigVideoProfileResolver.java
@@ -23,7 +23,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy;
import androidx.camera.core.impl.Timebase;
import androidx.camera.video.VideoSpec;
import androidx.camera.video.internal.encoder.VideoEncoderConfig;
@@ -32,49 +32,49 @@
/**
* A {@link VideoEncoderConfig} supplier that resolves requested encoder settings from a
* {@link VideoSpec} for the given surface {@link Size} using the provided
- * {@link CamcorderProfileProxy}.
+ * {@link VideoProfileProxy}.
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public class VideoEncoderConfigCamcorderProfileResolver implements Supplier<VideoEncoderConfig> {
+public class VideoEncoderConfigVideoProfileResolver implements Supplier<VideoEncoderConfig> {
- private static final String TAG = "VidEncCmcrdrPrflRslvr";
+ private static final String TAG = "VidEncVdPrflRslvr";
private final String mMimeType;
private final Timebase mInputTimebase;
private final VideoSpec mVideoSpec;
private final Size mSurfaceSize;
- private final CamcorderProfileProxy mCamcorderProfile;
+ private final VideoProfileProxy mVideoProfile;
@Nullable
private final Range<Integer> mExpectedFrameRateRange;
/**
- * Constructor for a VideoEncoderConfigCamcorderProfileResolver.
+ * Constructor for a VideoEncoderConfigVideoProfileResolver.
*
* @param mimeType The mime type for the video encoder
* @param inputTimebase The timebase of the input frame
* @param videoSpec The {@link VideoSpec} which defines the settings that should be
* used with the video encoder.
* @param surfaceSize The size of the surface required by the camera for the video encoder.
- * @param camcorderProfile The {@link CamcorderProfileProxy} used to resolve automatic and
- * range settings.
+ * @param videoProfile The {@link VideoProfileProxy} used to resolve automatic and range
+ * settings.
* @param expectedFrameRateRange The expected source frame rate range. This should act as an
* envelope for any frame rate calculated from {@code videoSpec
- * } and {@code camcorderProfile} since the source should not
+ * } and {@code videoProfile} since the source should not
* produce frames at a frame rate outside this range. If {@code
* null}, then no information about the source frame rate is
* available and it does not need to be used in calculations.
*/
- public VideoEncoderConfigCamcorderProfileResolver(@NonNull String mimeType,
+ public VideoEncoderConfigVideoProfileResolver(@NonNull String mimeType,
@NonNull Timebase inputTimebase,
@NonNull VideoSpec videoSpec,
@NonNull Size surfaceSize,
- @NonNull CamcorderProfileProxy camcorderProfile,
+ @NonNull VideoProfileProxy videoProfile,
@Nullable Range<Integer> expectedFrameRateRange) {
mMimeType = mimeType;
mInputTimebase = inputTimebase;
mVideoSpec = videoSpec;
mSurfaceSize = surfaceSize;
- mCamcorderProfile = camcorderProfile;
+ mVideoProfile = videoProfile;
mExpectedFrameRateRange = expectedFrameRateRange;
}
@@ -85,12 +85,12 @@
Logger.d(TAG, "Resolved VIDEO frame rate: " + resolvedFrameRate + "fps");
Range<Integer> videoSpecBitrateRange = mVideoSpec.getBitrate();
- Logger.d(TAG, "Using resolved VIDEO bitrate from CamcorderProfile");
+ Logger.d(TAG, "Using resolved VIDEO bitrate from EncoderProfiles");
int resolvedBitrate = VideoConfigUtil.scaleAndClampBitrate(
- mCamcorderProfile.getVideoBitRate(),
- resolvedFrameRate, mCamcorderProfile.getVideoFrameRate(),
- mSurfaceSize.getWidth(), mCamcorderProfile.getVideoFrameWidth(),
- mSurfaceSize.getHeight(), mCamcorderProfile.getVideoFrameHeight(),
+ mVideoProfile.getBitrate(),
+ resolvedFrameRate, mVideoProfile.getFrameRate(),
+ mSurfaceSize.getWidth(), mVideoProfile.getWidth(),
+ mSurfaceSize.getHeight(), mVideoProfile.getHeight(),
videoSpecBitrateRange);
return VideoEncoderConfig.builder()
@@ -104,15 +104,15 @@
private int resolveFrameRate() {
Range<Integer> videoSpecFrameRateRange = mVideoSpec.getFrameRate();
- int camcorderProfileVideoFrameRate = mCamcorderProfile.getVideoFrameRate();
+ int videoProfileFrameRate = mVideoProfile.getFrameRate();
Logger.d(TAG,
- String.format("Frame rate from camcorder profile: %dfps. [Requested range: %s, "
- + "Expected operating range: %s]", camcorderProfileVideoFrameRate,
+ String.format("Frame rate from video profile: %dfps. [Requested range: %s, "
+ + "Expected operating range: %s]", videoProfileFrameRate,
videoSpecFrameRateRange, mExpectedFrameRateRange));
return VideoConfigUtil.resolveFrameRate(
/*preferredRange=*/ videoSpecFrameRateRange,
- /*exactFrameRateHint=*/ camcorderProfileVideoFrameRate,
+ /*exactFrameRateHint=*/ videoProfileFrameRate,
/*strictOperatingFpsRange=*/mExpectedFrameRateRange);
}
}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
index b3596b2..7d2f985 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
@@ -20,7 +20,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.core.impl.EncoderProfilesProxy;
import androidx.camera.core.impl.Timebase;
/**
@@ -32,7 +32,7 @@
public interface EncoderConfig {
/** Constant corresponding to no profile for the encoder */
- int CODEC_PROFILE_NONE = CamcorderProfileProxy.CODEC_PROFILE_NONE;
+ int CODEC_PROFILE_NONE = EncoderProfilesProxy.CODEC_PROFILE_NONE;
/**
* The mime type of the encoder.
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
index 8e7dd14..664c481 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
@@ -16,16 +16,21 @@
package androidx.camera.video
+import android.media.CamcorderProfile.QUALITY_1080P
+import android.media.CamcorderProfile.QUALITY_2160P
+import android.media.CamcorderProfile.QUALITY_480P
+import android.media.CamcorderProfile.QUALITY_720P
+import android.media.CamcorderProfile.QUALITY_HIGH
+import android.media.CamcorderProfile.QUALITY_LOW
import android.os.Build
-import androidx.camera.testing.CamcorderProfileUtil
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_1080P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_2160P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_480P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_720P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_2160P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_720P
-import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_2160P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_720P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_1080P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_2160P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_480P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_720P
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeEncoderProfilesProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertThrows
import org.junit.Test
@@ -36,10 +41,6 @@
private const val CAMERA_ID_0 = "0"
private const val CAMERA_ID_1 = "1"
-private val CAMERA_0_PROFILE_HIGH = CamcorderProfileUtil.asHighQuality(PROFILE_2160P)
-private val CAMERA_0_PROFILE_LOW = CamcorderProfileUtil.asLowQuality(PROFILE_720P)
-private val CAMERA_1_PROFILE_HIGH = CamcorderProfileUtil.asHighQuality(PROFILE_1080P)
-private val CAMERA_1_PROFILE_LOW = CamcorderProfileUtil.asLowQuality(PROFILE_480P)
@RunWith(RobolectricTestRunner::class)
@DoNotInstrument
@@ -47,22 +48,20 @@
class QualitySelectorTest {
private val cameraInfo0 = FakeCameraInfoInternal(CAMERA_ID_0).apply {
- camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
- .addProfile(
- CAMERA_0_PROFILE_HIGH,
- PROFILE_2160P,
- PROFILE_720P,
- CAMERA_0_PROFILE_LOW
- ).build()
+ encoderProfilesProvider = FakeEncoderProfilesProvider.Builder()
+ .add(QUALITY_HIGH, PROFILES_2160P)
+ .add(QUALITY_2160P, PROFILES_2160P)
+ .add(QUALITY_720P, PROFILES_720P)
+ .add(QUALITY_LOW, PROFILES_720P)
+ .build()
}
private val cameraInfo1 = FakeCameraInfoInternal(CAMERA_ID_1).apply {
- camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
- .addProfile(
- CAMERA_1_PROFILE_HIGH,
- PROFILE_1080P,
- PROFILE_480P,
- CAMERA_1_PROFILE_LOW
- ).build()
+ encoderProfilesProvider = FakeEncoderProfilesProvider.Builder()
+ .add(QUALITY_HIGH, PROFILES_1080P)
+ .add(QUALITY_1080P, PROFILES_1080P)
+ .add(QUALITY_480P, PROFILES_480P)
+ .add(QUALITY_LOW, PROFILES_480P)
+ .build()
}
@Test
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
index b77ffb6..8accf99 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
@@ -16,13 +16,18 @@
package androidx.camera.video
+import android.media.CamcorderProfile.QUALITY_2160P
+import android.media.CamcorderProfile.QUALITY_720P
+import android.media.CamcorderProfile.QUALITY_HIGH
+import android.media.CamcorderProfile.QUALITY_LOW
import android.os.Build
import android.util.Size
-import androidx.camera.testing.CamcorderProfileUtil
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_2160P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_720P
-import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
+import androidx.camera.testing.EncoderProfilesUtil
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_2160P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_720P
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeEncoderProfilesProvider
+import androidx.camera.video.internal.VideoValidatedEncoderProfilesProxy
import androidx.core.util.component1
import androidx.core.util.component2
import com.google.common.truth.Truth.assertThat
@@ -32,22 +37,21 @@
import org.robolectric.annotation.Config
import org.robolectric.annotation.internal.DoNotInstrument
-private val PROFILE_HIGH = CamcorderProfileUtil.asHighQuality(PROFILE_2160P)
-private val PROFILE_LOW = CamcorderProfileUtil.asLowQuality(PROFILE_720P)
-
@RunWith(RobolectricTestRunner::class)
@DoNotInstrument
@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
class VideoCapabilitiesTest {
private val cameraInfo = FakeCameraInfoInternal().apply {
- camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
- .addProfile(PROFILE_HIGH) // UHD (2160p) per above definition
- .addProfile(PROFILE_2160P) // UHD (2160p)
- .addProfile(PROFILE_720P) // HD (720p)
- .addProfile(PROFILE_LOW) // HD (720p) per above definition
+ encoderProfilesProvider = FakeEncoderProfilesProvider.Builder()
+ .add(QUALITY_HIGH, PROFILES_2160P) // UHD (2160p) per above definition
+ .add(QUALITY_2160P, PROFILES_2160P) // UHD (2160p)
+ .add(QUALITY_720P, PROFILES_720P) // HD (720p)
+ .add(QUALITY_LOW, PROFILES_720P) // HD (720p) per above definition
.build()
}
+ private val validatedProfiles2160p = VideoValidatedEncoderProfilesProxy.from(PROFILES_2160P)
+ private val validatedProfiles720p = VideoValidatedEncoderProfilesProxy.from(PROFILES_720P)
@Test
fun isQualitySupported() {
@@ -63,23 +67,19 @@
@Test
fun getProfile() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
- assertThat(videoCapabilities.getProfile(Quality.HIGHEST))
- .isEqualTo(PROFILE_2160P)
- assertThat(videoCapabilities.getProfile(Quality.LOWEST))
- .isEqualTo(PROFILE_720P)
- assertThat(videoCapabilities.getProfile(Quality.UHD))
- .isEqualTo(PROFILE_2160P)
- assertThat(videoCapabilities.getProfile(Quality.FHD)).isNull()
- assertThat(videoCapabilities.getProfile(Quality.HD))
- .isEqualTo(PROFILE_720P)
- assertThat(videoCapabilities.getProfile(Quality.SD)).isNull()
+ assertThat(videoCapabilities.getProfiles(Quality.HIGHEST)).isEqualTo(validatedProfiles2160p)
+ assertThat(videoCapabilities.getProfiles(Quality.LOWEST)).isEqualTo(validatedProfiles720p)
+ assertThat(videoCapabilities.getProfiles(Quality.UHD)).isEqualTo(validatedProfiles2160p)
+ assertThat(videoCapabilities.getProfiles(Quality.FHD)).isNull()
+ assertThat(videoCapabilities.getProfiles(Quality.HD)).isEqualTo(validatedProfiles720p)
+ assertThat(videoCapabilities.getProfiles(Quality.SD)).isNull()
}
@Test
fun findHighestSupportedQuality_returnsHigherQuality() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size between 720p and 2160p
- val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+ val (width720p, height720p) = EncoderProfilesUtil.RESOLUTION_720P
val inBetweenSize = Size(width720p + 10, height720p)
assertThat(videoCapabilities.findHighestSupportedQualityFor(inBetweenSize))
@@ -90,7 +90,7 @@
fun findHighestSupportedQuality_returnsHighestQuality_whenAboveHighest() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size between greater than the max quality (UHD)
- val (width2160p, height2160p) = CamcorderProfileUtil.RESOLUTION_2160P
+ val (width2160p, height2160p) = EncoderProfilesUtil.RESOLUTION_2160P
val aboveHighestSize = Size(width2160p + 10, height2160p)
assertThat(videoCapabilities.findHighestSupportedQualityFor(aboveHighestSize))
@@ -101,7 +101,7 @@
fun findHighestSupportedQuality_returnsLowestQuality_whenBelowLowest() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size below the lowest quality (HD)
- val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+ val (width720p, height720p) = EncoderProfilesUtil.RESOLUTION_720P
val belowLowestSize = Size(width720p - 10, height720p)
assertThat(videoCapabilities.findHighestSupportedQualityFor(belowLowestSize))
@@ -111,51 +111,51 @@
@Test
fun findHighestSupportedQuality_returnsExactQuality_whenExactSizeGiven() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
- val exactSize720p = CamcorderProfileUtil.RESOLUTION_720P
+ val exactSize720p = EncoderProfilesUtil.RESOLUTION_720P
assertThat(videoCapabilities.findHighestSupportedQualityFor(exactSize720p))
.isEqualTo(Quality.HD)
}
@Test
- fun findHighestSupportedCamcorderProfileFor_returnsHigherProfile() {
+ fun findHighestSupportedEncoderProfilesFor_returnsHigherProfile() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size between 720p and 2160p
- val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+ val (width720p, height720p) = EncoderProfilesUtil.RESOLUTION_720P
val inBetweenSize = Size(width720p + 10, height720p)
- assertThat(videoCapabilities.findHighestSupportedCamcorderProfileFor(inBetweenSize))
- .isEqualTo(PROFILE_2160P)
+ assertThat(videoCapabilities.findHighestSupportedEncoderProfilesFor(inBetweenSize))
+ .isEqualTo(validatedProfiles2160p)
}
@Test
- fun findHighestSupportedCamcorderProfileFor_returnsHighestProfile_whenAboveHighest() {
+ fun findHighestSupportedEncoderProfilesFor_returnsHighestProfile_whenAboveHighest() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size between greater than the max quality (UHD)
- val (width2160p, height2160p) = CamcorderProfileUtil.RESOLUTION_2160P
+ val (width2160p, height2160p) = EncoderProfilesUtil.RESOLUTION_2160P
val aboveHighestSize = Size(width2160p + 10, height2160p)
- assertThat(videoCapabilities.findHighestSupportedCamcorderProfileFor(aboveHighestSize))
- .isEqualTo(PROFILE_2160P)
+ assertThat(videoCapabilities.findHighestSupportedEncoderProfilesFor(aboveHighestSize))
+ .isEqualTo(validatedProfiles2160p)
}
@Test
- fun findHighestSupportedCamcorderProfileFor_returnsLowestProfile_whenBelowLowest() {
+ fun findHighestSupportedEncoderProfilesFor_returnsLowestProfile_whenBelowLowest() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
// Create a size below the lowest quality (HD)
- val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+ val (width720p, height720p) = EncoderProfilesUtil.RESOLUTION_720P
val belowLowestSize = Size(width720p - 10, height720p)
- assertThat(videoCapabilities.findHighestSupportedCamcorderProfileFor(belowLowestSize))
- .isEqualTo(PROFILE_720P)
+ assertThat(videoCapabilities.findHighestSupportedEncoderProfilesFor(belowLowestSize))
+ .isEqualTo(validatedProfiles720p)
}
@Test
- fun findHighestSupportedCamcorderProfileFor_returnsExactProfile_whenExactSizeGiven() {
+ fun findHighestSupportedEncoderProfilesFor_returnsExactProfile_whenExactSizeGiven() {
val videoCapabilities = VideoCapabilities.from(cameraInfo)
- val exactSize720p = CamcorderProfileUtil.RESOLUTION_720P
+ val exactSize720p = EncoderProfilesUtil.RESOLUTION_720P
- assertThat(videoCapabilities.findHighestSupportedCamcorderProfileFor(exactSize720p))
- .isEqualTo(PROFILE_720P)
+ assertThat(videoCapabilities.findHighestSupportedEncoderProfilesFor(exactSize720p))
+ .isEqualTo(validatedProfiles720p)
}
}
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
index dd46cef..d94802f 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
@@ -18,6 +18,12 @@
import android.content.Context
import android.graphics.Rect
+import android.media.CamcorderProfile.QUALITY_1080P
+import android.media.CamcorderProfile.QUALITY_2160P
+import android.media.CamcorderProfile.QUALITY_480P
+import android.media.CamcorderProfile.QUALITY_720P
+import android.media.CamcorderProfile.QUALITY_HIGH
+import android.media.CamcorderProfile.QUALITY_LOW
import android.os.Build
import android.os.Looper
import android.util.Range
@@ -26,15 +32,16 @@
import androidx.arch.core.util.Function
import androidx.camera.core.AspectRatio.RATIO_16_9
import androidx.camera.core.AspectRatio.RATIO_4_3
+import androidx.camera.core.CameraEffect
import androidx.camera.core.CameraEffect.VIDEO_CAPTURE
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraSelector.LENS_FACING_BACK
import androidx.camera.core.CameraXConfig
import androidx.camera.core.SurfaceRequest
import androidx.camera.core.UseCase
-import androidx.camera.core.impl.CamcorderProfileProxy
import androidx.camera.core.impl.CameraFactory
import androidx.camera.core.impl.CameraInfoInternal
+import androidx.camera.core.impl.EncoderProfilesProxy
import androidx.camera.core.impl.ImageFormatConstants
import androidx.camera.core.impl.ImageOutputConfig
import androidx.camera.core.impl.MutableStateObservable
@@ -47,27 +54,26 @@
import androidx.camera.core.impl.utils.executor.CameraXExecutors.directExecutor
import androidx.camera.core.impl.utils.executor.CameraXExecutors.mainThreadExecutor
import androidx.camera.core.internal.CameraUseCaseAdapter
-import androidx.camera.core.processing.SurfaceProcessorInternal
-import androidx.camera.testing.CamcorderProfileUtil
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_1080P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_2160P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_480P
-import androidx.camera.testing.CamcorderProfileUtil.PROFILE_720P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_1080P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_2160P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_480P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_720P
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_QHD
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_QVGA
-import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_VGA
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_1080P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_2160P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_480P
+import androidx.camera.testing.EncoderProfilesUtil.PROFILES_720P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_1080P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_2160P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_480P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_720P
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_QHD
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_QVGA
+import androidx.camera.testing.EncoderProfilesUtil.RESOLUTION_VGA
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraXUtil
import androidx.camera.testing.fakes.FakeAppConfig
-import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.camera.testing.fakes.FakeEncoderProfilesProvider
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessorInternal
import androidx.camera.video.Quality.FHD
import androidx.camera.video.Quality.HD
@@ -100,11 +106,11 @@
private val ANY_SIZE = Size(640, 480)
private const val CAMERA_ID_0 = "0"
-private val CAMERA_0_PROFILES = arrayOf(
- CamcorderProfileUtil.asHighQuality(PROFILE_2160P),
- PROFILE_2160P,
- PROFILE_720P,
- CamcorderProfileUtil.asLowQuality(PROFILE_720P)
+private val CAMERA_0_PROFILES = mapOf(
+ QUALITY_HIGH to PROFILES_2160P,
+ QUALITY_2160P to PROFILES_2160P,
+ QUALITY_720P to PROFILES_720P,
+ QUALITY_LOW to PROFILES_720P,
)
@RunWith(RobolectricTestRunner::class)
@@ -145,8 +151,7 @@
fun setNoCameraTransform_propagatesToCameraEdge() {
// Arrange.
setupCamera()
- val processor = createFakeSurfaceProcessor()
- val videoCapture = createVideoCapture(createVideoOutput(), processor = processor)
+ val videoCapture = createVideoCapture(createVideoOutput(), effect = createFakeEffect())
// Act: set no transform and create pipeline.
videoCapture.hasCameraTransform = false
videoCapture.bindToCamera(camera, null, null)
@@ -163,8 +168,7 @@
// Arrange.
setupCamera()
createCameraUseCaseAdapter()
- val processor = createFakeSurfaceProcessor()
- val videoCapture = createVideoCapture(createVideoOutput(), processor = processor)
+ val videoCapture = createVideoCapture(createVideoOutput(), effect = createFakeEffect())
// Act.
addAndAttachUseCases(videoCapture)
// Assert.
@@ -199,7 +203,7 @@
fun enableProcessor_sensorRotationIs0AndSetTargetRotation_sendCorrectResolution() {
testSetRotationWillSendCorrectResolution(
sensorRotation = 0,
- processor = createFakeSurfaceProcessor()
+ effect = createFakeEffect()
)
}
@@ -207,7 +211,7 @@
fun enableProcessor_sensorRotationIs90AndSetTargetRotation_sendCorrectResolution() {
testSetRotationWillSendCorrectResolution(
sensorRotation = 90,
- processor = createFakeSurfaceProcessor()
+ effect = createFakeEffect()
)
}
@@ -215,7 +219,7 @@
fun enableProcessor_sensorRotationIs180AndSetTargetRotation_sendCorrectResolution() {
testSetRotationWillSendCorrectResolution(
sensorRotation = 180,
- processor = createFakeSurfaceProcessor()
+ effect = createFakeEffect()
)
}
@@ -223,7 +227,7 @@
fun enableProcessor_sensorRotationIs270AndSetTargetRotation_sendCorrectResolution() {
testSetRotationWillSendCorrectResolution(
sensorRotation = 270,
- processor = createFakeSurfaceProcessor()
+ effect = createFakeEffect()
)
}
@@ -233,7 +237,7 @@
setupCamera()
createCameraUseCaseAdapter()
val videoCapture =
- createVideoCapture(createVideoOutput(), processor = createFakeSurfaceProcessor())
+ createVideoCapture(createVideoOutput(), effect = createFakeEffect())
addAndAttachUseCases(videoCapture)
// Act: invalidate.
videoCapture.surfaceRequest.invalidate()
@@ -247,8 +251,9 @@
// Arrange: create videoCapture.
setupCamera()
createCameraUseCaseAdapter()
- val processor = createFakeSurfaceProcessor()
- val videoCapture = createVideoCapture(createVideoOutput(), processor = processor)
+ val processor = FakeSurfaceProcessorInternal(mainThreadExecutor())
+ val effect = createFakeEffect(processor = processor)
+ val videoCapture = createVideoCapture(createVideoOutput(), effect = effect)
addAndAttachUseCases(videoCapture)
// Act: invalidate.
processor.surfaceRequest!!.invalidate()
@@ -277,7 +282,7 @@
setupCamera()
createCameraUseCaseAdapter()
val videoCapture =
- createVideoCapture(createVideoOutput(), processor = createFakeSurfaceProcessor())
+ createVideoCapture(createVideoOutput(), effect = createFakeEffect())
addAndAttachUseCases(videoCapture)
val surfaceRequest = videoCapture.surfaceRequest
detachAndRemoveUseCases(videoCapture)
@@ -291,7 +296,7 @@
private fun testSetRotationWillSendCorrectResolution(
sensorRotation: Int = 0,
- processor: SurfaceProcessorInternal? = null
+ effect: CameraEffect? = null
) {
setupCamera(sensorRotation = sensorRotation)
createCameraUseCaseAdapter()
@@ -313,7 +318,7 @@
surfaceRequestListener = { request, _ ->
surfaceRequest = request
})
- val videoCapture = createVideoCapture(videoOutput, processor = processor)
+ val videoCapture = createVideoCapture(videoOutput, effect = effect)
videoCapture.targetRotation = targetRotation
// Act.
@@ -321,7 +326,7 @@
// Assert.
val resolution = CAMERA_0_QUALITY_SIZE[quality]!!
- val expectedResolution = if (processor != null) {
+ val expectedResolution = if (effect != null) {
rotateSize(resolution, cameraInfo.getSensorRotationDegrees(targetRotation))
} else {
resolution
@@ -347,7 +352,7 @@
@Test
fun addUseCasesWithSurfaceProcessor_cameraIsUptime_requestIsUptime() {
testTimebase(
- processor = createFakeSurfaceProcessor(),
+ effect = createFakeEffect(),
cameraTimebase = Timebase.UPTIME,
expectedTimebase = Timebase.UPTIME
)
@@ -356,14 +361,14 @@
@Test
fun addUseCasesWithSurfaceProcessor_cameraIsRealtime_requestIsRealtime() {
testTimebase(
- processor = createFakeSurfaceProcessor(),
+ effect = createFakeEffect(),
cameraTimebase = Timebase.REALTIME,
expectedTimebase = Timebase.REALTIME
)
}
private fun testTimebase(
- processor: SurfaceProcessorInternal? = null,
+ effect: CameraEffect? = null,
cameraTimebase: Timebase,
expectedTimebase: Timebase
) {
@@ -375,7 +380,7 @@
val videoOutput = createVideoOutput(surfaceRequestListener = { _, tb ->
timebase = tb
})
- val videoCapture = createVideoCapture(videoOutput, processor = processor)
+ val videoCapture = createVideoCapture(videoOutput, effect = effect)
// Act.
addAndAttachUseCases(videoCapture)
@@ -433,13 +438,13 @@
fun setQualitySelector_sameCustomOrderedResolutions() {
// Arrange.
setupCamera(
- profiles = arrayOf(
- CamcorderProfileUtil.asHighQuality(PROFILE_2160P),
- PROFILE_2160P,
- PROFILE_1080P,
- PROFILE_720P,
- PROFILE_480P,
- CamcorderProfileUtil.asLowQuality(PROFILE_480P)
+ profiles = mapOf(
+ QUALITY_HIGH to PROFILES_2160P,
+ QUALITY_2160P to PROFILES_2160P,
+ QUALITY_1080P to PROFILES_1080P,
+ QUALITY_720P to PROFILES_720P,
+ QUALITY_480P to PROFILES_480P,
+ QUALITY_LOW to PROFILES_480P
)
)
createCameraUseCaseAdapter()
@@ -475,13 +480,13 @@
fun setAspectRatio_4by3() {
// Arrange.
setupCamera(
- profiles = arrayOf(
- CamcorderProfileUtil.asHighQuality(PROFILE_2160P),
- PROFILE_2160P,
- PROFILE_1080P,
- PROFILE_720P,
- PROFILE_480P,
- CamcorderProfileUtil.asLowQuality(PROFILE_480P)
+ profiles = mapOf(
+ QUALITY_HIGH to PROFILES_2160P,
+ QUALITY_2160P to PROFILES_2160P,
+ QUALITY_1080P to PROFILES_1080P,
+ QUALITY_720P to PROFILES_720P,
+ QUALITY_480P to PROFILES_480P,
+ QUALITY_LOW to PROFILES_480P
)
)
createCameraUseCaseAdapter()
@@ -515,13 +520,13 @@
fun setAspectRatio_16by9() {
// Arrange.
setupCamera(
- profiles = arrayOf(
- CamcorderProfileUtil.asHighQuality(PROFILE_2160P),
- PROFILE_2160P,
- PROFILE_1080P,
- PROFILE_720P,
- PROFILE_480P,
- CamcorderProfileUtil.asLowQuality(PROFILE_480P)
+ profiles = mapOf(
+ QUALITY_HIGH to PROFILES_2160P,
+ QUALITY_2160P to PROFILES_2160P,
+ QUALITY_1080P to PROFILES_1080P,
+ QUALITY_720P to PROFILES_720P,
+ QUALITY_480P to PROFILES_480P,
+ QUALITY_LOW to PROFILES_480P
)
)
createCameraUseCaseAdapter()
@@ -561,7 +566,7 @@
val videoOutput = createVideoOutput()
val videoCapture = createVideoCapture(
videoOutput,
- processor = createFakeSurfaceProcessor(),
+ effect = createFakeEffect(),
videoEncoderInfoFinder = {
createVideoEncoderInfo(widthAlignment = 16, heightAlignment = 16)
})
@@ -597,7 +602,7 @@
@Test
fun noSupportedQuality_supportedResolutionsIsNotSet() {
// Arrange.
- setupCamera(profiles = emptyArray())
+ setupCamera(profiles = emptyMap())
createCameraUseCaseAdapter()
val videoOutput = createVideoOutput(
@@ -764,7 +769,8 @@
appSurfaceReadyToRelease = true
}
})
- val videoCapture = createVideoCapture(videoOutput, processor = processor)
+ val effect = createFakeEffect(processor = processor)
+ val videoCapture = createVideoCapture(videoOutput, effect = effect)
// Act: bind and provide Surface.
addAndAttachUseCases(videoCapture)
@@ -898,7 +904,7 @@
)
val videoCapture = createVideoCapture(
videoOutput,
- processor = createFakeSurfaceProcessor(),
+ effect = createFakeEffect(),
videoEncoderInfoFinder = { videoEncoderInfo }
)
videoCapture.setViewPortCropRect(cropRect)
@@ -997,7 +1003,7 @@
hasCameraTransform: Boolean = true,
targetRotation: Int? = null,
targetResolution: Size? = null,
- processor: SurfaceProcessorInternal? = null,
+ effect: CameraEffect? = null,
videoEncoderInfoFinder: Function<VideoEncoderConfig, VideoEncoderInfo> =
Function { createVideoEncoderInfo() },
): VideoCapture<VideoOutput> = VideoCapture.Builder(videoOutput)
@@ -1007,11 +1013,18 @@
targetResolution?.let { setTargetResolution(it) }
setVideoEncoderInfoFinder(videoEncoderInfoFinder)
}.build().apply {
- setProcessor(processor)
+ setEffect(effect)
setHasCameraTransform(hasCameraTransform)
}
- private fun createFakeSurfaceProcessor() = FakeSurfaceProcessorInternal(mainThreadExecutor())
+ private fun createFakeEffect(
+ processor: FakeSurfaceProcessorInternal = FakeSurfaceProcessorInternal(
+ mainThreadExecutor()
+ )
+ ) =
+ FakeSurfaceEffect(
+ processor
+ )
private fun setSuggestedStreamSpec(quality: Quality) {
setSuggestedStreamSpec(StreamSpec.builder(CAMERA_0_QUALITY_SIZE[quality]!!).build())
@@ -1029,15 +1042,14 @@
cameraId: String = CAMERA_ID_0,
sensorRotation: Int = 0,
supportedResolutions: Map<Int, List<Size>> = CAMERA_0_SUPPORTED_RESOLUTION_MAP,
- vararg profiles: CamcorderProfileProxy = CAMERA_0_PROFILES,
+ profiles: Map<Int, EncoderProfilesProxy> = CAMERA_0_PROFILES,
timebase: Timebase = Timebase.UPTIME,
) {
cameraInfo = FakeCameraInfoInternal(cameraId, sensorRotation, LENS_FACING_BACK).apply {
supportedResolutions.forEach { (format, resolutions) ->
setSupportedResolutions(format, resolutions)
}
- camcorderProfileProvider =
- FakeCamcorderProfileProvider.Builder().addProfile(*profiles).build()
+ encoderProfilesProvider = FakeEncoderProfilesProvider.Builder().addAll(profiles).build()
setTimebase(timebase)
}
camera = FakeCamera(cameraId, null, cameraInfo)
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
index 9476da71e..e6266ed 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
@@ -35,7 +35,7 @@
import androidx.camera.testing.CoreAppTestUtil
import androidx.camera.testing.fakes.FakeActivity
import androidx.camera.testing.fakes.FakeLifecycleOwner
-import androidx.camera.testing.fakes.FakePreviewEffect
+import androidx.camera.testing.fakes.FakeSurfaceEffect
import androidx.camera.testing.fakes.FakeSurfaceProcessor
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
@@ -126,11 +126,11 @@
waitUtilPreviewViewIsReady(previewView!!)
// Act: set the same effect twice, which is invalid.
- val previewEffect1 = FakePreviewEffect(
+ val previewEffect1 = FakeSurfaceEffect(
mainThreadExecutor(),
FakeSurfaceProcessor(mainThreadExecutor())
)
- val previewEffect2 = FakePreviewEffect(
+ val previewEffect2 = FakeSurfaceEffect(
mainThreadExecutor(),
FakeSurfaceProcessor(mainThreadExecutor())
)
@@ -159,19 +159,19 @@
waitUtilPreviewViewIsReady(previewView!!)
// Act: set an effect
- val effect = FakePreviewEffect(
+ val effect = FakeSurfaceEffect(
mainThreadExecutor(), FakeSurfaceProcessor(mainThreadExecutor())
)
instrumentation.runOnMainSync { controller!!.setEffects(setOf(effect)) }
// Assert: preview has effect
- assertThat(controller!!.mPreview.processor).isNotNull()
+ assertThat(controller!!.mPreview.effect).isNotNull()
// Act: clear the effects
instrumentation.runOnMainSync { controller!!.setEffects(null) }
// Assert: preview no longer has the effect.
- assertThat(controller!!.mPreview.processor).isNull()
+ assertThat(controller!!.mPreview.effect).isNull()
}
@Test
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
index d41a8ce..1b89972 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
@@ -174,11 +174,6 @@
@Test
fun setZoomRatio_largerThanMax_zoomUnmodified() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
assumeTrue(2.0f <= cameraInfo.zoomState.value!!.maxZoomRatio + DELTA)
cameraControl.setZoomRatio(2.0f)[5, TimeUnit.SECONDS]
@@ -198,11 +193,6 @@
@Test
fun setZoomRatio_largerThanMax_OutOfRangeException() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
val maxZoomRatio = cameraInfo.zoomState.value!!.maxZoomRatio
val result = cameraControl.setZoomRatio(maxZoomRatio + 1.0f)
@@ -211,11 +201,6 @@
@Test
fun setZoomRatio_smallerThanMin_zoomUnmodified() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
assumeTrue(2.0f <= cameraInfo.zoomState.value!!.maxZoomRatio + DELTA)
cameraControl.setZoomRatio(2.0f)[5, TimeUnit.SECONDS]
@@ -235,11 +220,6 @@
@Test
fun setZoomRatio_smallerThanMin_OutOfRangeException() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
val minZoomRatio = cameraInfo.zoomState.value!!.minZoomRatio
val result = cameraControl.setZoomRatio(minZoomRatio - 1.0f)
@@ -278,7 +258,7 @@
@Test
fun setZoomRatioBy2_0_cropRegionIsSetCorrectly() = runBlocking {
- assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! <= 2.0f + DELTA)
+ assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! > 2.0f + DELTA)
checkTestPreconditions(isAndroidRZoom = false)
@@ -342,11 +322,6 @@
@Test
fun setLinearZoomBy0_5_isHalfCropWidth() = runBlocking {
- assumeFalse(
- "b/267665704: CameraPipe linear zoom conversion to zoom ratio is not correct",
- implName == "CameraPipeConfig"
- )
-
checkTestPreconditions(isAndroidRZoom = false)
// crop region in percentage == 0 may be null, need to use sensor rect instead.
@@ -363,11 +338,6 @@
@Test
@SdkSuppress(minSdkVersion = 30)
fun setLinearZoomBy0_5_androidRZoomRatioUpdatedCorrectly() = runBlocking {
- assumeFalse(
- "b/267665704: CameraPipe linear zoom conversion to zoom ratio is not correct",
- implName == "CameraPipeConfig"
- )
-
checkTestPreconditions(isAndroidRZoom = true)
val cropWidth = 10000f
@@ -388,11 +358,6 @@
@Test
fun setLinearZoom_cropWidthChangedLinearly() = runBlocking {
- assumeFalse(
- "b/267665704: CameraPipe linear zoom conversion to zoom ratio is not correct",
- implName == "CameraPipeConfig"
- )
-
checkTestPreconditions(isAndroidRZoom = false)
// crop region in percentage == 0 may be null, need to use sensor rect instead.
@@ -421,11 +386,6 @@
@RequiresApi(Build.VERSION_CODES.R)
@Test
fun setLinearZoom_androidRZoomRatio_cropWidthChangedLinearly() = runBlocking {
- assumeFalse(
- "b/267665704: CameraPipe linear zoom conversion to zoom ratio is not correct",
- implName == "CameraPipeConfig"
- )
-
checkTestPreconditions(isAndroidRZoom = true)
val cropWidth = 10000f
@@ -456,11 +416,6 @@
@Test
fun setLinearZoom_largerThan1_zoomUnmodified() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
cameraControl.setLinearZoom(0.5f)[5, TimeUnit.SECONDS]
/**
@@ -477,11 +432,6 @@
@Test
fun setLinearZoom_largerThan1_outOfRangeException() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
val result = cameraControl.setLinearZoom(1.1f)
assertFutureThrowsIllegalArgumentException(result)
@@ -489,11 +439,6 @@
@Test
fun setLinearZoom_smallerThan0_zoomUnmodified() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
cameraControl.setLinearZoom(0.5f)[5, TimeUnit.SECONDS]
/**
@@ -510,11 +455,6 @@
@Test
fun setLinearZoom_smallerThan0_outOfRangeException() = runBlocking {
- assumeFalse(
- "b/262225455: CameraPipe does not yet handle zoom value outside available range",
- implName == "CameraPipeConfig"
- )
-
val result = cameraControl.setLinearZoom(-0.1f)
assertFutureThrowsIllegalArgumentException(result)
@@ -527,7 +467,7 @@
@Test
fun getZoomRatioLiveData_observerIsCalledWhenZoomRatioIsSet() = runBlocking {
- assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! <= 2.0f + DELTA)
+ assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! > 2.0f + DELTA)
val latch1 = CountDownLatch(1)
val latch2 = CountDownLatch(1)
@@ -579,11 +519,6 @@
@Test
fun getZoomPercentageLiveData_observerIsCalledWhenZoomPercentageIsSet() = runBlocking {
- assumeFalse(
- "b/267665704: CameraPipe linear zoom conversion to zoom ratio is not correct",
- implName == "CameraPipeConfig"
- )
-
val latch1 = CountDownLatch(1)
val latch2 = CountDownLatch(1)
val latch3 = CountDownLatch(1)
@@ -611,7 +546,7 @@
@Test
fun getZoomPercentageLiveData_observerIsCalledWhenZoomRatioIsSet() = runBlocking {
- assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! <= 2.0f + DELTA)
+ assumeTrue(getMaxDigitalZoom() != null && getMaxDigitalZoom()!! > 2.0f + DELTA)
val latch = CountDownLatch(3)
withContext(Dispatchers.Main) {
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/CameraControlDeviceTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/CameraControlDeviceTest.kt
index 2e1cbf7..9b35256 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/CameraControlDeviceTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/CameraControlDeviceTest.kt
@@ -84,8 +84,7 @@
@Before
fun setUp() {
val context = ApplicationProvider.getApplicationContext<Context>()
- val cameraXConfig = Camera2Config.defaultConfig()
- CameraXUtil.initialize(context, cameraXConfig).get()
+ CameraXUtil.initialize(context, cameraConfig).get()
val cameraX = CameraXUtil.getOrCreateInstance(context, null).get()
Assume.assumeTrue(
CameraAvailabilityUtil.hasCamera(
@@ -202,7 +201,7 @@
private fun <T> assertFutureCompletes(future: ListenableFuture<T>) {
try {
- future[5, TimeUnit.SECONDS]
+ future[10, TimeUnit.SECONDS]
} catch (e: Exception) {
Assert.fail("future fail:$e")
}
diff --git a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
index 209122c..ea47c1f 100644
--- a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
+++ b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
@@ -18,6 +18,9 @@
import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+import static androidx.car.app.model.Action.FLAG_DEFAULT;
+import static androidx.car.app.model.Action.FLAG_PRIMARY;
+
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -40,9 +43,14 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RawRes;
+import androidx.car.app.AppManager;
import androidx.car.app.CarContext;
import androidx.car.app.CarToast;
+import androidx.car.app.model.Action;
+import androidx.car.app.model.Alert;
+import androidx.car.app.model.AlertCallback;
import androidx.car.app.model.CarIcon;
+import androidx.car.app.model.CarText;
import androidx.car.app.model.Distance;
import androidx.car.app.navigation.NavigationManager;
import androidx.car.app.navigation.NavigationManagerCallback;
@@ -59,6 +67,7 @@
import androidx.car.app.sample.navigation.common.model.Script;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
+import androidx.core.graphics.drawable.IconCompat;
import java.io.IOException;
import java.util.ArrayList;
@@ -256,6 +265,14 @@
getTrafficAccidentWarningNotification());
}
+ // Send the alert every 7-step updates. This number is
+ // randomly chosen to distinguish from the HUN experience
+ // that is triggered every 10-step updates.
+ if (++mStepsSent % 7 == 0) {
+ mCarContext.getCarService(AppManager.class)
+ .showAlert(createAlert());
+ }
+
update(
/* isNavigating= */ true,
/* isRerouting= */ false,
@@ -581,4 +598,61 @@
intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true);
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
+
+ @NonNull
+ private Alert createAlert() {
+ CarText title =
+ CarText.create(getString(R.string.navigation_alert_title));
+ CarIcon icon = new CarIcon.Builder(
+ IconCompat.createWithResource(this, R.drawable.ic_police)).build();
+
+ CarText yesTitle = CarText.create(getString(R.string.yes_action_title));
+ Action yesAction = new Action.Builder().setTitle(yesTitle).setOnClickListener(
+ () -> CarToast.makeText(
+ mCarContext,
+ getString(
+ R.string.yes_action_toast_msg),
+ CarToast.LENGTH_SHORT)
+ .show()).setFlags(FLAG_PRIMARY).build();
+
+ CarText noTitle = CarText.create(getString(R.string.no_action_title));
+ Action noAction = new Action.Builder().setTitle(noTitle).setOnClickListener(
+ () -> CarToast.makeText(
+ mCarContext,
+ getString(
+ R.string.no_action_toast_msg),
+ CarToast.LENGTH_SHORT)
+ .show()).setFlags(FLAG_DEFAULT).build();
+
+ return new Alert.Builder(/* alertId: */ 0, title, /* durationMillis: */ 10000)
+ .setIcon(icon)
+ .addAction(yesAction)
+ .addAction(noAction)
+ .setCallback(new AlertCallback() {
+ @Override
+ public void onCancel(int reason) {
+ if (reason == AlertCallback.REASON_NOT_SUPPORTED) {
+ mNotificationManager.notify(
+ NOTIFICATION_ID,
+ getPoliceReportNotification());
+ }
+ }
+
+ @Override
+ public void onDismiss() {
+ }
+ }).build();
+ }
+
+ private Notification getPoliceReportNotification() {
+ return new NotificationCompat.Builder(this, CHANNEL_ID)
+ .setContentTitle(getString(R.string.navigation_alert_title))
+ .setSmallIcon(R.drawable.ic_police)
+ .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_police))
+ .extend(
+ new CarAppExtender.Builder()
+ .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
+ .build())
+ .build();
+ }
}
diff --git a/car/app/app-samples/navigation/common/src/main/res/drawable/ic_police.xml b/car/app/app-samples/navigation/common/src/main/res/drawable/ic_police.xml
new file mode 100644
index 0000000..2ba337c2
--- /dev/null
+++ b/car/app/app-samples/navigation/common/src/main/res/drawable/ic_police.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2023 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path android:fillColor="@android:color/white" android:pathData="M18.7,30.35 L24,26.45 29.15,30.35 27,24.05 32.3,20.25H25.9L24,14L22.1,20.25H15.7L20.9,24.05ZM24,43.95Q17,42.2 12.5,35.825Q8,29.45 8,21.85V9.95L24,3.95L40,9.95V21.85Q40,29.45 35.5,35.825Q31,42.2 24,43.95ZM24,40.85Q29.75,38.95 33.375,33.675Q37,28.4 37,21.85V12.05L24,7.15L11,12.05V21.85Q11,28.4 14.625,33.675Q18.25,38.95 24,40.85ZM24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Z"/>
+</vector>
\ No newline at end of file
diff --git a/car/app/app-samples/navigation/common/src/main/res/values/strings.xml b/car/app/app-samples/navigation/common/src/main/res/values/strings.xml
index 9d27900..27a95a0 100644
--- a/car/app/app-samples/navigation/common/src/main/res/values/strings.xml
+++ b/car/app/app-samples/navigation/common/src/main/res/values/strings.xml
@@ -38,4 +38,13 @@
<string name="settings_five_pref" translatable="false">setting_five</string>
<string name="settings_six_label" translatable="false">Setting Six</string>
<string name="settings_six_pref" translatable="false">setting_six</string>
+
+ <!-- Alert card -->
+ <string name="navigation_alert_title">Is police still there?</string>
+ <string name="yes_action_title">Yes</string>
+ <string name="no_action_title">No</string>
+ <string name="yes_action_toast_msg">Yes button pressed!</string>
+ <string name="no_action_toast_msg">No button pressed!</string>
+ <string name="alert_timeout_toast_msg">Alert is timed out!</string>
+ <string name="alert_not_supported">Alert is not supported, use HUN instead</string>
</resources>
diff --git a/car/app/app/build.gradle b/car/app/app/build.gradle
index 5807cb4..74dff68 100644
--- a/car/app/app/build.gradle
+++ b/car/app/app/build.gradle
@@ -16,6 +16,7 @@
import androidx.build.LibraryType
import androidx.build.Release
+import androidx.build.checkapi.LibraryApiTaskConfig
import androidx.build.metalava.MetalavaRunnerKt
import androidx.build.uptodatedness.EnableCachingKt
import androidx.build.Version
@@ -29,6 +30,8 @@
import java.util.concurrent.TimeUnit
import javax.inject.Inject
+import static androidx.build.dependencies.DependenciesKt.*
+
buildscript {
dependencies {
// This dependency means that tasks in this project might become out-of-date whenever
@@ -314,14 +317,12 @@
@Input
String carApiLevel = project.latestCarAppApiLevel
- @OutputDirectory
- final DirectoryProperty outputDir = project.objects.directoryProperty()
+ @OutputFile
+ File apiLevelFile
@TaskAction
def exec() {
- def outputFile = new File(outputDir.get().asFile, "car-app-api.level")
- outputFile.parentFile.mkdirs()
- PrintWriter writer = new PrintWriter(outputFile)
+ PrintWriter writer = new PrintWriter(apiLevelFile)
writer.println(carApiLevel)
writer.close()
}
@@ -379,6 +380,9 @@
}
}
+def RESOURCE_DIRECTORY = "generatedResources"
+def API_LEVEL_FILE_PATH = "$RESOURCE_DIRECTORY/car-app-api.level"
+
LibraryExtension library = project.extensions.getByType(LibraryExtension.class)
def getLibraryExtension() {
@@ -409,15 +413,24 @@
return sourceCollection
}
-def writeCarApiLevelFileTask = tasks.register("writeCarApiLevelFile", ApiLevelFileWriterTask) { task ->
- task.outputDir.set(new File(project.buildDir, "generatedResources"))
-}
-
-AndroidSourceDirectorySet resources = library.sourceSets.getByName("main").resources
-resources.srcDir(writeCarApiLevelFileTask.map {it.outputDir })
-
// afterEvaluate required to read extension properties
afterEvaluate {
+ task writeCarApiLevelFile(type: ApiLevelFileWriterTask) {
+ File artifactName = new File(buildDir, API_LEVEL_FILE_PATH)
+ apiLevelFile = artifactName
+ }
+
+ AndroidSourceDirectorySet resources = library.sourceSets.getByName("main").resources
+ Set<File> resFiles = new HashSet<>()
+ resFiles.add(resources.srcDirs)
+ resFiles.add(new File(buildDir, RESOURCE_DIRECTORY))
+ resources.srcDirs(resFiles)
+ Set<String> includes = resources.includes
+ if (!includes.isEmpty()) {
+ includes.add("*.level")
+ resources.setIncludes(includes)
+ }
+
FileCollection sourceCollection = getSourceCollection()
FileCollection dependencyClasspath = getLibraryVariant().getCompileClasspath(null)
FileCollection metalavaClasspath = MetalavaRunnerKt.getMetalavaClasspath(project)
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
index 439cb47..26429f7 100644
--- a/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
@@ -143,7 +143,7 @@
return mReceivedTimeEpochMillis;
}
- /** Returns a {@link boolean}, indicating whether the message has been read */
+ /** Returns a {@code boolean}, indicating whether the message has been read */
public boolean isRead() {
return mIsRead;
}
@@ -175,7 +175,7 @@
return this;
}
- /** Sets a {@link boolean}, indicating whether the message has been read */
+ /** Sets a {@code boolean}, indicating whether the message has been read */
public @NonNull Builder setRead(boolean isRead) {
mIsRead = isRead;
return this;
diff --git a/compose/animation/animation-core-lint/src/main/java/androidx/compose/animation/core/lint/AnimationCoreIssueRegistry.kt b/compose/animation/animation-core-lint/src/main/java/androidx/compose/animation/core/lint/AnimationCoreIssueRegistry.kt
index 7dce8cf..02be66d 100644
--- a/compose/animation/animation-core-lint/src/main/java/androidx/compose/animation/core/lint/AnimationCoreIssueRegistry.kt
+++ b/compose/animation/animation-core-lint/src/main/java/androidx/compose/animation/core/lint/AnimationCoreIssueRegistry.kt
@@ -25,7 +25,7 @@
*/
class AnimationCoreIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
TransitionDetector.UnusedTransitionTargetStateParameter,
diff --git a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
index 6cff075..3884e78 100644
--- a/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
+++ b/compose/animation/animation-lint/src/main/java/androidx/compose/animation/lint/AnimationIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class AnimationIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
CrossfadeDetector.UnusedCrossfadeTargetStateParameter
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/SizeTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/SizeTest.kt
index 2e337c7..dc3c333 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/SizeTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/SizeTest.kt
@@ -58,6 +58,7 @@
import org.junit.runner.RunWith
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
import org.junit.Assert.assertNotEquals
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -1486,6 +1487,7 @@
assertEquals(Offset(root.width - size.toFloat(), 0f), childPosition.value)
}
+ @SdkSuppress(maxSdkVersion = 32) // b/267699626
@Test
fun testWrapContentSize_rtl() = with(density) {
val sizeDp = 200.toDp()
diff --git a/compose/foundation/foundation-lint/src/main/java/androidx/compose/foundation/lint/FoundationIssueRegistry.kt b/compose/foundation/foundation-lint/src/main/java/androidx/compose/foundation/lint/FoundationIssueRegistry.kt
index 9d622a1..ef9e339 100644
--- a/compose/foundation/foundation-lint/src/main/java/androidx/compose/foundation/lint/FoundationIssueRegistry.kt
+++ b/compose/foundation/foundation-lint/src/main/java/androidx/compose/foundation/lint/FoundationIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class FoundationIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
LazyLayoutStateReadInCompositionDetector.FrequentlyChangedStateReadInComposition,
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableTest.kt
index 2345c6e..7f51f44 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableTest.kt
@@ -102,6 +102,7 @@
import androidx.test.espresso.action.Swipe
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlin.math.abs
@@ -2341,6 +2342,7 @@
}
}
+ @SdkSuppress(maxSdkVersion = 32) // b/268753157
@Test
fun offsetsScrollable_velocityCalculationShouldConsiderLocalPositions() {
// arrange
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
index 7784e47..0a5cc61 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
@@ -2000,6 +2000,7 @@
.assertStartPositionInRootIsEqualTo(0.dp)
}
+ @SdkSuppress(maxSdkVersion = 32) // b/269178188
@Test
fun assertVelocityCalculationIsSimilar_witHistoricalValues() {
// arrange
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
index 425ef13..ff4a3e3 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
@@ -35,6 +35,7 @@
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import kotlin.math.absoluteValue
import kotlinx.coroutines.runBlocking
@@ -49,6 +50,7 @@
config: ParamConfig
) : BasePagerTest(config = config) {
+ @SdkSuppress(maxSdkVersion = 32) // b/269171814
@OptIn(ExperimentalFoundationApi::class)
@Test
fun nestedScrollContent_shouldNotPropagateUnconsumedFlings() {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
index 27a097a..8aa3c7a 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
@@ -31,6 +31,7 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertFalse
import kotlinx.coroutines.Dispatchers
@@ -85,6 +86,7 @@
}
}
+ @SdkSuppress(maxSdkVersion = 32) // b/269176638
@Test
fun scrollToPage_usedOffset_shouldPlacePagesCorrectly() = runBlocking {
// Arrange
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
index dbdf686..bde8eb6 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
@@ -77,8 +77,7 @@
) {
val overscrollEffect = ScrollableDefaults.overscrollEffect()
val itemProvider = rememberLazyListItemProvider(state, content)
- val semanticState =
- rememberLazyListSemanticState(state, itemProvider, reverseLayout, isVertical)
+ val semanticState = rememberLazyListSemanticState(state, isVertical)
val beyondBoundsInfo = remember { LazyListBeyondBoundsInfo() }
val scope = rememberCoroutineScope()
val placementAnimator = remember(state, isVertical) {
@@ -112,7 +111,8 @@
itemProvider = itemProvider,
state = semanticState,
orientation = orientation,
- userScrollEnabled = userScrollEnabled
+ userScrollEnabled = userScrollEnabled,
+ reverseScrolling = reverseLayout
)
.clipScrollableContainer(orientation)
.lazyListBeyondBoundsModifier(state, beyondBoundsInfo, reverseLayout, orientation)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt
new file mode 100644
index 0000000..d84e816
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListBeyondBoundsModifier.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2022 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.compose.foundation.lazy
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.lazy.layout.BeyondBoundsState
+import androidx.compose.foundation.lazy.layout.LazyLayoutBeyondBoundsModifierLocal
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalLayoutDirection
+
+/**
+ * This modifier is used to measure and place additional items when the lazyList receives a
+ * request to layout items beyond the visible bounds.
+ */
+@Suppress("ComposableModifierFactory")
+@Composable
+internal fun Modifier.lazyListBeyondBoundsModifier(
+ state: LazyListState,
+ beyondBoundsInfo: LazyListBeyondBoundsInfo,
+ reverseLayout: Boolean,
+ orientation: Orientation
+): Modifier {
+ val layoutDirection = LocalLayoutDirection.current
+ val beyondBoundsState = remember(state) { LazyListBeyondBoundsState(state) }
+ return this then remember(
+ beyondBoundsState,
+ beyondBoundsInfo,
+ reverseLayout,
+ layoutDirection,
+ orientation
+ ) {
+ LazyLayoutBeyondBoundsModifierLocal(
+ beyondBoundsState,
+ beyondBoundsInfo,
+ reverseLayout,
+ layoutDirection,
+ orientation
+ )
+ }
+}
+
+internal class LazyListBeyondBoundsState(val state: LazyListState) : BeyondBoundsState {
+ override fun remeasure() {
+ state.remeasurement?.forceRemeasure()
+ }
+
+ override val itemCount: Int
+ get() = state.layoutInfo.totalItemsCount
+ override val hasVisibleItems: Boolean
+ get() = state.layoutInfo.visibleItemsInfo.isNotEmpty()
+ override val firstVisibleIndex: Int
+ get() = state.firstVisibleItemIndex
+ override val lastVisibleIndex: Int
+ get() = state.layoutInfo.visibleItemsInfo.last().index
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListSemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListSemantics.kt
new file mode 100644
index 0000000..5864b07
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListSemantics.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.compose.foundation.lazy
+
+import androidx.compose.foundation.lazy.layout.LazyLayoutSemanticState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+
+@Composable
+internal fun rememberLazyListSemanticState(
+ state: LazyListState,
+ isVertical: Boolean
+): LazyLayoutSemanticState {
+ return remember(state, isVertical) {
+ LazyLayoutSemanticState(state = state, isVertical = isVertical)
+ }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt
deleted file mode 100644
index 96bccd6..0000000
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.compose.foundation.lazy
-
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.gestures.animateScrollBy
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
-import androidx.compose.foundation.lazy.layout.LazyLayoutSemanticState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.ui.semantics.CollectionInfo
-import androidx.compose.ui.semantics.ScrollAxisRange
-
-@OptIn(ExperimentalFoundationApi::class)
-@Composable
-internal fun rememberLazyListSemanticState(
- state: LazyListState,
- itemProvider: LazyLayoutItemProvider,
- reverseScrolling: Boolean,
- isVertical: Boolean
-): LazyLayoutSemanticState =
- remember(state, itemProvider, reverseScrolling, isVertical) {
- object : LazyLayoutSemanticState {
- override fun scrollAxisRange(): ScrollAxisRange =
- ScrollAxisRange(
- value = {
- // This is a simple way of representing the current position without
- // needing any lazy items to be measured. It's good enough so far, because
- // screen-readers care mostly about whether scroll position changed or not
- // rather than the actual offset in pixels.
- state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
- },
- maxValue = {
- if (state.canScrollForward) {
- // If we can scroll further, we don't know the end yet,
- // but it's upper bounded by #items + 1
- itemProvider.itemCount + 1f
- } else {
- // If we can't scroll further, the current value is the max
- state.firstVisibleItemIndex +
- state.firstVisibleItemScrollOffset / 100_000f
- }
- },
- reverseScrolling = reverseScrolling
- )
-
- override suspend fun animateScrollBy(delta: Float) {
- state.animateScrollBy(delta)
- }
-
- override suspend fun scrollToItem(index: Int) {
- state.scrollToItem(index)
- }
-
- override fun collectionInfo(): CollectionInfo =
- if (isVertical) {
- CollectionInfo(rowCount = -1, columnCount = 1)
- } else {
- CollectionInfo(rowCount = 1, columnCount = -1)
- }
- }
- }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
index b6787df..502161e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGrid.kt
@@ -77,7 +77,7 @@
val itemProvider = rememberLazyGridItemProvider(state, content)
- val semanticState = rememberLazyGridSemanticState(state, itemProvider, reverseLayout)
+ val semanticState = rememberLazyGridSemanticState(state, reverseLayout)
val scope = rememberCoroutineScope()
val placementAnimator = remember(state, isVertical) {
@@ -110,7 +110,8 @@
itemProvider = itemProvider,
state = semanticState,
orientation = orientation,
- userScrollEnabled = userScrollEnabled
+ userScrollEnabled = userScrollEnabled,
+ reverseScrolling = reverseLayout
)
.clipScrollableContainer(orientation)
.overscroll(overscrollEffect)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazySemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazySemantics.kt
index 2e6d308..1f9c542 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazySemantics.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazySemantics.kt
@@ -18,45 +18,23 @@
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.animateScrollBy
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
import androidx.compose.foundation.lazy.layout.LazyLayoutSemanticState
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.semantics.CollectionInfo
-import androidx.compose.ui.semantics.ScrollAxisRange
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun rememberLazyGridSemanticState(
state: LazyGridState,
- itemProvider: LazyLayoutItemProvider,
reverseScrolling: Boolean
): LazyLayoutSemanticState =
- remember(state, itemProvider, reverseScrolling) {
+ remember(state, reverseScrolling) {
object : LazyLayoutSemanticState {
- override fun scrollAxisRange(): ScrollAxisRange =
- ScrollAxisRange(
- value = {
- // This is a simple way of representing the current position without
- // needing any lazy items to be measured. It's good enough so far, because
- // screen-readers care mostly about whether scroll position changed or not
- // rather than the actual offset in pixels.
- state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
- },
- maxValue = {
- if (state.canScrollForward) {
- // If we can scroll further, we don't know the end yet,
- // but it's upper bounded by #items + 1
- itemProvider.itemCount + 1f
- } else {
- // If we can't scroll further, the current value is the max
- state.firstVisibleItemIndex +
- state.firstVisibleItemScrollOffset / 100_000f
- }
- },
- reverseScrolling = reverseScrolling
- )
+ override val currentPosition: Float
+ get() = state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
+ override val canScrollForward: Boolean
+ get() = state.canScrollForward
override suspend fun animateScrollBy(delta: Float) {
state.animateScrollBy(delta)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/BeyondBoundsState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/BeyondBoundsState.kt
new file mode 100644
index 0000000..3407f2c
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/BeyondBoundsState.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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.compose.foundation.lazy.layout
+
+internal interface BeyondBoundsState {
+
+ fun remeasure()
+
+ val itemCount: Int
+
+ val hasVisibleItems: Boolean
+
+ val firstVisibleIndex: Int
+
+ val lastVisibleIndex: Int
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyBeyondBoundsModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
similarity index 79%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyBeyondBoundsModifier.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
index df49b4e..939fe3e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyBeyondBoundsModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsModifierLocal.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 The Android Open Source Project
+ * Copyright 2023 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.
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.layout
import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.lazy.LazyListBeyondBoundsInfo
import androidx.compose.foundation.lazy.LazyListBeyondBoundsInfo.Interval
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.BeyondBoundsLayout
import androidx.compose.ui.layout.BeyondBoundsLayout.BeyondBoundsScope
import androidx.compose.ui.layout.BeyondBoundsLayout.LayoutDirection.Companion.Above
@@ -32,43 +30,12 @@
import androidx.compose.ui.layout.ModifierLocalBeyondBoundsLayout
import androidx.compose.ui.modifier.ModifierLocalProvider
import androidx.compose.ui.modifier.ProvidableModifierLocal
-import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.LayoutDirection.Ltr
import androidx.compose.ui.unit.LayoutDirection.Rtl
-/**
- * This modifier is used to measure and place additional items when the lazyList receives a
- * request to layout items beyond the visible bounds.
- */
-@Suppress("ComposableModifierFactory")
-@Composable
-internal fun Modifier.lazyListBeyondBoundsModifier(
- state: LazyListState,
- beyondBoundsInfo: LazyListBeyondBoundsInfo,
- reverseLayout: Boolean,
- orientation: Orientation
-): Modifier {
- val layoutDirection = LocalLayoutDirection.current
- return this then remember(
- state,
- beyondBoundsInfo,
- reverseLayout,
- layoutDirection,
- orientation
- ) {
- LazyListBeyondBoundsModifierLocal(
- state,
- beyondBoundsInfo,
- reverseLayout,
- layoutDirection,
- orientation
- )
- }
-}
-
-private class LazyListBeyondBoundsModifierLocal(
- private val state: LazyListState,
+internal class LazyLayoutBeyondBoundsModifierLocal(
+ private val state: BeyondBoundsState,
private val beyondBoundsInfo: LazyListBeyondBoundsInfo,
private val reverseLayout: Boolean,
private val layoutDirection: LayoutDirection,
@@ -90,14 +57,14 @@
): T? {
// If the lazy list is empty, or if it does not have any visible items (Which implies
// that there isn't space to add a single item), we don't attempt to layout any more items.
- if (state.layoutInfo.totalItemsCount <= 0 || state.layoutInfo.visibleItemsInfo.isEmpty()) {
+ if (state.itemCount <= 0 || !state.hasVisibleItems) {
return block.invoke(emptyBeyondBoundsScope)
}
// We use a new interval each time because this function is re-entrant.
var interval = beyondBoundsInfo.addInterval(
- state.firstVisibleItemIndex,
- state.layoutInfo.visibleItemsInfo.last().index
+ state.firstVisibleIndex,
+ state.lastVisibleIndex
)
var found: T? = null
@@ -107,7 +74,7 @@
interval = addNextInterval(interval, direction).also {
beyondBoundsInfo.removeInterval(interval)
}
- state.remeasurement?.forceRemeasure()
+ state.remeasure()
// When we invoke this block, the beyond bounds items are present.
found = block.invoke(
@@ -120,7 +87,7 @@
// Dispose the items that are beyond the visible bounds.
beyondBoundsInfo.removeInterval(interval)
- state.remeasurement?.forceRemeasure()
+ state.remeasure()
return found
}
@@ -150,7 +117,7 @@
private fun Interval.hasMoreContent(direction: BeyondBoundsLayout.LayoutDirection): Boolean {
fun hasMoreItemsBefore() = start > 0
- fun hasMoreItemsAfter() = end < state.layoutInfo.totalItemsCount - 1
+ fun hasMoreItemsAfter() = end < state.itemCount - 1
if (direction.isOppositeToOrientation()) return false
return when (direction) {
Before -> hasMoreItemsBefore()
@@ -181,4 +148,4 @@
private fun unsupportedDirection(): Nothing = error(
"Lazy list does not support beyond bounds layout for the specified direction"
-)
+)
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemanticState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemanticState.kt
new file mode 100644
index 0000000..c4e0403
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemanticState.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 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.compose.foundation.lazy.layout
+
+import androidx.compose.foundation.gestures.animateScrollBy
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.ui.semantics.CollectionInfo
+
+internal fun LazyLayoutSemanticState(
+ state: LazyListState,
+ isVertical: Boolean
+): LazyLayoutSemanticState = object : LazyLayoutSemanticState {
+
+ override val currentPosition: Float
+ get() = state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
+ override val canScrollForward: Boolean
+ get() = state.canScrollForward
+
+ override suspend fun animateScrollBy(delta: Float) {
+ state.animateScrollBy(delta)
+ }
+
+ override suspend fun scrollToItem(index: Int) {
+ state.scrollToItem(index)
+ }
+
+ override fun collectionInfo(): CollectionInfo =
+ if (isVertical) {
+ CollectionInfo(rowCount = -1, columnCount = 1)
+ } else {
+ CollectionInfo(rowCount = 1, columnCount = -1)
+ }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
index c5e286b..1e56270 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutSemantics.kt
@@ -41,7 +41,8 @@
itemProvider: LazyLayoutItemProvider,
state: LazyLayoutSemanticState,
orientation: Orientation,
- userScrollEnabled: Boolean
+ userScrollEnabled: Boolean,
+ reverseScrolling: Boolean
): Modifier {
val coroutineScope = rememberCoroutineScope()
return this.then(
@@ -63,7 +64,26 @@
result
}
- val accessibilityScrollState = state.scrollAxisRange()
+ val accessibilityScrollState = ScrollAxisRange(
+ value = {
+ // This is a simple way of representing the current position without
+ // needing any lazy items to be measured. It's good enough so far, because
+ // screen-readers care mostly about whether scroll position changed or not
+ // rather than the actual offset in pixels.
+ state.currentPosition
+ },
+ maxValue = {
+ if (state.canScrollForward) {
+ // If we can scroll further, we don't know the end yet,
+ // but it's upper bounded by #items + 1
+ itemProvider.itemCount + 1f
+ } else {
+ // If we can't scroll further, the current value is the max
+ state.currentPosition
+ }
+ },
+ reverseScrolling = reverseScrolling
+ )
val scrollByAction: ((x: Float, y: Float) -> Boolean)? = if (userScrollEnabled) {
{ x, y ->
@@ -123,7 +143,8 @@
}
internal interface LazyLayoutSemanticState {
- fun scrollAxisRange(): ScrollAxisRange
+ val currentPosition: Float
+ val canScrollForward: Boolean
fun collectionInfo(): CollectionInfo
suspend fun animateScrollBy(delta: Float)
suspend fun scrollToItem(index: Int)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGrid.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGrid.kt
index 2630e7d..9525489 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGrid.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGrid.kt
@@ -74,7 +74,7 @@
horizontalArrangement,
slotSizesSums
)
- val semanticState = rememberLazyStaggeredGridSemanticState(state, itemProvider, reverseLayout)
+ val semanticState = rememberLazyStaggeredGridSemanticState(state, reverseLayout)
ScrollPositionUpdater(itemProvider, state)
@@ -100,7 +100,8 @@
itemProvider = itemProvider,
state = semanticState,
orientation = orientation,
- userScrollEnabled = userScrollEnabled
+ userScrollEnabled = userScrollEnabled,
+ reverseScrolling = reverseLayout
),
prefetchState = state.prefetchState,
itemProvider = itemProvider,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridSemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridSemantics.kt
index e9b7ca7..459702f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridSemantics.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridSemantics.kt
@@ -18,44 +18,23 @@
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.animateScrollBy
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
import androidx.compose.foundation.lazy.layout.LazyLayoutSemanticState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.semantics.CollectionInfo
-import androidx.compose.ui.semantics.ScrollAxisRange
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun rememberLazyStaggeredGridSemanticState(
state: LazyStaggeredGridState,
- itemProvider: LazyLayoutItemProvider,
reverseScrolling: Boolean
): LazyLayoutSemanticState =
- remember(state, itemProvider, reverseScrolling) {
+ remember(state, reverseScrolling) {
object : LazyLayoutSemanticState {
- override fun scrollAxisRange(): ScrollAxisRange =
- ScrollAxisRange(
- value = {
- // This is a simple way of representing the current position without
- // needing any lazy items to be measured. It's good enough so far, because
- // screen-readers care mostly about whether scroll position changed or not
- // rather than the actual offset in pixels.
- state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
- },
- maxValue = {
- if (state.canScrollForward) {
- // If we can scroll further, we don't know the end yet,
- // but it's upper bounded by #items + 1
- itemProvider.itemCount + 1f
- } else {
- // If we can't scroll further, the current value is the max
- state.firstVisibleItemIndex +
- state.firstVisibleItemScrollOffset / 100_000f
- }
- },
- reverseScrolling = reverseScrolling
- )
+ override val currentPosition: Float
+ get() = state.firstVisibleItemIndex + state.firstVisibleItemScrollOffset / 100_000f
+ override val canScrollForward: Boolean
+ get() = state.canScrollForward
override suspend fun animateScrollBy(delta: Float) {
state.animateScrollBy(delta)
diff --git a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
index 29098a8..6dd41f2 100644
--- a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
+++ b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
@@ -25,7 +25,7 @@
class ComposeIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues get(): List<Issue> {
return listOf(
ListIteratorDetector.ISSUE,
diff --git a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
index f7b3b43..75ce926 100644
--- a/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
+++ b/compose/material/material-lint/src/main/java/androidx/compose/material/lint/MaterialIssueRegistry.kt
@@ -25,7 +25,7 @@
*/
class MaterialIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ColorsDetector.ConflictingOnColor,
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SnackbarHostTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SnackbarHostTest.kt
index 3c60de2..cc683a3 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SnackbarHostTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SnackbarHostTest.kt
@@ -107,7 +107,7 @@
}
}
- rule.waitUntil { parent.children.all { it.isCompleted } }
+ rule.waitUntil(timeoutMillis = 5_000) { parent.children.all { it.isCompleted } }
Truth.assertThat(resultedInvocation).isEqualTo("0123456789")
}
@@ -139,7 +139,8 @@
Truth.assertThat(result).isEqualTo(SnackbarResult.Dismissed)
}
- rule.waitUntil(timeoutMillis = 7_000) { job2.isCompleted }
+ rule.mainClock.advanceTimeBy(5_000)
+ rule.waitUntil { job2.isCompleted }
}
@Test
diff --git a/compose/material3/material3-lint/src/main/java/androidx/compose/material3/lint/Material3IssueRegistry.kt b/compose/material3/material3-lint/src/main/java/androidx/compose/material3/lint/Material3IssueRegistry.kt
index 6887bda..8529446 100644
--- a/compose/material3/material3-lint/src/main/java/androidx/compose/material3/lint/Material3IssueRegistry.kt
+++ b/compose/material3/material3-lint/src/main/java/androidx/compose/material3/lint/Material3IssueRegistry.kt
@@ -25,7 +25,7 @@
*/
class Material3IssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ScaffoldPaddingDetector.UnusedMaterial3ScaffoldPaddingParameter
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index e1b2628..22b8041 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -340,7 +340,7 @@
}
public final class DateRangePickerKt {
- method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DateRangePicker(androidx.compose.material3.DateRangePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DatePickerFormatter dateFormatter, optional kotlin.jvm.functions.Function1<? super java.lang.Long,java.lang.Boolean> dateValidator, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit> headline, optional androidx.compose.material3.DatePickerColors colors);
+ method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DateRangePicker(androidx.compose.material3.DateRangePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DatePickerFormatter dateFormatter, optional kotlin.jvm.functions.Function1<? super java.lang.Long,java.lang.Boolean> dateValidator, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit> headline, optional boolean showModeToggle, optional androidx.compose.material3.DatePickerColors colors);
method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.DateRangePickerState rememberDateRangePickerState(optional Long? initialSelectedStartDateMillis, optional Long? initialSelectedEndDateMillis, optional Long? initialDisplayedMonthMillis, optional kotlin.ranges.IntRange yearRange, optional int initialDisplayMode);
}
diff --git a/compose/material3/material3/samples/build.gradle b/compose/material3/material3/samples/build.gradle
index ae744c3..b2707cf 100644
--- a/compose/material3/material3/samples/build.gradle
+++ b/compose/material3/material3/samples/build.gradle
@@ -41,8 +41,6 @@
implementation("androidx.compose.ui:ui-text:1.2.1")
implementation("androidx.savedstate:savedstate-ktx:1.2.0")
implementation(project(":compose:ui:ui-tooling-preview"))
- implementation(project(":lifecycle:lifecycle-runtime-ktx"))
- implementation(project(":lifecycle:lifecycle-common-java8"))
debugImplementation(project(":compose:ui:ui-tooling"))
}
@@ -57,3 +55,11 @@
android {
namespace "androidx.compose.material3.samples"
}
+
+// Workaround for https://github.com/gradle/gradle/issues/19882
+configurations.all {
+ resolutionStrategy.dependencySubstitution {
+ substitute(module("androidx.lifecycle:lifecycle-common-java8:")).
+ using project(":lifecycle:lifecycle-common-java8")
+ }
+}
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DatePickerSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DatePickerSamples.kt
index 66f3939..3888e13 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DatePickerSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DatePickerSamples.kt
@@ -30,7 +30,6 @@
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DateRangePicker
import androidx.compose.material3.DisplayMode
-import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHost
@@ -48,6 +47,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.zIndex
import java.time.DayOfWeek
import java.time.Instant
import java.time.ZoneId
@@ -166,7 +166,11 @@
@Sampled
@Composable
fun DateRangePickerSample() {
- val savedRange = remember { mutableStateOf(LongRange.EMPTY) }
+ // Decoupled snackbar host state from scaffold state for demo purposes.
+ val snackState = remember { SnackbarHostState() }
+ val snackScope = rememberCoroutineScope()
+ SnackbarHost(hostState = snackState, Modifier.zIndex(1f))
+
val state = rememberDateRangePickerState()
Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Top) {
// Add a row with "Save" and dismiss actions.
@@ -182,8 +186,12 @@
}
TextButton(
onClick = {
- savedRange.value =
- state.selectedStartDateMillis!!..state.selectedEndDateMillis!!
+ snackScope.launch {
+ snackState.showSnackbar(
+ "Saved range (timestamps): " +
+ "${state.selectedStartDateMillis!!..state.selectedEndDateMillis!!}"
+ )
+ }
},
enabled = state.selectedEndDateMillis != null
) {
@@ -192,8 +200,5 @@
}
DateRangePicker(state = state, modifier = Modifier.weight(1f))
-
- Divider()
- Text("Saved range of timestamps: ${savedRange.value}")
}
}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
index 27760ff..0d32838 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
@@ -355,7 +355,7 @@
stateData.calendarModel.getCanonicalDate(1649721600000L) // 04/12/2022
val displayedMonth = stateData.calendarModel.getMonth(date)
rule.runOnIdle {
- stateData.selectedStartDate = date
+ stateData.selectedStartDate.value = date
stateData.displayedMonth = displayedMonth
}
@@ -364,7 +364,7 @@
restorationTester.emulateSavedInstanceStateRestore()
rule.runOnIdle {
- assertThat(stateData.selectedStartDate).isEqualTo(date)
+ assertThat(stateData.selectedStartDate.value).isEqualTo(date)
assertThat(stateData.displayedMonth).isEqualTo(displayedMonth)
assertThat(datePickerState!!.selectedDateMillis).isEqualTo(1649721600000L)
}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputScreenshotTest.kt
new file mode 100644
index 0000000..fc637de
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputScreenshotTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2023 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.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import java.time.LocalDate
+import java.time.LocalTime
+import java.time.ZoneId
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@LargeTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@OptIn(ExperimentalMaterial3Api::class)
+class DateRangeInputScreenshotTest(private val scheme: ColorSchemeWrapper) {
+
+ @get:Rule
+ val rule = createComposeRule()
+
+ @get:Rule
+ val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
+
+ private val wrap = Modifier.wrapContentSize(Alignment.Center)
+ private val wrapperTestTag = "dateRangeInputWrapper"
+
+ @Test
+ fun dateRangeInput_initialState() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ Box(wrap.testTag(wrapperTestTag)) {
+ DateRangePicker(
+ state = rememberDateRangePickerState(initialDisplayMode = DisplayMode.Input),
+ showModeToggle = false
+ )
+ }
+ }
+ assertAgainstGolden("dateRangeInput_initialState_${scheme.name}")
+ }
+
+ @Test
+ fun dateRangeInput_withModeToggle() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ Box(wrap.testTag(wrapperTestTag)) {
+ DateRangePicker(
+ state = rememberDateRangePickerState(initialDisplayMode = DisplayMode.Input)
+ )
+ }
+ }
+ assertAgainstGolden("dateRangeInput_withModeToggle_${scheme.name}")
+ }
+
+ @Test
+ fun dateRangeInput_withEnteredDates() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ Box(wrap.testTag(wrapperTestTag)) {
+ val startDayMillis = dayInUtcMilliseconds(year = 2021, month = 3, dayOfMonth = 6)
+ val endDayMillis = dayInUtcMilliseconds(year = 2022, month = 1, dayOfMonth = 10)
+ DateRangePicker(
+ state = rememberDateRangePickerState(
+ initialSelectedStartDateMillis = startDayMillis,
+ initialSelectedEndDateMillis = endDayMillis,
+ initialDisplayMode = DisplayMode.Input
+ ),
+ showModeToggle = false
+ )
+ }
+ }
+ assertAgainstGolden("dateRangeInput_withEnteredDates_${scheme.name}")
+ }
+
+ // Returns the given date's day as milliseconds from epoch. The returned value is for the day's
+ // start on midnight.
+ private fun dayInUtcMilliseconds(year: Int, month: Int, dayOfMonth: Int): Long =
+ LocalDate.of(year, month, dayOfMonth)
+ .atTime(LocalTime.MIDNIGHT)
+ .atZone(ZoneId.of("UTC"))
+ .toInstant()
+ .toEpochMilli()
+
+ private fun assertAgainstGolden(goldenName: String) {
+ rule.onNodeWithTag(wrapperTestTag)
+ .captureToImage()
+ .assertAgainstGolden(screenshotRule, goldenName)
+ }
+
+ // Provide the ColorScheme and their name parameter in a ColorSchemeWrapper.
+ // This makes sure that the default method name and the initial Scuba image generated
+ // name is as expected.
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun parameters() = arrayOf(
+ ColorSchemeWrapper("lightTheme", lightColorScheme()),
+ ColorSchemeWrapper("darkTheme", darkColorScheme()),
+ )
+ }
+
+ class ColorSchemeWrapper(val name: String, val colorScheme: ColorScheme) {
+ override fun toString(): String {
+ return name
+ }
+ }
+}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt
new file mode 100644
index 0000000..aa623b5
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2023 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.compose.material3
+
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher.Companion.expectValue
+import androidx.compose.ui.test.SemanticsMatcher.Companion.keyIsDefined
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onAllNodesWithText
+import androidx.compose.ui.test.onFirst
+import androidx.compose.ui.test.onLast
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextInput
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import java.util.Calendar
+import java.util.Locale
+import java.util.TimeZone
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterial3Api::class)
+class DateRangeInputTest {
+
+ @get:Rule
+ val rule = createComposeRule()
+
+ @Test
+ fun dateRangeInput() {
+ lateinit var dateRangeInputLabel: String
+ lateinit var state: DateRangePickerState
+ lateinit var pickerStartDateHeadline: String
+ lateinit var pickerEndDateHeadline: String
+ rule.setMaterialContent(lightColorScheme()) {
+ pickerStartDateHeadline = getString(string = Strings.DateRangePickerStartHeadline)
+ pickerEndDateHeadline = getString(string = Strings.DateRangePickerEndHeadline)
+ dateRangeInputLabel = getString(string = Strings.DateInputLabel)
+ val monthInUtcMillis = dayInUtcMilliseconds(year = 2019, month = 1, dayOfMonth = 1)
+ state = rememberDateRangePickerState(
+ initialDisplayedMonthMillis = monthInUtcMillis,
+ initialDisplayMode = DisplayMode.Input
+ )
+ DateRangePicker(state = state)
+ }
+
+ rule.onNodeWithText(pickerStartDateHeadline, useUnmergedTree = true).assertExists()
+ rule.onNodeWithText(pickerEndDateHeadline, useUnmergedTree = true).assertExists()
+
+ // Enter dates.
+ rule.onAllNodesWithText(dateRangeInputLabel).onFirst().performClick()
+ .performTextInput("01272019")
+ rule.onAllNodesWithText(dateRangeInputLabel).onLast().performClick()
+ .performTextInput("05102020")
+
+ rule.runOnIdle {
+ assertThat(state.selectedStartDateMillis).isEqualTo(
+ dayInUtcMilliseconds(
+ year = 2019,
+ month = 1,
+ dayOfMonth = 27
+ )
+ )
+ assertThat(state.selectedEndDateMillis).isEqualTo(
+ dayInUtcMilliseconds(
+ year = 2020,
+ month = 5,
+ dayOfMonth = 10
+ )
+ )
+ }
+
+ rule.onNodeWithText(pickerStartDateHeadline, useUnmergedTree = true).assertDoesNotExist()
+ rule.onNodeWithText(pickerEndDateHeadline, useUnmergedTree = true).assertDoesNotExist()
+ rule.onNodeWithText("Jan 27, 2019", useUnmergedTree = true).assertExists()
+ rule.onNodeWithText("May 10, 2020", useUnmergedTree = true).assertExists()
+ }
+
+ @Test
+ fun dateRangeInputWithInitialDates() {
+ lateinit var state: DateRangePickerState
+ rule.setMaterialContent(lightColorScheme()) {
+ val initialStartDateMillis =
+ dayInUtcMilliseconds(year = 2010, month = 5, dayOfMonth = 11)
+ val initialEndDateMillis =
+ dayInUtcMilliseconds(year = 2020, month = 10, dayOfMonth = 20)
+ state = rememberDateRangePickerState(
+ initialSelectedStartDateMillis = initialStartDateMillis,
+ initialSelectedEndDateMillis = initialEndDateMillis,
+ initialDisplayMode = DisplayMode.Input
+ )
+ DateRangePicker(state = state)
+ }
+
+ rule.onNodeWithText("05/11/2010").assertExists()
+ rule.onNodeWithText("10/20/2020").assertExists()
+ rule.onNodeWithText("May 11, 2010", useUnmergedTree = true).assertExists()
+ rule.onNodeWithText("Oct 20, 2020", useUnmergedTree = true).assertExists()
+ }
+
+ @Test
+ fun inputDateNotAllowed() {
+ lateinit var dateRangeInputLabel: String
+ lateinit var errorMessage: String
+ lateinit var state: DateRangePickerState
+ rule.setMaterialContent(lightColorScheme()) {
+ dateRangeInputLabel = getString(string = Strings.DateInputLabel)
+ errorMessage = getString(string = Strings.DateInputInvalidNotAllowed)
+ state = rememberDateRangePickerState(initialDisplayMode = DisplayMode.Input)
+ DateRangePicker(state = state,
+ // All dates are invalid for the sake of this test.
+ dateValidator = { false }
+ )
+ }
+
+ // Enter dates.
+ rule.onAllNodesWithText(dateRangeInputLabel).onFirst().performClick()
+ .performTextInput("01272019")
+ rule.onAllNodesWithText(dateRangeInputLabel).onLast().performClick()
+ .performTextInput("05102020")
+
+ rule.runOnIdle {
+ assertThat(state.selectedStartDateMillis).isNull()
+ assertThat(state.selectedEndDateMillis).isNull()
+ }
+ rule.onNodeWithText("01/27/2019")
+ .assert(keyIsDefined(SemanticsProperties.Error))
+ .assert(
+ expectValue(
+ SemanticsProperties.Error,
+ errorMessage.format("Jan 27, 2019")
+ )
+ )
+ rule.onNodeWithText("05/10/2020")
+ .assert(keyIsDefined(SemanticsProperties.Error))
+ .assert(
+ expectValue(
+ SemanticsProperties.Error,
+ errorMessage.format("May 10, 2020")
+ )
+ )
+ }
+
+ @Test
+ fun outOfOrderDateRange() {
+ lateinit var dateRangeInputLabel: String
+ lateinit var errorMessage: String
+ lateinit var state: DateRangePickerState
+ rule.setMaterialContent(lightColorScheme()) {
+ dateRangeInputLabel = getString(string = Strings.DateInputLabel)
+ errorMessage = getString(string = Strings.DateRangeInputInvalidRangeInput)
+ state = rememberDateRangePickerState(
+ // Limit the years selection to 2018-2023
+ yearRange = IntRange(2018, 2023),
+ initialDisplayMode = DisplayMode.Input
+ )
+ DateRangePicker(state = state)
+ }
+
+ // Enter dates where the start date is later than the end date.
+ rule.onAllNodesWithText(dateRangeInputLabel).onFirst().performClick()
+ .performTextInput("01272020")
+ rule.onAllNodesWithText(dateRangeInputLabel).onLast().performClick()
+ .performTextInput("05102019")
+
+ rule.runOnIdle {
+ // Expecting the first stored date to still be valid, and the second one to be null.
+ assertThat(state.selectedStartDateMillis).isNotNull()
+ assertThat(state.selectedEndDateMillis).isNull()
+ }
+ rule.onNodeWithText("05/10/2019")
+ .assert(keyIsDefined(SemanticsProperties.Error))
+ .assert(expectValue(SemanticsProperties.Error, errorMessage))
+ }
+
+ @Test
+ fun switchToDateRangePicker() {
+ lateinit var switchToPickerDescription: String
+ lateinit var dateRangeInputLabel: String
+ lateinit var pickerStartDateHeadline: String
+ lateinit var pickerEndDateHeadline: String
+ rule.setMaterialContent(lightColorScheme()) {
+ switchToPickerDescription = getString(string = Strings.DatePickerSwitchToCalendarMode)
+ dateRangeInputLabel = getString(string = Strings.DateInputLabel)
+ pickerStartDateHeadline = getString(string = Strings.DateRangePickerStartHeadline)
+ pickerEndDateHeadline = getString(string = Strings.DateRangePickerEndHeadline)
+ DateRangePicker(
+ state = rememberDateRangePickerState(initialDisplayMode = DisplayMode.Input)
+ )
+ }
+
+ // Click to switch to DateRangePicker.
+ rule.onNodeWithContentDescription(label = switchToPickerDescription).performClick()
+
+ rule.waitForIdle()
+ rule.onNodeWithText(pickerStartDateHeadline, useUnmergedTree = true).assertIsDisplayed()
+ rule.onNodeWithText(pickerEndDateHeadline, useUnmergedTree = true).assertIsDisplayed()
+ rule.onNodeWithText(dateRangeInputLabel).assertDoesNotExist()
+ }
+
+ @Test
+ fun defaultSemantics() {
+ val startDateMillis = dayInUtcMilliseconds(year = 2010, month = 5, dayOfMonth = 11)
+ val endDateMillis = dayInUtcMilliseconds(year = 2010, month = 6, dayOfMonth = 12)
+ lateinit var pickerStartDateHeadline: String
+ lateinit var pickerEndDateHeadline: String
+ rule.setMaterialContent(lightColorScheme()) {
+ pickerStartDateHeadline = getString(string = Strings.DateRangePickerStartHeadline)
+ pickerEndDateHeadline = getString(string = Strings.DateRangePickerEndHeadline)
+ DateRangePicker(
+ state = rememberDateRangePickerState(
+ initialSelectedStartDateMillis = startDateMillis,
+ initialSelectedEndDateMillis = endDateMillis,
+ initialDisplayMode = DisplayMode.Input
+ )
+ )
+ }
+
+ val fullStartDateDescription = formatWithSkeleton(
+ startDateMillis,
+ DatePickerDefaults.YearMonthWeekdayDaySkeleton,
+ Locale.US
+ )
+ val fullEndDateDescription = formatWithSkeleton(
+ endDateMillis,
+ DatePickerDefaults.YearMonthWeekdayDaySkeleton,
+ Locale.US
+ )
+
+ val startHeadlineDescription = "$pickerStartDateHeadline: $fullStartDateDescription"
+ val endHeadlineDescription = "$pickerEndDateHeadline: $fullEndDateDescription"
+ rule.onNodeWithContentDescription("$startHeadlineDescription, $endHeadlineDescription")
+ .assertExists()
+ }
+
+ // Returns the given date's day as milliseconds from epoch. The returned value is for the day's
+ // start on midnight.
+ private fun dayInUtcMilliseconds(year: Int, month: Int, dayOfMonth: Int): Long {
+ val firstDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
+ firstDayCalendar.clear()
+ firstDayCalendar[Calendar.YEAR] = year
+ firstDayCalendar[Calendar.MONTH] = month - 1
+ firstDayCalendar[Calendar.DAY_OF_MONTH] = dayOfMonth
+ return firstDayCalendar.timeInMillis
+ }
+}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerScreenshotTest.kt
index 0b46437..2e96eb2 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerScreenshotTest.kt
@@ -62,7 +62,8 @@
DateRangePicker(
state = rememberDateRangePickerState(
initialDisplayedMonthMillis = monthInUtcMillis
- )
+ ),
+ showModeToggle = false
)
}
}
@@ -83,7 +84,8 @@
initialDisplayedMonthMillis = monthInUtcMillis,
initialSelectedStartDateMillis = startSelectionMillis,
initialSelectedEndDateMillis = endSelectionMillis
- )
+ ),
+ showModeToggle = false
)
}
}
@@ -104,7 +106,8 @@
initialDisplayedMonthMillis = monthInUtcMillis,
initialSelectedStartDateMillis = startSelectionMillis,
initialSelectedEndDateMillis = endSelectionMillis
- )
+ ),
+ showModeToggle = false
)
}
}
@@ -126,13 +129,29 @@
.toLocalDate()
val dayOfWeek = localDate.dayOfWeek
dayOfWeek != DayOfWeek.SUNDAY
- }
+ },
+ showModeToggle = false
)
}
}
assertAgainstGolden("dateRangePicker_invalidSundaySelection_${scheme.name}")
}
+ @Test
+ fun dateRangePicker_withModeToggle() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ Box(wrap.testTag(wrapperTestTag)) {
+ val monthInUtcMillis = dayInUtcMilliseconds(year = 2021, month = 1, dayOfMonth = 1)
+ DateRangePicker(
+ state = rememberDateRangePickerState(
+ initialDisplayedMonthMillis = monthInUtcMillis
+ )
+ )
+ }
+ }
+ assertAgainstGolden("dateRangePicker_withModeToggle_${scheme.name}")
+ }
+
// Returns the given date's day as milliseconds from epoch. The returned value is for the day's
// start on midnight.
private fun dayInUtcMilliseconds(year: Int, month: Int, dayOfMonth: Int): Long =
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
index 351f502..feecc3a 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
@@ -302,8 +302,8 @@
stateData.calendarModel.getCanonicalDate(1649721600000L + MillisecondsIn24Hours)
val displayedMonth = stateData.calendarModel.getMonth(startDate)
rule.runOnIdle {
- stateData.selectedStartDate = startDate
- stateData.selectedEndDate = endDate
+ stateData.selectedStartDate.value = startDate
+ stateData.selectedEndDate.value = endDate
stateData.displayedMonth = displayedMonth
}
@@ -312,8 +312,8 @@
restorationTester.emulateSavedInstanceStateRestore()
rule.runOnIdle {
- assertThat(stateData.selectedStartDate).isEqualTo(startDate)
- assertThat(stateData.selectedEndDate).isEqualTo(endDate)
+ assertThat(stateData.selectedStartDate.value).isEqualTo(startDate)
+ assertThat(stateData.selectedEndDate.value).isEqualTo(endDate)
assertThat(stateData.displayedMonth).isEqualTo(displayedMonth)
assertThat(dateRangePickerState!!.selectedStartDateMillis)
.isEqualTo(1649721600000L)
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SnackbarHostTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SnackbarHostTest.kt
index 8201b0a..14e22c4 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SnackbarHostTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SnackbarHostTest.kt
@@ -141,7 +141,8 @@
Truth.assertThat(result).isEqualTo(SnackbarResult.Dismissed)
}
- rule.waitUntil(timeoutMillis = 10_000) { job2.isCompleted }
+ rule.mainClock.advanceTimeBy(5_000)
+ rule.waitUntil { job2.isCompleted }
}
@Test
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
index eafc433..bbffc0f5 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
@@ -17,20 +17,22 @@
package androidx.compose.material3
import android.os.Build
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.testutils.assertAgainstGolden
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.captureToImage
import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.longClick
import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import androidx.test.filters.SdkSuppress
import androidx.test.screenshot.AndroidXScreenshotTestRule
-import kotlinx.coroutines.launch
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,44 +50,98 @@
@Test
fun plainTooltip_lightTheme() {
- rule.setMaterialContent(lightColorScheme()) { TestPlainTooltips() }
+ rule.setMaterialContent(lightColorScheme()) { PlainTooltipTest() }
+
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
assertAgainstGolden("plainTooltip_lightTheme")
}
@Test
fun plainTooltip_darkTheme() {
- rule.setMaterialContent(darkColorScheme()) { TestPlainTooltips() }
+ rule.setMaterialContent(darkColorScheme()) { PlainTooltipTest() }
+
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
assertAgainstGolden("plainTooltip_darkTheme")
}
@Test
fun richTooltip_lightTheme() {
- rule.setMaterialContent(lightColorScheme()) { TestRichTooltips() }
+ rule.setMaterialContent(lightColorScheme()) { RichTooltipTest() }
+
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
assertAgainstGolden("richTooltip_lightTheme")
}
@Test
fun richTooltip_darkTheme() {
- rule.setMaterialContent(darkColorScheme()) { TestRichTooltips() }
+ rule.setMaterialContent(darkColorScheme()) { RichTooltipTest() }
+
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
assertAgainstGolden("richTooltip_darkTheme")
}
+ private fun assertAgainstGolden(goldenName: String) {
+ rule.onNodeWithTag(TooltipTestTag)
+ .captureToImage()
+ .assertAgainstGolden(screenshotRule, goldenName)
+ }
+
@Composable
- private fun TestPlainTooltips() {
- val scope = rememberCoroutineScope()
+ private fun PlainTooltipTest() {
val tooltipState = remember { PlainTooltipState() }
PlainTooltipBox(
tooltip = { Text("Tooltip Text") },
modifier = Modifier.testTag(TooltipTestTag),
tooltipState = tooltipState
- ) {}
-
- scope.launch { tooltipState.show() }
+ ) {
+ Icon(
+ Icons.Filled.Favorite,
+ contentDescription = null,
+ modifier = Modifier
+ .testTag(AnchorTestTag)
+ .tooltipAnchor()
+ )
+ }
}
@Composable
- private fun TestRichTooltips() {
- val scope = rememberCoroutineScope()
+ private fun RichTooltipTest() {
val tooltipState = remember { RichTooltipState() }
RichTooltipBox(
title = { Text("Title") },
@@ -98,16 +154,17 @@
action = { Text("Action Text") },
tooltipState = tooltipState,
modifier = Modifier.testTag(TooltipTestTag)
- ) {}
-
- scope.launch { tooltipState.show() }
- }
-
- private fun assertAgainstGolden(goldenName: String) {
- rule.onNodeWithTag(TooltipTestTag)
- .captureToImage()
- .assertAgainstGolden(screenshotRule, goldenName)
+ ) {
+ Icon(
+ Icons.Filled.Favorite,
+ contentDescription = null,
+ modifier = Modifier
+ .testTag(AnchorTestTag)
+ .tooltipAnchor()
+ )
+ }
}
}
+private const val AnchorTestTag = "Anchor"
private const val TooltipTestTag = "tooltip"
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
index 666507d..848bfb6 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
@@ -16,8 +16,6 @@
package androidx.compose.material3
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
@@ -41,7 +39,6 @@
import androidx.test.filters.MediumTest
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.launch
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -56,8 +53,18 @@
@Test
fun plainTooltip_noContent_size() {
- rule.setMaterialContent(lightColorScheme()) { TestPlainTooltip() }
+ rule.setMaterialContent(lightColorScheme()) { PlainTooltipTest() }
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
rule.onNodeWithTag(ContainerTestTag)
.assertHeightIsEqualTo(TooltipMinHeight)
.assertWidthIsEqualTo(TooltipMinWidth)
@@ -65,7 +72,18 @@
@Test
fun richTooltip_noContent_size() {
- rule.setMaterialContent(lightColorScheme()) { TestRichTooltip() }
+ rule.setMaterialContent(lightColorScheme()) { RichTooltipTest() }
+
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
rule.onNodeWithTag(ContainerTestTag)
.assertHeightIsEqualTo(TooltipMinHeight)
.assertWidthIsEqualTo(TooltipMinWidth)
@@ -75,11 +93,22 @@
fun plainTooltip_customSize_size() {
val customWidth = 100.dp
val customHeight = 100.dp
-
rule.setMaterialContent(lightColorScheme()) {
- TestPlainTooltip(modifier = Modifier.size(customWidth, customHeight))
+ PlainTooltipTest(
+ modifier = Modifier.size(customWidth, customHeight)
+ )
}
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
rule.onNodeWithTag(ContainerTestTag)
.assertHeightIsEqualTo(customHeight)
.assertWidthIsEqualTo(customWidth)
@@ -89,21 +118,31 @@
fun richTooltip_customSize_size() {
val customWidth = 100.dp
val customHeight = 100.dp
-
rule.setMaterialContent(lightColorScheme()) {
- TestRichTooltip(modifier = Modifier.size(customWidth, customHeight))
+ RichTooltipTest(
+ modifier = Modifier.size(customWidth, customHeight)
+ )
}
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
rule.onNodeWithTag(ContainerTestTag)
.assertHeightIsEqualTo(customHeight)
.assertWidthIsEqualTo(customWidth)
}
- @Ignore // b/264907895
@Test
fun plainTooltip_content_padding() {
rule.setMaterialContent(lightColorScheme()) {
- TestPlainTooltip(
+ PlainTooltipTest(
tooltipContent = {
Text(
text = "Test",
@@ -113,6 +152,16 @@
)
}
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
rule.onNodeWithTag(TextTestTag)
.assertLeftPositionInRootIsEqualTo(8.dp)
.assertTopPositionInRootIsEqualTo(4.dp)
@@ -121,13 +170,23 @@
@Test
fun richTooltip_content_padding() {
rule.setMaterialContent(lightColorScheme()) {
- TestRichTooltip(
+ RichTooltipTest(
title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
- action = { Text(text = "Action", modifier = Modifier.testTag(ActionTestTag)) },
+ action = { Text(text = "Action", modifier = Modifier.testTag(ActionTestTag)) }
)
}
+ // Stop auto advance for test consistency
+ rule.mainClock.autoAdvance = false
+
+ rule.onNodeWithTag(AnchorTestTag)
+ .performTouchInput { longClick() }
+
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
+ rule.waitForIdle()
val subhead = rule.onNodeWithTag(SubheadTestTag)
val text = rule.onNodeWithTag(TextTestTag)
@@ -154,23 +213,25 @@
fun plainTooltip_behavior() {
val tooltipState = PlainTooltipState()
rule.setMaterialContent(lightColorScheme()) {
- PlainTooltipBox(
- tooltip = { Text(text = "Test", modifier = Modifier.testTag(TextTestTag)) },
- tooltipState = tooltipState,
- modifier = Modifier.testTag(ContainerTestTag)
- ) { Anchor(tooltipState) }
+ PlainTooltipTest(
+ tooltipContent = { Text(text = "Test", modifier = Modifier.testTag(TextTestTag)) },
+ tooltipState = tooltipState
+ )
}
- // Tooltip should initially be not visible
- assertThat(tooltipState.isVisible).isFalse()
-
// Test will manually advance the time to check the timeout
rule.mainClock.autoAdvance = false
+ // Tooltip should initially be not visible
+ assertThat(tooltipState.isVisible).isFalse()
+
// Long press the icon
rule.onNodeWithTag(AnchorTestTag)
.performTouchInput { longClick() }
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
// Check that the tooltip is now showing
rule.waitForIdle()
assertThat(tooltipState.isVisible).isTrue()
@@ -185,24 +246,26 @@
fun richTooltip_behavior_noAction() {
val tooltipState = RichTooltipState()
rule.setMaterialContent(lightColorScheme()) {
- RichTooltipBox(
+ RichTooltipTest(
title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
- tooltipState = tooltipState,
- modifier = Modifier.testTag(ContainerTestTag)
- ) { Anchor(tooltipState) }
+ tooltipState = tooltipState
+ )
}
- // Tooltip should initially be not visible
- assertThat(tooltipState.isVisible).isFalse()
-
// Test will manually advance the time to check the timeout
rule.mainClock.autoAdvance = false
+ // Tooltip should initially be not visible
+ assertThat(tooltipState.isVisible).isFalse()
+
// Long press the icon
rule.onNodeWithTag(AnchorTestTag)
.performTouchInput { longClick() }
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
// Check that the tooltip is now showing
rule.waitForIdle()
assertThat(tooltipState.isVisible).isTrue()
@@ -218,7 +281,7 @@
val tooltipState = RichTooltipState()
rule.setMaterialContent(lightColorScheme()) {
val scope = rememberCoroutineScope()
- RichTooltipBox(
+ RichTooltipTest(
title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
action = {
@@ -227,21 +290,23 @@
modifier = Modifier.testTag(ActionTestTag)
) { Text(text = "Action") }
},
- tooltipState = tooltipState,
- modifier = Modifier.testTag(ContainerTestTag)
- ) { Anchor(tooltipState) }
+ tooltipState = tooltipState
+ )
}
- // Tooltip should initially be not visible
- assertThat(tooltipState.isVisible).isFalse()
-
// Test will manually advance the time to check the timeout
rule.mainClock.autoAdvance = false
+ // Tooltip should initially be not visible
+ assertThat(tooltipState.isVisible).isFalse()
+
// Long press the icon
rule.onNodeWithTag(AnchorTestTag)
.performTouchInput { longClick() }
+ // Advance by the fade in time
+ rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
+
// Check that the tooltip is now showing
rule.waitForIdle()
assertThat(tooltipState.isVisible).isTrue()
@@ -258,64 +323,49 @@
}
@Composable
- private fun TestPlainTooltip(
+ private fun PlainTooltipTest(
modifier: Modifier = Modifier,
+ tooltipContent: @Composable () -> Unit = {},
tooltipState: PlainTooltipState = remember { PlainTooltipState() },
- tooltipContent: @Composable () -> Unit = {}
) {
- val scope = rememberCoroutineScope()
-
PlainTooltipBox(
tooltip = tooltipContent,
- modifier = modifier.testTag(ContainerTestTag),
- tooltipState = tooltipState
- ) {}
-
- scope.launch { tooltipState.show() }
+ tooltipState = tooltipState,
+ modifier = modifier.testTag(ContainerTestTag)
+ ) {
+ Icon(
+ Icons.Filled.Favorite,
+ contentDescription = null,
+ modifier = Modifier
+ .testTag(AnchorTestTag)
+ .tooltipAnchor()
+ )
+ }
}
@Composable
- private fun TestRichTooltip(
+ private fun RichTooltipTest(
modifier: Modifier = Modifier,
tooltipState: RichTooltipState = remember { RichTooltipState() },
text: @Composable () -> Unit = {},
- action: (@Composable () -> Unit)? = null,
- title: (@Composable () -> Unit)? = null
+ title: (@Composable () -> Unit)? = null,
+ action: (@Composable () -> Unit)? = null
) {
- val scope = rememberCoroutineScope()
-
RichTooltipBox(
text = text,
- action = action,
title = title,
- modifier = modifier.testTag(ContainerTestTag),
- tooltipState = tooltipState
- ) {}
-
- scope.launch { tooltipState.show() }
- }
-
- @OptIn(ExperimentalFoundationApi::class)
- @Composable
- private fun Anchor(
- tooltipState: TooltipState
- ) {
- val scope = rememberCoroutineScope()
-
- Icon(
- Icons.Filled.Favorite,
- contentDescription = null,
- modifier = Modifier
- .testTag(AnchorTestTag)
- .combinedClickable(
- onClick = {},
- onLongClick = {
- scope.launch {
- tooltipState.show()
- }
- }
- )
- )
+ action = action,
+ tooltipState = tooltipState,
+ modifier = modifier.testTag(ContainerTestTag)
+ ) {
+ Icon(
+ Icons.Filled.Favorite,
+ contentDescription = null,
+ modifier = Modifier
+ .testTag(AnchorTestTag)
+ .tooltipAnchor()
+ )
+ }
}
}
@@ -323,4 +373,4 @@
private const val TextTestTag = "Text"
private const val SubheadTestTag = "Subhead"
private const val ActionTestTag = "Action"
-private const val AnchorTestTag = "Anchor'"
\ No newline at end of file
+private const val AnchorTestTag = "Anchor"
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
index eb02073..731e5348 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
@@ -93,6 +93,12 @@
Strings.DatePickerTodayDescription -> resources.getString(
androidx.compose.material3.R.string.date_picker_today_description
)
+ Strings.DatePickerScrollToShowLaterYears -> resources.getString(
+ androidx.compose.material3.R.string.date_picker_scroll_to_later_years
+ )
+ Strings.DatePickerScrollToShowEarlierYears -> resources.getString(
+ androidx.compose.material3.R.string.date_picker_scroll_to_earlier_years
+ )
Strings.DateInputTitle -> resources.getString(
androidx.compose.material3.R.string.date_input_title
)
@@ -129,11 +135,20 @@
Strings.DateRangePickerStartHeadline -> resources.getString(
androidx.compose.material3.R.string.date_range_picker_start_headline
)
+ Strings.DateRangePickerEndHeadline -> resources.getString(
+ androidx.compose.material3.R.string.date_range_picker_end_headline
+ )
+ Strings.DateRangePickerScrollToShowNextMonth -> resources.getString(
+ androidx.compose.material3.R.string.date_range_picker_scroll_to_next_month
+ )
+ Strings.DateRangePickerScrollToShowPreviousMonth -> resources.getString(
+ androidx.compose.material3.R.string.date_range_picker_scroll_to_previous_month
+ )
Strings.DateRangeInputTitle -> resources.getString(
androidx.compose.material3.R.string.date_range_input_title
)
- Strings.DateRangePickerEndHeadline -> resources.getString(
- androidx.compose.material3.R.string.date_range_picker_end_headline
+ Strings.DateRangeInputInvalidRangeInput -> resources.getString(
+ androidx.compose.material3.R.string.date_range_input_invalid_range_input
)
Strings.TooltipLongPressLabel -> resources.getString(
androidx.compose.material3.R.string.tooltip_long_press_label
diff --git a/compose/material3/material3/src/androidMain/res/values/strings.xml b/compose/material3/material3/src/androidMain/res/values/strings.xml
index a7eadde..465ed75 100644
--- a/compose/material3/material3/src/androidMain/res/values/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values/strings.xml
@@ -54,10 +54,22 @@
</string>
<string name="date_picker_switch_to_calendar_mode">Switch to calendar input mode</string>
<string name="date_picker_switch_to_input_mode">Switch to text input mode</string>
+ <!-- Spoken description for scrolling to display later years -->
+ <string name="date_picker_scroll_to_later_years">Scroll to show later years</string>
+ <!-- Spoken description for scrolling to display earlier years -->
+ <string name="date_picker_scroll_to_earlier_years">Scroll to show earlier years</string>
<string name="date_range_picker_title">Select dates</string>
<string name="date_range_picker_start_headline">Start date</string>
<string name="date_range_picker_end_headline">End date</string>
+ <!-- Spoken description for scrolling to the next month -->
+ <string name="date_range_picker_scroll_to_next_month">Scroll to show the next month</string>
+ <!-- Spoken description for scrolling to the previous month -->
+ <string name="date_range_picker_scroll_to_previous_month">Scroll to show the previous month</string>
<string name="date_range_input_title">Enter dates</string>
+ <!--
+ Describes an invalid date range input when a user enters a start or end date [CHAR_LIMIT=NONE]
+ -->
+ <string name="date_range_input_invalid_range_input">Invalid date range input</string>
<!-- Spoken description of a tooltip -->
<string name="tooltip_long_press_label">Show tooltip</string>
<!-- Suffix for time in 12-hour standard, after noon. [CHAR_LIMIT=2]" -->
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
index d513a40..9291197 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
@@ -17,6 +17,7 @@
package androidx.compose.material3
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import java.util.Locale
@@ -285,6 +286,7 @@
* in a short format, as well as a date pattern with and without a delimiter.
*/
@ExperimentalMaterial3Api
+@Immutable
internal data class DateInputFormat(
val patternWithDelimiters: String,
val delimiter: Char
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
index 129ac14..42b31c0 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateInput.kt
@@ -21,6 +21,8 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -38,6 +40,7 @@
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
+import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -46,39 +49,62 @@
dateFormatter: DatePickerFormatter,
dateValidator: (Long) -> Boolean,
) {
- DateInputTextField(
- modifier = Modifier
- .fillMaxWidth()
- .padding(InputTextFieldPadding),
- stateData = stateData,
- dateFormatter = dateFormatter,
- dateValidator = dateValidator
- )
-}
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-private fun DateInputTextField(
- modifier: Modifier,
- stateData: StateData,
- dateFormatter: DatePickerFormatter,
- dateValidator: (Long) -> Boolean
-) {
// Obtain the DateInputFormat for the default Locale.
val defaultLocale = defaultLocale()
val dateInputFormat = remember(defaultLocale) {
stateData.calendarModel.getDateInputFormat(defaultLocale)
}
- var errorText by rememberSaveable { mutableStateOf("") }
+ val errorDatePattern = getString(Strings.DateInputInvalidForPattern)
+ val errorDateOutOfYearRange = getString(Strings.DateInputInvalidYearRange)
+ val errorInvalidNotAllowed = getString(Strings.DateInputInvalidNotAllowed)
+ val dateInputValidator = remember(dateInputFormat, dateFormatter) {
+ DateInputValidator(
+ stateData = stateData,
+ dateInputFormat = dateInputFormat,
+ dateFormatter = dateFormatter,
+ dateValidator = dateValidator,
+ errorDatePattern = errorDatePattern,
+ errorDateOutOfYearRange = errorDateOutOfYearRange,
+ errorInvalidNotAllowed = errorInvalidNotAllowed,
+ errorInvalidRangeInput = "" // Not used for a single date input
+ )
+ }
+ DateInputTextField(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(InputTextFieldPadding),
+ stateData = stateData,
+ initialDate = stateData.selectedStartDate.value,
+ onDateChanged = { date -> stateData.selectedStartDate.value = date },
+ inputIdentifier = InputIdentifier.SingleDateInput,
+ dateInputValidator = dateInputValidator,
+ dateInputFormat = dateInputFormat,
+ locale = defaultLocale
+ )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal fun DateInputTextField(
+ modifier: Modifier,
+ stateData: StateData,
+ initialDate: CalendarDate?,
+ onDateChanged: (CalendarDate?) -> Unit,
+ inputIdentifier: InputIdentifier,
+ dateInputValidator: DateInputValidator,
+ dateInputFormat: DateInputFormat,
+ locale: Locale
+) {
+ val errorText = rememberSaveable { mutableStateOf("") }
var text by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
TextFieldValue(
text = with(stateData) {
- selectedStartDate?.let {
+ initialDate?.let {
calendarModel.formatWithPattern(
it.utcTimeMillis,
dateInputFormat.patternWithoutDelimiters,
- defaultLocale
+ locale
)
} ?: ""
},
@@ -87,57 +113,6 @@
)
}
- // Holds a string for displaying an error message when an input does not match the expected date
- // pattern. The string expects a date pattern string as an argument to be formatted into it.
- val errorDatePattern = getString(Strings.DateInputInvalidForPattern)
- // Holds a string for displaying an error message when an input date exceeds the year-range
- // defined at the DateInput's state. The string expects a start and end year as arguments to
- // be formatted into it.
- val errorDateOutOfYearRange = getString(Strings.DateInputInvalidYearRange)
- // Holds a string for displaying an error message when an input date does not pass the
- // DateInput's validator check. The string expects a date argument to be formatted into it.
- val errorInvalidNotAllowed = getString(Strings.DateInputInvalidNotAllowed)
-
- // Validates the input. Sets an error message at the errorText, or return a non-null
- // CalendarDate that represents a validated date.
- fun validate(input: TextFieldValue): CalendarDate? {
- val dateInputText = input.text.trim()
- if (dateInputText.isEmpty() ||
- dateInputText.length < dateInputFormat.patternWithoutDelimiters.length
- ) {
- errorText = ""
- return null
- }
- val parsedDate = stateData.calendarModel.parse(
- dateInputText,
- dateInputFormat.patternWithoutDelimiters
- )
- if (parsedDate == null) {
- errorText = errorDatePattern.format(dateInputFormat.patternWithDelimiters.uppercase())
- return null
- }
- // Check that the date is within the valid range of years.
- if (!stateData.yearRange.contains(parsedDate.year)) {
- errorText = errorDateOutOfYearRange.format(
- stateData.yearRange.first,
- stateData.yearRange.last
- )
- return null
- }
- // Check that the provided date validator allows this date to be selected.
- if (!dateValidator.invoke(parsedDate.utcTimeMillis)) {
- errorText = errorInvalidNotAllowed.format(
- dateFormatter.formatDate(
- date = parsedDate,
- calendarModel = stateData.calendarModel,
- locale = defaultLocale
- )
- )
- return null
- }
- return parsedDate
- }
-
OutlinedTextField(
value = text,
onValueChange = { input ->
@@ -145,26 +120,45 @@
input.text.all { it.isDigit() }
) {
text = input
- stateData.selectedStartDate = validate(input)
+ val trimmedText = input.text.trim()
+ if (trimmedText.isEmpty() ||
+ trimmedText.length < dateInputFormat.patternWithoutDelimiters.length
+ ) {
+ errorText.value = ""
+ onDateChanged(null)
+ } else {
+ val parsedDate = stateData.calendarModel.parse(
+ trimmedText,
+ dateInputFormat.patternWithoutDelimiters
+ )
+ errorText.value = dateInputValidator.validate(
+ calendarDate = parsedDate,
+ inputIdentifier = inputIdentifier,
+ locale = locale
+ )
+ // Set the parsed date only if the error validation returned an empty string.
+ // Otherwise, set it to null, as the validation failed.
+ onDateChanged(if (errorText.value.isEmpty()) parsedDate else null)
+ }
}
},
modifier = modifier
// Add bottom padding when there is no error. Otherwise, remove it as the error text
// will take additional height.
.padding(
- bottom = if (errorText.isNotBlank()) {
+ bottom = if (errorText.value.isNotBlank()) {
0.dp
} else {
InputTextNonErroneousBottomPadding
}
)
.semantics {
- if (errorText.isNotBlank()) error(errorText)
+ if (errorText.value.isNotBlank()) error(errorText.value)
},
label = { Text(getString(string = Strings.DateInputLabel)) },
placeholder = { Text(dateInputFormat.patternWithDelimiters.uppercase()) },
- supportingText = { if (errorText.isNotBlank()) Text(errorText) },
- isError = errorText.isNotBlank(),
+ supportingText = { if (errorText.value.isNotBlank()) Text(errorText.value) },
+ isError = errorText.value.isNotBlank(),
visualTransformation = DateVisualTransformation(dateInputFormat),
keyboardOptions = KeyboardOptions(
autoCorrect = false,
@@ -176,6 +170,118 @@
}
/**
+ * A date input validator class.
+ *
+ * @param stateData the [StateData] that holds the selected dates info
+ * @param dateInputFormat a [DateInputFormat] that holds date patterns information
+ * @param dateFormatter a [DatePickerFormatter]
+ * @param dateValidator a lambda that takes a date timestamp and return true if the date is a valid
+ * one for selection.
+ * @param errorDatePattern a string for displaying an error message when an input does not match the
+ * expected date pattern. The string expects a date pattern string as an argument to be formatted
+ * into it.
+ * @param errorDateOutOfYearRange a string for displaying an error message when an input date
+ * exceeds the year-range defined at the DateInput's state. The string expects a start and end year
+ * as arguments to be formatted into it.
+ * @param errorInvalidNotAllowed a string for displaying an error message when an input date does
+ * not pass the DateInput's validator check. The string expects a date argument to be formatted into
+ * it.
+ * @param errorInvalidRangeInput a string for displaying an error message when in a range input mode
+ * and one of the input dates is out of order (i.e. the user inputs a start date that is after the
+ * end date, or an end date that is before the start date)
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Stable
+internal class DateInputValidator(
+ private val stateData: StateData,
+ private val dateInputFormat: DateInputFormat,
+ private val dateFormatter: DatePickerFormatter,
+ private val dateValidator: (Long) -> Boolean,
+ private val errorDatePattern: String,
+ private val errorDateOutOfYearRange: String,
+ private val errorInvalidNotAllowed: String,
+ private val errorInvalidRangeInput: String
+) {
+
+ /**
+ * Validates a [CalendarDate] input and returns an error string in case an issue with the given
+ * date is detected, or an empty string in case there are no issues.
+ *
+ * @param calendarDate a [CalendarDate] input
+ * @param inputIdentifier an [InputIdentifier] that provides information about the input field
+ * that is supposed to hold the date.
+ * @param locale the current [Locale]
+ */
+ fun validate(
+ calendarDate: CalendarDate?,
+ inputIdentifier: InputIdentifier,
+ locale: Locale
+ ): String {
+ if (calendarDate == null) {
+ return errorDatePattern.format(dateInputFormat.patternWithDelimiters.uppercase())
+ }
+ // Check that the date is within the valid range of years.
+ if (!stateData.yearRange.contains(calendarDate.year)) {
+ return errorDateOutOfYearRange.format(
+ stateData.yearRange.first.toLocalString(),
+ stateData.yearRange.last.toLocalString()
+ )
+ }
+ // Check that the provided date validator allows this date to be selected.
+ if (!dateValidator.invoke(calendarDate.utcTimeMillis)) {
+ return errorInvalidNotAllowed.format(
+ dateFormatter.formatDate(
+ date = calendarDate,
+ calendarModel = stateData.calendarModel,
+ locale = locale
+ )
+ )
+ }
+
+ // Additional validation when the InputIdentifier is for start of end dates in a range input
+ if ((inputIdentifier == InputIdentifier.StartDateInput &&
+ calendarDate.utcTimeMillis >= (stateData.selectedEndDate.value?.utcTimeMillis
+ ?: Long.MAX_VALUE)) ||
+ (inputIdentifier == InputIdentifier.EndDateInput &&
+ calendarDate.utcTimeMillis <= (stateData.selectedStartDate.value?.utcTimeMillis
+ ?: Long.MIN_VALUE))
+ ) {
+ // The input start date is after the end date, or the end date is before the start date.
+ return errorInvalidRangeInput
+ }
+
+ return ""
+ }
+}
+
+/**
+ * Represents different input identifiers for the [DateInputTextField]. An `InputIdentifier` is used
+ * when validating the user input, and especially when validating an input range.
+ */
+@Immutable
+@JvmInline
+internal value class InputIdentifier internal constructor(internal val value: Int) {
+
+ companion object {
+ /** Single date input */
+ val SingleDateInput = InputIdentifier(0)
+
+ /** A start date input */
+ val StartDateInput = InputIdentifier(1)
+
+ /** An end date input */
+ val EndDateInput = InputIdentifier(2)
+ }
+
+ override fun toString() = when (this) {
+ SingleDateInput -> "SingleDateInput"
+ StartDateInput -> "StartDateInput"
+ EndDateInput -> "EndDateInput"
+ else -> "Unknown"
+ }
+}
+
+/**
* A [VisualTransformation] for date input. The transformation will automatically display the date
* delimiters provided by the [DateInputFormat] as the date is being entered into the text field.
*/
@@ -228,7 +334,7 @@
}
}
-private val InputTextFieldPadding = PaddingValues(
+internal val InputTextFieldPadding = PaddingValues(
start = 12.dp,
end = 12.dp,
top = 10.dp
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
index a900775..6df721d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
@@ -48,6 +48,7 @@
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.lazy.rememberLazyListState
@@ -86,12 +87,15 @@
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.LiveRegionMode
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.ScrollAxisRange
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.horizontalScrollAxisRange
+import androidx.compose.ui.semantics.isContainer
import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.paneTitle
import androidx.compose.ui.semantics.role
@@ -105,6 +109,7 @@
import java.lang.Integer.max
import java.text.NumberFormat
import java.util.Locale
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
// TODO: External preview image.
@@ -160,7 +165,16 @@
title = title,
headline = headline,
modeToggleButton = if (showModeToggle) {
- { DateEntryModeToggleButton(stateData = state.stateData) }
+ {
+ DisplayModeToggleButton(
+ displayMode = state.displayMode,
+ onDisplayModeChange = { displayMode ->
+ state.stateData.switchDisplayMode(
+ displayMode
+ )
+ },
+ )
+ }
} else {
null
},
@@ -262,7 +276,7 @@
*/
@get:Suppress("AutoBoxing")
val selectedDateMillis by derivedStateOf {
- stateData.selectedStartDate?.utcTimeMillis
+ stateData.selectedStartDate.value?.utcTimeMillis
}
/**
@@ -413,12 +427,12 @@
with(state.stateData) {
val defaultLocale = defaultLocale()
val formattedDate = dateFormatter.formatDate(
- date = selectedStartDate,
+ date = selectedStartDate.value,
calendarModel = calendarModel,
locale = defaultLocale
)
val verboseDateDescription = dateFormatter.formatDate(
- date = selectedStartDate,
+ date = selectedStartDate.value,
calendarModel = calendarModel,
locale = defaultLocale,
forContentDescription = true
@@ -810,7 +824,7 @@
/**
* A mutable state of [CalendarDate] that represents the start date for a selection.
*/
- var selectedStartDate by mutableStateOf(
+ var selectedStartDate = mutableStateOf(
if (initialSelectedStartDateMillis != null) {
val date = calendarModel.getCanonicalDate(
initialSelectedStartDateMillis
@@ -830,7 +844,7 @@
*
* Single date selection states that use this [StateData] should always have this as `null`.
*/
- var selectedEndDate by mutableStateOf(
+ var selectedEndDate = mutableStateOf(
// Set to null in case the provided value is "undefined" or <= than the start date.
if (initialSelectedEndDateMillis != null &&
initialSelectedStartDateMillis != null &&
@@ -896,8 +910,22 @@
get() = (yearRange.last - yearRange.first + 1) * 12
fun isInRange(date: Long): Boolean {
- return date >= (selectedStartDate?.utcTimeMillis ?: Long.MAX_VALUE) &&
- date <= (selectedEndDate?.utcTimeMillis ?: Long.MIN_VALUE)
+ return date >= (selectedStartDate.value?.utcTimeMillis ?: Long.MAX_VALUE) &&
+ date <= (selectedEndDate.value?.utcTimeMillis ?: Long.MIN_VALUE)
+ }
+
+ fun switchDisplayMode(displayMode: DisplayMode) {
+ // Update the displayed month, if needed, and change the mode to a date-picker.
+ selectedStartDate.value?.let {
+ displayedMonth = calendarModel.getMonth(it)
+ }
+ // When toggling back from an input mode, it's possible that the user input an invalid
+ // start date and a valid end date. If this is the case, and the start date is null, ensure
+ // that the end date is also null.
+ if (selectedStartDate.value == null && selectedEndDate.value != null) {
+ selectedEndDate.value = null
+ }
+ this.displayMode.value = displayMode
}
companion object {
@@ -907,8 +935,8 @@
fun Saver(): Saver<StateData, Any> = listSaver(
save = {
listOf(
- it.selectedStartDate?.utcTimeMillis,
- it.selectedEndDate?.utcTimeMillis,
+ it.selectedStartDate.value?.utcTimeMillis,
+ it.selectedEndDate.value?.utcTimeMillis,
it.displayedMonth.startUtcTimeMillis,
it.yearRange.first,
it.yearRange.last,
@@ -949,6 +977,7 @@
modifier = modifier
.sizeIn(minWidth = DatePickerModalTokens.ContainerWidth)
.padding(DatePickerHorizontalPadding)
+ .semantics { isContainer = true }
) {
DatePickerHeader(
modifier = Modifier,
@@ -968,31 +997,25 @@
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-internal fun DateEntryModeToggleButton(stateData: StateData) {
- with(stateData) {
- if (displayMode.value == DisplayMode.Picker) {
- IconButton(onClick = {
- displayMode.value = DisplayMode.Input
- }) {
- Icon(
- imageVector = Icons.Filled.Edit,
- contentDescription = getString(Strings.DatePickerSwitchToInputMode)
- )
- }
- } else {
- IconButton(
- onClick = {
- // Update the displayed month, if needed, and change the mode to a
- // date-picker.
- selectedStartDate?.let { displayedMonth = calendarModel.getMonth(it) }
- displayMode.value = DisplayMode.Picker
- }
- ) {
- Icon(
- imageVector = Icons.Filled.DateRange,
- contentDescription = getString(Strings.DatePickerSwitchToCalendarMode)
- )
- }
+internal fun DisplayModeToggleButton(
+ displayMode: DisplayMode,
+ onDisplayModeChange: (DisplayMode) -> Unit
+) {
+ if (displayMode == DisplayMode.Picker) {
+ IconButton(onClick = { onDisplayModeChange(DisplayMode.Input) }) {
+ Icon(
+ imageVector = Icons.Filled.Edit,
+ contentDescription = getString(Strings.DatePickerSwitchToInputMode)
+ )
+ }
+ } else {
+ IconButton(
+ onClick = { onDisplayModeChange(DisplayMode.Picker) }
+ ) {
+ Icon(
+ imageVector = Icons.Filled.DateRange,
+ contentDescription = getString(Strings.DatePickerSwitchToCalendarMode)
+ )
}
}
}
@@ -1011,7 +1034,10 @@
) {
// TODO(b/266480386): Apply the motion spec for this once we have it. Consider replacing this
// with AnimatedContent when it's out of experimental.
- Crossfade(targetState = state.displayMode, animationSpec = spring()) { mode ->
+ Crossfade(
+ targetState = state.displayMode,
+ animationSpec = spring(),
+ modifier = Modifier.semantics { isContainer = true }) { mode ->
when (mode) {
DisplayMode.Picker -> DatePickerContent(
stateData = state.stateData,
@@ -1042,7 +1068,7 @@
val coroutineScope = rememberCoroutineScope()
val onDateSelected = { dateInMillis: Long ->
- stateData.selectedStartDate =
+ stateData.selectedStartDate.value =
stateData.calendarModel.getCanonicalDate(dateInMillis)
}
@@ -1334,8 +1360,8 @@
if (rangeSelectionEnabled) {
SelectedRangeInfo.calculateRangeInfo(
month,
- stateData.selectedStartDate,
- stateData.selectedEndDate
+ stateData.selectedStartDate.value,
+ stateData.selectedEndDate.value
)
} else {
null
@@ -1389,8 +1415,9 @@
val dateInMillis = month.startUtcTimeMillis +
(dayNumber * MillisecondsIn24Hours)
val isToday = dateInMillis == today.utcTimeMillis
- val startDateSelected = dateInMillis == startSelection?.utcTimeMillis
- val endDateSelected = dateInMillis == endSelection?.utcTimeMillis
+ val startDateSelected =
+ dateInMillis == startSelection.value?.utcTimeMillis
+ val endDateSelected = dateInMillis == endSelection.value?.utcTimeMillis
val dayContentDescription = dayContentDescription(
rangeSelectionEnabled = rangeSelectionEnabled,
isToday = isToday,
@@ -1482,7 +1509,7 @@
// In the `Month` function above, the implementation checks whether the day is today and
// sets the content description differently.
modifier = modifier
- .minimumInteractiveComponentSize()
+ .minimumInteractiveComponentSize()
.requiredSize(
DatePickerModalTokens.DateStateLayerWidth,
DatePickerModalTokens.DateStateLayerHeight
@@ -1542,6 +1569,9 @@
} else {
colors.containerColor
}
+ val coroutineScope = rememberCoroutineScope()
+ val scrollToEarlierYearsLabel = getString(Strings.DatePickerScrollToShowEarlierYears)
+ val scrollToLaterYearsLabel = getString(Strings.DatePickerScrollToShowLaterYears)
LazyVerticalGrid(
columns = GridCells.Fixed(YearsInRow),
modifier = modifier
@@ -1562,7 +1592,24 @@
.requiredSize(
width = DatePickerModalTokens.SelectionYearContainerWidth,
height = DatePickerModalTokens.SelectionYearContainerHeight
- ),
+ )
+ .semantics {
+ // Apply a11y custom actions to the first and last items in the years
+ // grid. The actions will suggest to scroll to earlier or later years in
+ // the grid.
+ customActions = if (lazyGridState.firstVisibleItemIndex == it ||
+ lazyGridState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == it
+ ) {
+ customScrollActions(
+ state = lazyGridState,
+ coroutineScope = coroutineScope,
+ scrollUpLabel = scrollToEarlierYearsLabel,
+ scrollDownLabel = scrollToLaterYearsLabel
+ )
+ } else {
+ emptyList()
+ }
+ },
selected = selectedYear == displayedYear,
currentYear = selectedYear == currentYear,
onClick = { onYearSelected(selectedYear) },
@@ -1721,10 +1768,48 @@
}
}
+private fun customScrollActions(
+ state: LazyGridState,
+ coroutineScope: CoroutineScope,
+ scrollUpLabel: String,
+ scrollDownLabel: String
+): List<CustomAccessibilityAction> {
+ val scrollUpAction = {
+ if (!state.canScrollBackward) {
+ false
+ } else {
+ coroutineScope.launch {
+ state.scrollToItem(state.firstVisibleItemIndex - YearsInRow)
+ }
+ true
+ }
+ }
+ val scrollDownAction = {
+ if (!state.canScrollForward) {
+ false
+ } else {
+ coroutineScope.launch {
+ state.scrollToItem(state.firstVisibleItemIndex + YearsInRow)
+ }
+ true
+ }
+ }
+ return listOf(
+ CustomAccessibilityAction(
+ label = scrollUpLabel,
+ action = scrollUpAction
+ ),
+ CustomAccessibilityAction(
+ label = scrollDownLabel,
+ action = scrollDownAction
+ )
+ )
+}
+
/**
* Returns a string representation of an integer at the current Locale.
*/
-private fun Int.toLocalString(): String {
+internal fun Int.toLocalString(): String {
val formatter = NumberFormat.getIntegerInstance()
// Eliminate any use of delimiters when formatting the integer.
formatter.isGroupingUsed = false
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangeInput.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangeInput.kt
new file mode 100644
index 0000000..19f4293
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangeInput.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 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.compose.material3
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal fun DateRangeInputContent(
+ stateData: StateData,
+ dateFormatter: DatePickerFormatter,
+ dateValidator: (Long) -> Boolean,
+) {
+ // Obtain the DateInputFormat for the default Locale.
+ val defaultLocale = defaultLocale()
+ val dateInputFormat = remember(defaultLocale) {
+ stateData.calendarModel.getDateInputFormat(defaultLocale)
+ }
+ val errorDatePattern = getString(Strings.DateInputInvalidForPattern)
+ val errorDateOutOfYearRange = getString(Strings.DateInputInvalidYearRange)
+ val errorInvalidNotAllowed = getString(Strings.DateInputInvalidNotAllowed)
+ val errorInvalidRange = getString(Strings.DateRangeInputInvalidRangeInput)
+ val dateInputValidator = remember(dateInputFormat, dateFormatter) {
+ DateInputValidator(
+ stateData = stateData,
+ dateInputFormat = dateInputFormat,
+ dateFormatter = dateFormatter,
+ dateValidator = dateValidator,
+ errorDatePattern = errorDatePattern,
+ errorDateOutOfYearRange = errorDateOutOfYearRange,
+ errorInvalidNotAllowed = errorInvalidNotAllowed,
+ errorInvalidRangeInput = errorInvalidRange
+ )
+ }
+ Row(
+ modifier = Modifier.padding(paddingValues = InputTextFieldPadding),
+ horizontalArrangement = Arrangement.spacedBy(TextFieldSpacing)
+ ) {
+ DateInputTextField(
+ modifier = Modifier.weight(0.5f),
+ stateData = stateData,
+ initialDate = stateData.selectedStartDate.value,
+ onDateChanged = { date -> stateData.selectedStartDate.value = date },
+ inputIdentifier = InputIdentifier.StartDateInput,
+ dateInputValidator = dateInputValidator,
+ dateInputFormat = dateInputFormat,
+ locale = defaultLocale
+ )
+ DateInputTextField(
+ modifier = Modifier.weight(0.5f),
+ stateData = stateData,
+ initialDate = stateData.selectedEndDate.value,
+ onDateChanged = { date -> stateData.selectedEndDate.value = date },
+ inputIdentifier = InputIdentifier.EndDateInput,
+ dateInputValidator = dateInputValidator,
+ dateInputFormat = dateInputFormat,
+ locale = defaultLocale
+ )
+ }
+}
+
+private val TextFieldSpacing = 8.dp
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
index e855829..c8d83ef 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
@@ -16,6 +16,9 @@
package androidx.compose.material3
+import androidx.compose.animation.Crossfade
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -31,6 +34,7 @@
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
@@ -41,12 +45,20 @@
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
+import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.LiveRegionMode
+import androidx.compose.ui.semantics.ScrollAxisRange
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.customActions
+import androidx.compose.ui.semantics.isContainer
import androidx.compose.ui.semantics.liveRegion
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.verticalScrollAxisRange
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
/**
* <a href="https://m3.material.io/components/date-pickers/overview" class="external" target="_blank">Material Design date range picker</a>.
@@ -63,6 +75,8 @@
* one for selection. Invalid dates will appear disabled in the UI.
* @param title the title to be displayed in the date range picker
* @param headline the headline to be displayed in the date range picker
+ * @param showModeToggle indicates if this DateRangePicker should show a mode toggle action that
+ * transforms it into a date range input
* @param colors [DatePickerColors] that will be used to resolve the colors used for this date
* range picker in different states. See [DatePickerDefaults.colors].
*/
@@ -82,14 +96,27 @@
dateFormatter
)
},
+ showModeToggle: Boolean = true,
colors: DatePickerColors = DatePickerDefaults.colors()
) {
DateEntryContainer(
modifier = modifier,
title = title,
headline = headline,
- // TODO(b/245821979): Add showModeToggle param and us it here for DateEntryModeToggleButton
- modeToggleButton = null,
+ modeToggleButton = if (showModeToggle) {
+ {
+ DisplayModeToggleButton(
+ displayMode = state.displayMode,
+ onDisplayModeChange = { displayMode ->
+ state.stateData.switchDisplayMode(
+ displayMode
+ )
+ }
+ )
+ }
+ } else {
+ null
+ },
headlineTextStyle = MaterialTheme.typography.fromToken(
DatePickerModalTokens.RangeSelectionHeaderHeadlineFont
),
@@ -98,9 +125,8 @@
headerContentPadding = DateRangePickerHeaderPadding,
colors = colors
) {
- // TODO(b/245821979): Implement using a SwitchableDateEntryContent similar to the DatePicker
- DateRangePickerContent(
- stateData = state.stateData,
+ SwitchableDateEntryContent(
+ state = state,
dateFormatter = dateFormatter,
dateValidator = dateValidator,
colors = colors
@@ -200,7 +226,7 @@
*/
@get:Suppress("AutoBoxing")
val selectedStartDateMillis by derivedStateOf {
- stateData.selectedStartDate?.utcTimeMillis
+ stateData.selectedStartDate.value?.utcTimeMillis
}
/**
@@ -213,7 +239,7 @@
*/
@get:Suppress("AutoBoxing")
val selectedEndDateMillis by derivedStateOf {
- stateData.selectedEndDate?.utcTimeMillis
+ stateData.selectedEndDate.value?.utcTimeMillis
}
/**
@@ -335,19 +361,19 @@
with(state.stateData) {
val defaultLocale = defaultLocale()
val formatterStartDate = dateFormatter.formatDate(
- date = selectedStartDate,
+ date = selectedStartDate.value,
calendarModel = calendarModel,
locale = defaultLocale
)
val formatterEndDate = dateFormatter.formatDate(
- date = selectedEndDate,
+ date = selectedEndDate.value,
calendarModel = calendarModel,
locale = defaultLocale
)
val verboseStartDateDescription = dateFormatter.formatDate(
- date = selectedStartDate,
+ date = selectedStartDate.value,
calendarModel = calendarModel,
locale = defaultLocale,
forContentDescription = true
@@ -358,7 +384,7 @@
}
val verboseEndDateDescription = dateFormatter.formatDate(
- date = selectedEndDate,
+ date = selectedEndDate.value,
calendarModel = calendarModel,
locale = defaultLocale,
forContentDescription = true
@@ -397,6 +423,41 @@
}
}
+/**
+ * Date entry content that displays a [DateRangePickerContent] or a [DateRangeInputContent]
+ * according to the state's display mode.
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun SwitchableDateEntryContent(
+ state: DateRangePickerState,
+ dateFormatter: DatePickerFormatter,
+ dateValidator: (Long) -> Boolean,
+ colors: DatePickerColors
+) {
+ // TODO(b/266480386): Apply the motion spec for this once we have it. Consider replacing this
+ // with AnimatedContent when it's out of experimental.
+ Crossfade(
+ targetState = state.displayMode,
+ animationSpec = spring(),
+ modifier = Modifier.semantics { isContainer = true }) { mode ->
+ when (mode) {
+ DisplayMode.Picker -> DateRangePickerContent(
+ stateData = state.stateData,
+ dateFormatter = dateFormatter,
+ dateValidator = dateValidator,
+ colors = colors
+ )
+
+ DisplayMode.Input -> DateRangeInputContent(
+ stateData = state.stateData,
+ dateFormatter = dateFormatter,
+ dateValidator = dateValidator,
+ )
+ }
+ }
+}
+
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DateRangePickerContent(
@@ -452,7 +513,17 @@
DatePickerModalTokens.RangeSelectionMonthSubheadFont
)
) {
- LazyColumn(state = lazyListState) {
+ val coroutineScope = rememberCoroutineScope()
+ val scrollToPreviousMonthLabel = getString(Strings.DateRangePickerScrollToShowPreviousMonth)
+ val scrollToNextMonthLabel = getString(Strings.DateRangePickerScrollToShowNextMonth)
+ LazyColumn(
+ // Apply this to have the screen reader traverse outside the visible list of months
+ // and not scroll them by default.
+ modifier = Modifier.semantics {
+ verticalScrollAxisRange = ScrollAxisRange(value = { 0f }, maxValue = { 0f })
+ },
+ state = lazyListState
+ ) {
items(stateData.totalMonthsInRange) {
val month =
stateData.calendarModel.plusMonths(
@@ -468,7 +539,17 @@
stateData.calendarModel,
defaultLocale()
) ?: "-",
- modifier = Modifier.padding(paddingValues = CalendarMonthSubheadPadding),
+ modifier = Modifier
+ .padding(paddingValues = CalendarMonthSubheadPadding)
+ .clickable { /* no-op (needed for customActions to operate */ }
+ .semantics {
+ customActions = customScrollActions(
+ state = lazyListState,
+ coroutineScope = coroutineScope,
+ scrollUpLabel = scrollToPreviousMonthLabel,
+ scrollDownLabel = scrollToNextMonthLabel
+ )
+ },
color = colors.subheadContentColor
)
Month(
@@ -497,17 +578,17 @@
) {
with(stateData) {
val date = calendarModel.getCanonicalDate(dateInMillis)
- val currentStart = selectedStartDate
- val currentEnd = selectedEndDate
+ val currentStart = selectedStartDate.value
+ val currentEnd = selectedEndDate.value
if ((currentStart == null && currentEnd == null) ||
(currentStart != null && currentEnd != null) ||
(currentStart != null && date < currentStart)
) {
// Reset the selection to "start" only.
- selectedStartDate = date
- selectedEndDate = null
+ selectedStartDate.value = date
+ selectedEndDate.value = null
} else if (currentStart != null && date > currentStart) {
- selectedEndDate = date
+ selectedEndDate.value = date
}
}
}
@@ -650,6 +731,44 @@
}
}
+private fun customScrollActions(
+ state: LazyListState,
+ coroutineScope: CoroutineScope,
+ scrollUpLabel: String,
+ scrollDownLabel: String
+): List<CustomAccessibilityAction> {
+ val scrollUpAction = {
+ if (!state.canScrollBackward) {
+ false
+ } else {
+ coroutineScope.launch {
+ state.scrollToItem(state.firstVisibleItemIndex - 1)
+ }
+ true
+ }
+ }
+ val scrollDownAction = {
+ if (!state.canScrollForward) {
+ false
+ } else {
+ coroutineScope.launch {
+ state.scrollToItem(state.firstVisibleItemIndex + 1)
+ }
+ true
+ }
+ }
+ return listOf(
+ CustomAccessibilityAction(
+ label = scrollUpLabel,
+ action = scrollUpAction
+ ),
+ CustomAccessibilityAction(
+ label = scrollDownLabel,
+ action = scrollDownAction
+ )
+ )
+}
+
// Base header paddings that are used for the header part (title + headline). Note that for the
// range picker default title and headline we add additional start padding. The additional paddings
// are added there to allow more flexibility when those composables are provided by a developer.
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
index c2d0a66..2b4c752 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
@@ -50,29 +50,34 @@
val DatePickerHeadlineDescription = Strings(21)
val DatePickerNoSelectionDescription = Strings(22)
val DatePickerTodayDescription = Strings(23)
- val DateInputTitle = Strings(24)
- val DateInputHeadline = Strings(25)
- val DateInputLabel = Strings(26)
- val DateInputHeadlineDescription = Strings(27)
- val DateInputNoInputDescription = Strings(28)
- val DateInputInvalidNotAllowed = Strings(29)
- val DateInputInvalidForPattern = Strings(30)
- val DateInputInvalidYearRange = Strings(31)
- val DatePickerSwitchToCalendarMode = Strings(32)
- val DatePickerSwitchToInputMode = Strings(33)
- val DateRangePickerTitle = Strings(34)
- val DateRangePickerStartHeadline = Strings(35)
- val DateRangePickerEndHeadline = Strings(36)
- val DateRangeInputTitle = Strings(37)
- val TooltipLongPressLabel = Strings(38)
- val TimePickerAM = Strings(39)
- val TimePickerPM = Strings(40)
- val TimePickerPeriodToggle = Strings(41)
- val TimePickerHourSelection = Strings(42)
- val TimePickerMinuteSelection = Strings(43)
- val TimePickerHourSuffix = Strings(44)
- val TimePicker24HourSuffix = Strings(45)
- val TimePickerMinuteSuffix = Strings(46)
+ val DatePickerScrollToShowLaterYears = Strings(24)
+ val DatePickerScrollToShowEarlierYears = Strings(25)
+ val DateInputTitle = Strings(26)
+ val DateInputHeadline = Strings(27)
+ val DateInputLabel = Strings(28)
+ val DateInputHeadlineDescription = Strings(29)
+ val DateInputNoInputDescription = Strings(30)
+ val DateInputInvalidNotAllowed = Strings(31)
+ val DateInputInvalidForPattern = Strings(32)
+ val DateInputInvalidYearRange = Strings(33)
+ val DatePickerSwitchToCalendarMode = Strings(34)
+ val DatePickerSwitchToInputMode = Strings(35)
+ val DateRangePickerTitle = Strings(36)
+ val DateRangePickerStartHeadline = Strings(37)
+ val DateRangePickerEndHeadline = Strings(38)
+ val DateRangePickerScrollToShowNextMonth = Strings(39)
+ val DateRangePickerScrollToShowPreviousMonth = Strings(40)
+ val DateRangeInputTitle = Strings(41)
+ val DateRangeInputInvalidRangeInput = Strings(42)
+ val TooltipLongPressLabel = Strings(43)
+ val TimePickerAM = Strings(44)
+ val TimePickerPM = Strings(45)
+ val TimePickerPeriodToggle = Strings(46)
+ val TimePickerHourSelection = Strings(47)
+ val TimePickerMinuteSelection = Strings(48)
+ val TimePickerHourSuffix = Strings(49)
+ val TimePicker24HourSuffix = Strings(50)
+ val TimePickerMinuteSuffix = Strings(51)
}
}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
index 302f4c8..841dd47 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
@@ -18,6 +18,7 @@
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
+import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
@@ -46,6 +47,7 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
@@ -245,30 +247,33 @@
}
}
- Box {
- Popup(
- popupPositionProvider = tooltipPositionProvider,
- onDismissRequest = {
- if (tooltipState.isVisible) {
- coroutineScope.launch { tooltipState.dismiss() }
+ Box(contentAlignment = Alignment.TopCenter) {
+ val transition = updateTransition(tooltipState.isVisible, label = "Tooltip transition")
+ if (transition.currentState || transition.targetState) {
+ Popup(
+ popupPositionProvider = tooltipPositionProvider,
+ onDismissRequest = {
+ if (tooltipState.isVisible) {
+ coroutineScope.launch { tooltipState.dismiss() }
+ }
}
+ ) {
+ Surface(
+ modifier = modifier
+ .sizeIn(
+ minWidth = TooltipMinWidth,
+ maxWidth = maxWidth,
+ minHeight = TooltipMinHeight
+ )
+ .animateTooltip(transition)
+ .focusable()
+ .semantics { liveRegion = LiveRegionMode.Polite },
+ shape = shape,
+ color = containerColor,
+ shadowElevation = elevation,
+ content = tooltipContent
+ )
}
- ) {
- Surface(
- modifier = modifier
- .sizeIn(
- minWidth = TooltipMinWidth,
- maxWidth = maxWidth,
- minHeight = TooltipMinHeight
- )
- .animateTooltip(tooltipState.isVisible)
- .focusable()
- .semantics { liveRegion = LiveRegionMode.Polite },
- shape = shape,
- color = containerColor,
- shadowElevation = elevation,
- content = tooltipContent
- )
}
scope.content()
@@ -484,15 +489,13 @@
}
private fun Modifier.animateTooltip(
- showTooltip: Boolean
+ transition: Transition<Boolean>
): Modifier = composed(
inspectorInfo = debugInspectorInfo {
name = "animateTooltip"
- properties["showTooltip"] = showTooltip
+ properties["transition"] = transition
}
) {
- val transition = updateTransition(showTooltip, label = "Tooltip transition")
-
val scale by transition.animateFloat(
transitionSpec = {
if (false isTransitioningTo true) {
@@ -760,5 +763,5 @@
private val ActionLabelBottomPadding = 8.dp
internal const val TooltipDuration = 1500L
// No specification for fade in and fade out duration, so aligning it with the behavior for snack bar
-private const val TooltipFadeInDuration = 150
+internal const val TooltipFadeInDuration = 150
private const val TooltipFadeOutDuration = 75
\ No newline at end of file
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
index 6a51fad..b9161ce7 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
@@ -49,6 +49,8 @@
Strings.DatePickerHeadlineDescription -> "Current selection: %1$"
Strings.DatePickerNoSelectionDescription -> "None"
Strings.DatePickerTodayDescription -> "Today"
+ Strings.DatePickerScrollToShowLaterYears -> "Scroll to show later years"
+ Strings.DatePickerScrollToShowEarlierYears -> "Scroll to show earlier years"
Strings.DateInputTitle -> "Select date"
Strings.DateInputHeadline -> "Entered date"
Strings.DateInputLabel -> "Date"
@@ -62,7 +64,10 @@
Strings.DateRangePickerTitle -> "Select dates"
Strings.DateRangePickerStartHeadline -> "Start date"
Strings.DateRangePickerEndHeadline -> "End date"
+ Strings.DateRangePickerScrollToShowNextMonth -> "Scroll to show the next month"
+ Strings.DateRangePickerScrollToShowPreviousMonth -> "Scroll to show the previous month"
Strings.DateRangeInputTitle -> "Enter dates"
+ Strings.DateRangeInputInvalidRangeInput -> "Invalid date range input"
Strings.TooltipLongPressLabel -> "Show tooltip"
Strings.TimePickerAM -> "AM"
Strings.TimePickerPM -> "PM"
diff --git a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
index edc16ae..bd97ea2 100644
--- a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
+++ b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class RuntimeIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ComposableCoroutineCreationDetector.CoroutineCreationDuringComposition,
diff --git a/compose/runtime/runtime-livedata/src/androidTest/java/androidx/compose/runtime/livedata/LiveDataAdapterTest.kt b/compose/runtime/runtime-livedata/src/androidTest/java/androidx/compose/runtime/livedata/LiveDataAdapterTest.kt
index 352ea84..9733e52 100644
--- a/compose/runtime/runtime-livedata/src/androidTest/java/androidx/compose/runtime/livedata/LiveDataAdapterTest.kt
+++ b/compose/runtime/runtime-livedata/src/androidTest/java/androidx/compose/runtime/livedata/LiveDataAdapterTest.kt
@@ -63,6 +63,21 @@
}
@Test
+ fun preferInitializedValueInFirstComposition() {
+ val liveData = MutableLiveData("value")
+ var firstComposition by mutableStateOf(true)
+ var realValue: String? = null
+ rule.setContent {
+ if (firstComposition) {
+ realValue = liveData.observeAsState("initial").value
+ firstComposition = false
+ }
+ }
+
+ assertThat(realValue).isEqualTo("value")
+ }
+
+ @Test
fun weReceiveUpdates() {
val liveData = MutableLiveData<String>()
liveData.postValue("value")
diff --git a/compose/runtime/runtime-livedata/src/main/java/androidx/compose/runtime/livedata/LiveDataAdapter.kt b/compose/runtime/runtime-livedata/src/main/java/androidx/compose/runtime/livedata/LiveDataAdapter.kt
index 289a4d0..e077036 100644
--- a/compose/runtime/runtime-livedata/src/main/java/androidx/compose/runtime/livedata/LiveDataAdapter.kt
+++ b/compose/runtime/runtime-livedata/src/main/java/androidx/compose/runtime/livedata/LiveDataAdapter.kt
@@ -45,6 +45,10 @@
* be new value posted into the [LiveData] the returned [State] will be updated causing
* recomposition of every [State.value] usage.
*
+ * The [initial] value will be used only if this LiveData is not already
+ * [initialized][isInitialized]. Note that if [T] is a non-null type, it is your
+ * responsibility to ensure that any value you set on this LiveData is also non-null.
+ *
* The inner observer will automatically be removed when this composable disposes or the current
* [LifecycleOwner] moves to the [Lifecycle.State.DESTROYED] state.
*
@@ -53,7 +57,10 @@
@Composable
fun <R, T : R> LiveData<T>.observeAsState(initial: R): State<R> {
val lifecycleOwner = LocalLifecycleOwner.current
- val state = remember { mutableStateOf(initial) }
+ val state = remember {
+ @Suppress("UNCHECKED_CAST") /* Initialized values of a LiveData<T> must be a T */
+ mutableStateOf(if (isInitialized) value as T else initial)
+ }
DisposableEffect(this, lifecycleOwner) {
val observer = Observer<T> { state.value = it }
observe(lifecycleOwner, observer)
diff --git a/compose/runtime/runtime-saveable-lint/src/main/java/androidx/compose/runtime/saveable/lint/RuntimeSaveableIssueRegistry.kt b/compose/runtime/runtime-saveable-lint/src/main/java/androidx/compose/runtime/saveable/lint/RuntimeSaveableIssueRegistry.kt
index 60bbfa0..ce3e102 100644
--- a/compose/runtime/runtime-saveable-lint/src/main/java/androidx/compose/runtime/saveable/lint/RuntimeSaveableIssueRegistry.kt
+++ b/compose/runtime/runtime-saveable-lint/src/main/java/androidx/compose/runtime/saveable/lint/RuntimeSaveableIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class RuntimeSaveableIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
RememberSaveableDetector.RememberSaveableSaverParameter
diff --git a/compose/ui/ui-graphics-lint/src/main/java/androidx/compose/ui/graphics/lint/UiGraphicsIssueRegistry.kt b/compose/ui/ui-graphics-lint/src/main/java/androidx/compose/ui/graphics/lint/UiGraphicsIssueRegistry.kt
index 065492c4..bff18de 100644
--- a/compose/ui/ui-graphics-lint/src/main/java/androidx/compose/ui/graphics/lint/UiGraphicsIssueRegistry.kt
+++ b/compose/ui/ui-graphics-lint/src/main/java/androidx/compose/ui/graphics/lint/UiGraphicsIssueRegistry.kt
@@ -25,7 +25,7 @@
*/
class UiGraphicsIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ColorDetector.MissingColorAlphaChannel,
diff --git a/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/UiIssueRegistry.kt b/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/UiIssueRegistry.kt
index d296f22..1a5b343 100644
--- a/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/UiIssueRegistry.kt
+++ b/compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/UiIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class UiIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ComposedModifierDetector.UnnecessaryComposedModifier,
diff --git a/compose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/TestManifestIssueRegistry.kt b/compose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/TestManifestIssueRegistry.kt
index a0b10da..5879da0b 100644
--- a/compose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/TestManifestIssueRegistry.kt
+++ b/compose/ui/ui-test-manifest-lint/src/main/java/androidx/compose/ui/test/manifest/lint/TestManifestIssueRegistry.kt
@@ -21,7 +21,7 @@
import com.android.tools.lint.detector.api.CURRENT_API
class TestManifestIssueRegistry : IssueRegistry() {
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(GradleDebugConfigurationDetector.ISSUE)
override val vendor = Vendor(
diff --git a/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutComposeIssueRegistry.kt b/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutComposeIssueRegistry.kt
index f81e031..1aa437d 100644
--- a/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutComposeIssueRegistry.kt
+++ b/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutComposeIssueRegistry.kt
@@ -25,12 +25,14 @@
private const val CL_COMPOSE_NEW_ISSUE = "new?component=323867&template=1023345"
class ConstraintLayoutComposeIssueRegistry : IssueRegistry() {
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues = listOf(
- ConstraintLayoutDslDetector.IncorrectReferencesDeclarationIssue
+ ConstraintLayoutDslDetector.IncorrectReferencesDeclarationIssue,
+ ConstraintLayoutDslDetector.IncorrectMatchParentUsageIssue,
+ ConstraintLayoutDslDetector.IncorrectChainMarginsUsageIssue
)
override val vendor = Vendor(
diff --git a/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutDslDetector.kt b/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutDslDetector.kt
index 647017d..81058d4 100644
--- a/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutDslDetector.kt
+++ b/constraintlayout/constraintlayout-compose-lint/src/main/java/androidx/constraintlayout/compose/lint/ConstraintLayoutDslDetector.kt
@@ -24,32 +24,231 @@
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.LintFix
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.UastLintUtils.Companion.tryResolveUDeclaration
import java.util.EnumSet
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
+import org.jetbrains.uast.UBinaryExpression
+import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UExpression
+import org.jetbrains.uast.ULambdaExpression
+import org.jetbrains.uast.UQualifiedReferenceExpression
+import org.jetbrains.uast.USimpleNameReferenceExpression
+import org.jetbrains.uast.getContainingUClass
+import org.jetbrains.uast.getParentOfType
+import org.jetbrains.uast.visitor.UastVisitor
+
+private const val CREATE_REFS_FOR_NAME = "createRefsFor"
+private const val MATCH_PARENT_NAME = "matchParent"
+private const val LINK_TO_NAME = "linkTo"
+private const val CENTER_TO_NAME = "centerTo"
+private const val CENTER_HORIZONTALLY_TO_NAME = "centerHorizontallyTo"
+private const val CENTER_VERTICALLY_TO_NAME = "centerVerticallyTo"
+private const val WIDTH_NAME = "width"
+private const val HEIGHT_NAME = "height"
+private const val PARENT_NAME = "parent"
+private const val CONSTRAIN_NAME = "constrain"
+private const val MARGIN_INDEX_IN_LINK_TO = 1
+private const val GONE_MARGIN_INDEX_IN_LINK_TO = 2
+private const val CREATE_HORIZONTAL_CHAIN_NAME = "createHorizontalChain"
+private const val CREATE_VERTICAL_CHAIN_NAME = "createVerticalChain"
+private const val WITH_CHAIN_PARAMS_NAME = "withChainParams"
+private const val CHAIN_PARAM_START_MARGIN_NAME = "startMargin"
+private const val CHAIN_PARAM_TOP_MARGIN_NAME = "topMargin"
+private const val CHAIN_PARAM_END_MARGIN_NAME = "endMargin"
+private const val CHAIN_PARAM_BOTTOM_MARGIN_NAME = "bottomMargin"
+private const val CHAIN_PARAM_START_GONE_MARGIN_NAME = "startGoneMargin"
+private const val CHAIN_PARAM_TOP_GONE_MARGIN_NAME = "topGoneMargin"
+private const val CHAIN_PARAM_END_GONE_MARGIN_NAME = "endGoneMargin"
+private const val CHAIN_PARAM_BOTTOM_GONE_MARGIN_NAME = "bottomGoneMargin"
+
+private const val CL_COMPOSE_DIMENSION_CLASS_NAME = "Dimension"
+
+private const val DIMENSION_MATCH_PARENT_EXPRESSION_NAME =
+ "$CL_COMPOSE_DIMENSION_CLASS_NAME.$MATCH_PARENT_NAME"
private const val CL_COMPOSE_PACKAGE = "androidx.constraintlayout.compose"
private const val CONSTRAINT_SET_SCOPE_CLASS_FQ = "$CL_COMPOSE_PACKAGE.ConstraintSetScope"
private const val MOTION_SCENE_SCOPE_CLASS_FQ = "$CL_COMPOSE_PACKAGE.MotionSceneScope"
-private const val CREATE_REFS_FOR_NAME = "createRefsFor"
+private const val CONSTRAIN_SCOPE_CLASS_FQ = "$CL_COMPOSE_PACKAGE.ConstrainScope"
+private const val CONSTRAINED_LAYOUT_REFERENCE_CLASS_FQ =
+ "$CL_COMPOSE_PACKAGE.ConstrainedLayoutReference"
+private const val LAYOUT_REFERENCE_CLASS_FQ = "$CL_COMPOSE_PACKAGE.LayoutReference"
-class ConstraintLayoutDslDetector : Detector(), SourceCodeScanner {
- private val knownOwnersOfCreateRefsFor = setOf(
+private val knownOwnersOfCreateRefsFor by lazy(LazyThreadSafetyMode.NONE) {
+ setOf(
CONSTRAINT_SET_SCOPE_CLASS_FQ,
MOTION_SCENE_SCOPE_CLASS_FQ
)
+}
- override fun getApplicableUastTypes() = listOf(UCallExpression::class.java)
+private val horizontalConstraintAnchors by lazy(LazyThreadSafetyMode.NONE) {
+ setOf(
+ "start",
+ "end",
+ "absoluteLeft",
+ "absoluteRight"
+ )
+}
+
+private val verticalConstraintAnchors by lazy(LazyThreadSafetyMode.NONE) {
+ setOf(
+ "top",
+ "bottom",
+ )
+}
+
+private val horizontalCenterMethodNames by lazy(LazyThreadSafetyMode.NONE) {
+ setOf(
+ CENTER_TO_NAME,
+ CENTER_HORIZONTALLY_TO_NAME,
+ )
+}
+
+private val verticalCenterMethodNames by lazy(LazyThreadSafetyMode.NONE) {
+ setOf(
+ CENTER_TO_NAME,
+ CENTER_VERTICALLY_TO_NAME,
+ )
+}
+
+class ConstraintLayoutDslDetector : Detector(), SourceCodeScanner {
+
+ // TODO: Add a case to detect use cases for `ConstrainedLayoutReference.withChainParams()`
+
+ override fun getApplicableUastTypes() =
+ listOf(UCallExpression::class.java, UBinaryExpression::class.java)
override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
+
+ /**
+ * Binary expressions are of the form `foo = bar`.
+ */
+ override fun visitBinaryExpression(node: UBinaryExpression) {
+ val assignedReferenceText = node.rightOperand.sourcePsi?.text ?: return
+
+ when (assignedReferenceText) {
+ DIMENSION_MATCH_PARENT_EXPRESSION_NAME -> detectMatchParentUsage(node)
+ }
+ }
+
override fun visitCallExpression(node: UCallExpression) {
- if (node.methodName != CREATE_REFS_FOR_NAME) {
+ when (node.methodName) {
+ CREATE_REFS_FOR_NAME -> detectCreateRefsForUsage(node)
+ CREATE_HORIZONTAL_CHAIN_NAME -> detectChainParamsUsage(node, true)
+ CREATE_VERTICAL_CHAIN_NAME -> detectChainParamsUsage(node, false)
+ // TODO: Detect that `withChainParams` is not called after chains are created
+ }
+ }
+
+ /**
+ * Verify correct usage of `Dimension.matchParent`.
+ *
+ *
+ *
+ * When using `Dimension.matchParent`, the user must be careful to not have custom
+ * constraints that result in different behavior from `centerTo(parent)`, otherwise, they
+ * should use `Dimension.percent(1f)` instead.
+ * ```
+ * val (text, button) = createRefsFor("text", "button")
+ * constrain(text) {
+ * width = Dimension.matchParent
+ *
+ * // Correct
+ * start.linkTo(parent.start)
+ * centerTo(parent)
+ * centerHorizontallyTo(parent)
+ *
+ * // Incorrect
+ * start.linkTo(parent.end)
+ * start.linkTo(button.start)
+ * centerHorizontallyTo(button)
+ * centerTo(button)
+ * }
+ * ```
+ *
+ */
+ private fun detectMatchParentUsage(node: UBinaryExpression) {
+ val assigneeNode = node.leftOperand
+ val assigneeName = assigneeNode.sourcePsi?.text ?: return
+
+ // Must be assigned to either `width` or `height`
+ val isHorizontal: Boolean = when (assigneeName) {
+ WIDTH_NAME -> true
+ HEIGHT_NAME -> false
+ else -> return
+ }
+
+ // Verify that the context of this Expression is within ConstrainScope
+ if (assigneeNode.tryResolveUDeclaration()
+ ?.getContainingUClass()?.qualifiedName != CONSTRAIN_SCOPE_CLASS_FQ
+ ) {
return
}
+
+ val containingBlock = node.getParentOfType<UBlockExpression>() ?: return
+
+ // Within the Block, look for expressions supported for the check and immediately return
+ // if any of those expressions indicate bad usage of `Dimension.matchParent`
+ val containsErrorProneUsage = containingBlock.expressions.asSequence()
+ .mapNotNull { expression ->
+ EvaluateableExpression.createForMatchParentUsage(
+ expression = expression,
+ isHorizontal = isHorizontal
+ )
+ }
+ .any(EvaluateableExpression::isErrorProneForMatchParentUsage)
+
+ if (!containsErrorProneUsage) {
+ return
+ }
+
+ val overrideMethodName =
+ if (isHorizontal) CENTER_HORIZONTALLY_TO_NAME else CENTER_VERTICALLY_TO_NAME
+
+ context.report(
+ issue = IncorrectMatchParentUsageIssue,
+ scope = node.rightOperand,
+ location = context.getNameLocation(node.rightOperand),
+ message = "`Dimension.matchParent` will override constraints to an equivalent of " +
+ "`$overrideMethodName(parent)`.\nUse `Dimension.percent(1f)` to respect " +
+ "constraints.",
+ quickfixData = LintFix.create()
+ .replace()
+ .name("Replace `matchParent` with `percent(1f)`.")
+ .range(context.getNameLocation(node.rightOperand))
+ .all()
+ .with("Dimension.percent(1f)")
+ .autoFix()
+ .build()
+ )
+ }
+
+ /**
+ * Verify correct usage of `createRefsFor("a", "b", "c")`.
+ *
+ *
+ *
+ * The number of assigned variables should match the number of given arguments:
+ * ```
+ * // Correct
+ * val (a, b, c) = createRefsFor("a", "b", "c")
+ *
+ * // Incorrect: Fewer variables than arguments
+ * val (a) = createRefsFor("a", "b", "c")
+ *
+ * // Incorrect: More variables than arguments
+ * val (a, b, c, d) = createRefsFor("a", "b", "c")
+ *
+ * ```
+ */
+ private fun detectCreateRefsForUsage(node: UCallExpression) {
val destructuringDeclarationElement =
node.sourcePsi?.getParentOfType<KtDestructuringDeclaration>(true) ?: return
@@ -84,6 +283,140 @@
"assigned variables ($varsReceived)"
)
}
+
+ /**
+ * Verify that margins for chains are applied correctly.
+ *
+ *
+ *
+ * Margins for elements in chains should be applied with `LayoutReference.withChainParams()`
+ * instinctively, users may want to create constraints with margins that mimic the chain
+ * behavior expecting those margins to be reflected in the chain. But that is not the
+ * correct way to do it.
+ *
+ * So this check detects when users create chain-like constraints, and suggests to use
+ * `withChainParams()` and delete conflicting constraints, keeping the intended margins.
+ *
+ *
+ *
+ * Example:
+ *
+ * Before
+ * ```
+ * val (button, text) = createRefs()
+ * createHorizontalChain(button, text)
+ *
+ * constrain(button) {
+ * end.linkTo(text.start, 8.dp)
+ * end.linkTo(text.start, goneMargin = 16.dp)
+ * }
+ * ```
+ *
+ * After
+ * ```
+ * val (button, text) = createRefs()
+ * createHorizontalChain(button.withChainParams(endMargin = 8.dp, endGoneMargin = 16.dp), text)
+ *
+ * constrain(button) {
+ * }
+ * ```
+ */
+ private fun detectChainParamsUsage(node: UCallExpression, isHorizontal: Boolean) {
+ // TODO(b/268213648): Don't attempt to fix chain elements that already have
+ // `withChainParams` that may have been defined elsewhere out of scope. A safe
+ // path to take would be to look for the layout reference declaration, and skip this
+ // check if it cannot be found within the current scope (code block). We could also try
+ // to search within the shared scope of the layout reference and chain declarations,
+ // but there's no straight-forward way to do it.
+
+ val containingBlock = node.getParentOfType<UBlockExpression>() ?: return
+
+ var previousNode: ChainNode? = null
+ val chainNodes = node.valueArguments
+ .filter(UExpression::isOfLayoutReferenceType)
+ .mapNotNull { argumentExpression ->
+ argumentExpression.findChildIdentifier()?.let { identifier ->
+ val chainNode = ChainNode(
+ expression = identifier,
+ hasChainParams = argumentExpression is UQualifiedReferenceExpression ||
+ containingBlock.isChainParamsCalledInIdentifier(identifier)
+ )
+ previousNode?.let { prevNode ->
+ chainNode.prev = prevNode
+ prevNode.next = chainNode
+ }
+ previousNode = chainNode
+ chainNode
+ }
+ }
+
+ val resolvedChainLikeConstraintsPerNode = chainNodes.map {
+ if (it.hasChainParams) {
+ emptyList()
+ } else {
+ findChainLikeConstraints(containingBlock, it, isHorizontal)
+ }
+ }
+ resolvedChainLikeConstraintsPerNode.forEachIndexed { index, chainLikeExpressions ->
+ val chainParamsBuilder = ChainParamsMethodBuilder()
+ val removeLinkToFixes = chainLikeExpressions.map { resolvedExpression ->
+ resolvedExpression.marginExpression?.let {
+ chainParamsBuilder.append(
+ resolvedExpression.marginParamName,
+ resolvedExpression.marginExpression
+ )
+ }
+ resolvedExpression.marginGoneExpression?.let {
+ chainParamsBuilder.append(
+ resolvedExpression.marginGoneParamName,
+ resolvedExpression.marginGoneExpression
+ )
+ }
+ val expressionToDelete =
+ resolvedExpression
+ .fullExpression
+ .getParentOfType<UQualifiedReferenceExpression>()
+ LintFix.create()
+ .replace()
+ .name("Remove conflicting `linkTo` declaration.")
+ .range(context.getLocation(expressionToDelete))
+ .all()
+ .with("")
+ .autoFix()
+ .build()
+ }
+ val chainNode = chainNodes[index]
+ if (!chainParamsBuilder.isEmpty() && removeLinkToFixes.isNotEmpty()) {
+ context.report(
+ issue = IncorrectChainMarginsUsageIssue,
+ scope = node,
+ location = context.getLocation(chainNode.expression.sourcePsi),
+ message = "Margins for elements in a Chain should be applied with " +
+ "`LayoutReference.withChainParams(...)`.",
+ quickfixData = LintFix.create()
+ .composite()
+ .name(
+ "Add `.withChainParams(...)` and remove " +
+ "(${removeLinkToFixes.size}) conflicting `linkTo` declarations."
+ )
+ // `join` might overwrite previously added fixes, so add grouped fixes
+ // first, then, add the remaining fixes individually with `add`
+ .join(*removeLinkToFixes.toTypedArray())
+ .add(
+ LintFix.create()
+ .replace()
+ .name("Add `.withChainParams(...)`.")
+ .range(context.getLocation(chainNode.expression.sourcePsi))
+ .end()
+ .with(chainParamsBuilder.build())
+ .autoFix()
+ .build()
+ )
+ .build()
+ )
+ }
+ }
+ }
}
companion object {
@@ -103,5 +436,328 @@
EnumSet.of(Scope.JAVA_FILE)
)
)
+
+ val IncorrectMatchParentUsageIssue = Issue.create(
+ id = "IncorrectMatchParentUsage",
+ briefDescription = "Prefer using `Dimension.percent(1f)` when defining custom " +
+ "constraints.",
+ explanation = "`Dimension.matchParent` forces the constraints to be an equivalent of " +
+ "`centerHorizontallyTo(parent)` or `centerVerticallyTo(parent)` according to the " +
+ "assigned dimension which can lead to unexpected behavior. To avoid that, prefer " +
+ "using `Dimension.percent(1f)`",
+ category = Category.CORRECTNESS,
+ priority = 5,
+ severity = Severity.WARNING,
+ implementation = Implementation(
+ ConstraintLayoutDslDetector::class.java,
+ EnumSet.of(Scope.JAVA_FILE)
+ )
+ )
+
+ val IncorrectChainMarginsUsageIssue = Issue.create(
+ id = "IncorrectChainMarginsUsage",
+ briefDescription = "Use `LayoutReference.withChainParams()` to define margins for " +
+ "elements in a Chain.",
+ explanation = "If you understand how a chain works, it might seem obvious to add " +
+ "margins by re-creating the constraints with the desired margin. However, in " +
+ "Compose, helpers will ignore custom constraints in favor of their layout " +
+ "implementation. So instead, use `LayoutReference.withChainParams()` " +
+ "to define margins for Chains.",
+ category = Category.CORRECTNESS,
+ priority = 5,
+ severity = Severity.WARNING,
+ implementation = Implementation(
+ ConstraintLayoutDslDetector::class.java,
+ EnumSet.of(Scope.JAVA_FILE)
+ )
+ )
}
+}
+
+internal class EvaluateableExpression(
+ private val expectedArgumentText: String,
+ private val expression: UCallExpression
+) {
+ /**
+ * Should only return `true` when we know for certain that there's wrong usage.
+ *
+ *
+ *
+ * E.g.: For the following snippet we can't know if usage is incorrect since we don't know what
+ * the variable `targetAnchor` represents.
+ * ```
+ * width = Dimension.matchParent
+ *
+ * var targetAnchor: HorizontalAnchor
+ * start.linkTo(targetAnchor)
+ * ```
+ */
+ fun isErrorProneForMatchParentUsage(): Boolean {
+ val argumentText = expression.valueArguments.firstOrNull()?.sourcePsi?.text ?: return false
+ return argumentText != expectedArgumentText
+ }
+
+ companion object {
+ fun createForMatchParentUsage(
+ expression: UExpression,
+ isHorizontal: Boolean
+ ): EvaluateableExpression? {
+ if (expression is UQualifiedReferenceExpression) {
+ // For the form of `start.linkTo(parent.start)`
+
+ val callExpression = (expression.selector as? UCallExpression) ?: return null
+ if (callExpression.methodName != LINK_TO_NAME) {
+ return null
+ }
+ val receiverAnchorName = expression.receiver.sourcePsi?.text ?: return null
+ val supportedAnchors =
+ if (isHorizontal) horizontalConstraintAnchors else verticalConstraintAnchors
+ if (!supportedAnchors.contains(receiverAnchorName)) {
+ return null
+ }
+ return EvaluateableExpression(
+ expectedArgumentText = "$PARENT_NAME.$receiverAnchorName",
+ expression = callExpression
+ )
+ } else if (expression is UCallExpression) {
+ // For the form of `centerTo(parent)`
+
+ val supportedMethodNames =
+ if (isHorizontal) horizontalCenterMethodNames else verticalCenterMethodNames
+ val methodName = expression.methodName ?: return null
+ if (!supportedMethodNames.contains(methodName)) {
+ return null
+ }
+ return EvaluateableExpression(
+ expectedArgumentText = PARENT_NAME,
+ expression = expression
+ )
+ }
+ return null
+ }
+ }
+}
+
+internal fun findChainLikeConstraints(
+ constraintSetBlock: UBlockExpression,
+ chainNode: ChainNode,
+ isHorizontal: Boolean
+): List<ResolvedChainLikeExpression> {
+ val identifier = chainNode.expression
+ val constrainTargetExpressions = constraintSetBlock.expressions.filter { cSetExpression ->
+ cSetExpression is UCallExpression && cSetExpression.methodName == CONSTRAIN_NAME &&
+ cSetExpression.valueArguments.any { argument ->
+ argument.sourcePsi?.text == identifier.identifier
+ }
+ }
+
+ val expectedAnchors =
+ if (isHorizontal) horizontalConstraintAnchors else verticalConstraintAnchors
+
+ return constrainTargetExpressions.asSequence().mapNotNull { constrainExpression ->
+ (constrainExpression as? UCallExpression)
+ ?.valueArguments
+ ?.filterIsInstance<ULambdaExpression>()
+ ?.lastOrNull()?.body as? UBlockExpression
+ }.flatMap {
+ it.expressions
+ }.filterIsInstance<UQualifiedReferenceExpression>().map {
+ it.selector
+ }.filterIsInstance<UCallExpression>().filter {
+ // No point in considering it if there's no margins applied
+ it.methodName == LINK_TO_NAME && it.valueArgumentCount >= 2
+ }.mapNotNull {
+ it.receiver?.sourcePsi?.text?.let { anchorName ->
+ if (expectedAnchors.contains(anchorName)) {
+ Pair(it, anchorName)
+ } else {
+ null
+ }
+ }
+ }.mapNotNull { (linkCallExpression, anchorName) ->
+ val nextIdentifier = chainNode.next?.expression?.identifier
+ val isNextParent = nextIdentifier == null
+
+ val prevIdentifier = chainNode.prev?.expression?.identifier
+ val isPrevParent = prevIdentifier == null
+ val expectedNextAnchorTo =
+ if (isNextParent) {
+ "parent.$anchorName"
+ } else {
+ "${nextIdentifier!!}.${anchorName.getOppositeAnchorName()}"
+ }
+ val expectedPrevAnchorTo =
+ if (isPrevParent) {
+ "parent.$anchorName"
+ } else {
+ "${prevIdentifier!!}.${anchorName.getOppositeAnchorName()}"
+ }
+
+ val targetAnchorExpressionText =
+ linkCallExpression.valueArguments[0].sourcePsi?.text
+ if (targetAnchorExpressionText == expectedPrevAnchorTo ||
+ targetAnchorExpressionText == expectedNextAnchorTo
+ ) {
+ ResolvedChainLikeExpression(
+ linkCallExpression,
+ anchorName,
+ linkCallExpression.getArgumentForParameter(MARGIN_INDEX_IN_LINK_TO),
+ linkCallExpression.getArgumentForParameter(GONE_MARGIN_INDEX_IN_LINK_TO)
+ )
+ } else {
+ null
+ }
+ }.toList()
+}
+
+internal class ChainNode(
+ val expression: USimpleNameReferenceExpression,
+ val hasChainParams: Boolean
+) {
+ var prev: ChainNode? = null
+ var next: ChainNode? = null
+}
+
+internal class ResolvedChainLikeExpression(
+ val fullExpression: UCallExpression,
+ anchorName: String,
+ val marginExpression: UExpression?,
+ val marginGoneExpression: UExpression?
+) {
+ val marginParamName: String = anchorName.asChainParamsArgument(false)
+ val marginGoneParamName: String = anchorName.asChainParamsArgument(true)
+}
+
+private fun String.getOppositeAnchorName() =
+ when (this) {
+ "start" -> "end"
+ "end" -> "start"
+ "absoluteLeft" -> "absoluteRight"
+ "absoluteRight" -> "absoluteLeft"
+ "top" -> "bottom"
+ "bottom" -> "top"
+ else -> "start"
+ }
+
+internal fun String.asChainParamsArgument(isGone: Boolean = false) =
+ if (!isGone) {
+ when (this) {
+ "absoluteLeft",
+ "start" -> CHAIN_PARAM_START_MARGIN_NAME
+
+ "absoluteRight",
+ "end" -> CHAIN_PARAM_END_MARGIN_NAME
+
+ "top" -> CHAIN_PARAM_TOP_MARGIN_NAME
+ "bottom" -> CHAIN_PARAM_BOTTOM_MARGIN_NAME
+ else -> CHAIN_PARAM_START_MARGIN_NAME
+ }
+ } else {
+ when (this) {
+ "absoluteLeft",
+ "start" -> CHAIN_PARAM_START_GONE_MARGIN_NAME
+
+ "absoluteRight",
+ "end" -> CHAIN_PARAM_END_GONE_MARGIN_NAME
+
+ "top" -> CHAIN_PARAM_TOP_GONE_MARGIN_NAME
+ "bottom" -> CHAIN_PARAM_BOTTOM_GONE_MARGIN_NAME
+ else -> CHAIN_PARAM_START_GONE_MARGIN_NAME
+ }
+ }
+
+internal fun UBlockExpression.isChainParamsCalledInIdentifier(
+ target: USimpleNameReferenceExpression
+): Boolean {
+ var found = false
+ this.accept(
+ object : UastVisitor {
+ override fun visitQualifiedReferenceExpression(
+ node: UQualifiedReferenceExpression
+ ): Boolean {
+ val identifier = (node.receiver as? USimpleNameReferenceExpression) ?: return true
+ if (identifier.identifier == target.identifier &&
+ identifier.getExpressionType() == target.getExpressionType()) {
+ val selector = node.selector
+ if (selector is UCallExpression &&
+ selector.methodName == WITH_CHAIN_PARAMS_NAME) {
+ found = true
+ } else {
+ // skip
+ return true
+ }
+ } else {
+ // skip
+ return true
+ }
+ return super.visitQualifiedReferenceExpression(node)
+ }
+
+ override fun visitElement(node: UElement): Boolean {
+ return found
+ }
+ }
+ )
+ return found
+}
+
+internal class ChainParamsMethodBuilder {
+ private val modificationMap = mutableMapOf<String, UExpression>()
+
+ fun append(paramName: String, paramExpression: UExpression) {
+ modificationMap[paramName] = paramExpression
+ }
+
+ fun isEmpty() = modificationMap.isEmpty()
+
+ fun build(): String =
+ StringBuilder().apply {
+ append('.')
+ append(WITH_CHAIN_PARAMS_NAME)
+ append('(')
+ modificationMap.forEach { (paramName, uExpression) ->
+ uExpression.sourcePsi?.text?.let {
+ append("$paramName = $it")
+ append(", ")
+ }
+ }
+ deleteCharAt(this.lastIndex)
+ deleteCharAt(this.lastIndex)
+ append(')')
+ }.toString()
+}
+
+internal fun UExpression.findChildIdentifier(): USimpleNameReferenceExpression? {
+ var identifier: USimpleNameReferenceExpression? = null
+ this.accept(
+ object : UastVisitor {
+ override fun visitSimpleNameReferenceExpression(
+ node: USimpleNameReferenceExpression
+ ): Boolean {
+ if (node.isOfLayoutReferenceType()) {
+ identifier = node
+ }
+ return true
+ }
+
+ // Only supported element to visit recursively, for the form of `textRef.withChainParams()`
+ override fun visitQualifiedReferenceExpression(
+ node: UQualifiedReferenceExpression
+ ): Boolean = false
+
+ override fun visitElement(node: UElement): Boolean = true
+ }
+ )
+ return identifier
+}
+
+/**
+ * Simple way to check if the Reference has a supported LayoutReference type. Note it does not do
+ * expression resolution and takes the type as is. So we have to manually check for inheritors of
+ * LayoutReference.
+ */
+internal fun UExpression.isOfLayoutReferenceType(): Boolean {
+ val typeName = this.getExpressionType()?.canonicalText ?: return false
+ return typeName == CONSTRAINED_LAYOUT_REFERENCE_CLASS_FQ ||
+ typeName == LAYOUT_REFERENCE_CLASS_FQ
}
\ No newline at end of file
diff --git a/core/core-ktx/api/1.10.0-beta01.txt b/core/core-ktx/api/1.10.0-beta01.txt
new file mode 100644
index 0000000..801b56b
--- /dev/null
+++ b/core/core-ktx/api/1.10.0-beta01.txt
@@ -0,0 +1,634 @@
+// Signature format: 4.0
+package androidx.core.animation {
+
+ public final class AnimatorKt {
+ method public static inline android.animation.Animator.AnimatorListener addListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onRepeat);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener addPauseListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onPause);
+ method public static inline android.animation.Animator.AnimatorListener doOnCancel(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnEnd(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnPause(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnRepeat(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnResume(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnStart(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentValuesKt {
+ method public static android.content.ContentValues contentValuesOf(kotlin.Pair<java.lang.String,?>... pairs);
+ }
+
+ public final class ContextKt {
+ method public static inline <reified T> T! getSystemService(android.content.Context);
+ method public static inline void withStyledAttributes(android.content.Context, optional android.util.AttributeSet? set, int[] attrs, optional @AttrRes int defStyleAttr, optional @StyleRes int defStyleRes, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ method public static inline void withStyledAttributes(android.content.Context, @StyleRes int resourceId, int[] attrs, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ }
+
+ public final class SharedPreferencesKt {
+ method public static inline void edit(android.content.SharedPreferences, optional boolean commit, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content.res {
+
+ public final class TypedArrayKt {
+ method public static boolean getBooleanOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @ColorInt public static int getColorOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.content.res.ColorStateList getColorStateListOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getDimensionOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelOffsetOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelSizeOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.graphics.drawable.Drawable getDrawableOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getFloatOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @RequiresApi(26) public static android.graphics.Typeface getFontOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntegerOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @AnyRes public static int getResourceIdOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static String getStringOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence![] getTextArrayOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence getTextOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static inline <R> R! use(android.content.res.TypedArray, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,? extends R> block);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorKt {
+ method public static inline byte[]? getBlobOrNull(android.database.Cursor, int index);
+ method public static inline Double? getDoubleOrNull(android.database.Cursor, int index);
+ method public static inline Float? getFloatOrNull(android.database.Cursor, int index);
+ method public static inline Integer? getIntOrNull(android.database.Cursor, int index);
+ method public static inline Long? getLongOrNull(android.database.Cursor, int index);
+ method public static inline Short? getShortOrNull(android.database.Cursor, int index);
+ method public static inline String? getStringOrNull(android.database.Cursor, int index);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteDatabaseKt {
+ method public static inline <T> T! transaction(android.database.sqlite.SQLiteDatabase, optional boolean exclusive, kotlin.jvm.functions.Function1<? super android.database.sqlite.SQLiteDatabase,? extends T> body);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapKt {
+ method public static inline android.graphics.Bitmap applyCanvas(android.graphics.Bitmap, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.PointF p);
+ method public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config);
+ method @RequiresApi(26) public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config, optional boolean hasAlpha, optional android.graphics.ColorSpace colorSpace);
+ method public static inline operator int get(android.graphics.Bitmap, int x, int y);
+ method public static inline android.graphics.Bitmap scale(android.graphics.Bitmap, int width, int height, optional boolean filter);
+ method public static inline operator void set(android.graphics.Bitmap, int x, int y, @ColorInt int color);
+ }
+
+ public final class CanvasKt {
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Rect clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.RectF clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, int left, int top, int right, int bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Path clipPath, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withMatrix(android.graphics.Canvas, optional android.graphics.Matrix matrix, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withRotation(android.graphics.Canvas, optional float degrees, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSave(android.graphics.Canvas, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withScale(android.graphics.Canvas, optional float x, optional float y, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSkew(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withTranslation(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class ColorKt {
+ method @RequiresApi(26) public static inline operator float component1(android.graphics.Color);
+ method public static inline operator int component1(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component1(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component2(android.graphics.Color);
+ method public static inline operator int component2(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component2(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component3(android.graphics.Color);
+ method public static inline operator int component3(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component3(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component4(android.graphics.Color);
+ method public static inline operator int component4(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component4(@ColorLong long);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace.Named colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace colorSpace);
+ method public static inline int getAlpha(@ColorInt int);
+ method @RequiresApi(26) public static inline float getAlpha(@ColorLong long);
+ method public static inline int getBlue(@ColorInt int);
+ method @RequiresApi(26) public static inline float getBlue(@ColorLong long);
+ method @RequiresApi(26) public static inline android.graphics.ColorSpace getColorSpace(@ColorLong long);
+ method public static inline int getGreen(@ColorInt int);
+ method @RequiresApi(26) public static inline float getGreen(@ColorLong long);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorInt int);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorLong long);
+ method public static inline int getRed(@ColorInt int);
+ method @RequiresApi(26) public static inline float getRed(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isSrgb(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isWideGamut(@ColorLong long);
+ method @RequiresApi(26) public static operator android.graphics.Color plus(android.graphics.Color, android.graphics.Color c);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorLong long);
+ method @ColorInt @RequiresApi(26) public static inline int toColorInt(@ColorLong long);
+ method @ColorInt public static inline int toColorInt(String);
+ method @ColorLong @RequiresApi(26) public static inline long toColorLong(@ColorInt int);
+ }
+
+ public final class ImageDecoderKt {
+ method @RequiresApi(28) public static inline android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ method @RequiresApi(28) public static inline android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ }
+
+ public final class MatrixKt {
+ method public static android.graphics.Matrix rotationMatrix(float degrees, optional float px, optional float py);
+ method public static android.graphics.Matrix scaleMatrix(optional float sx, optional float sy);
+ method public static inline operator android.graphics.Matrix times(android.graphics.Matrix, android.graphics.Matrix m);
+ method public static android.graphics.Matrix translationMatrix(optional float tx, optional float ty);
+ method public static inline float[] values(android.graphics.Matrix);
+ }
+
+ public final class PaintKt {
+ method public static inline boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat? blendModeCompat);
+ }
+
+ public final class PathKt {
+ method @RequiresApi(19) public static inline infix android.graphics.Path and(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(26) public static Iterable<androidx.core.graphics.PathSegment> flatten(android.graphics.Path, optional float error);
+ method @RequiresApi(19) public static inline operator android.graphics.Path minus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path or(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline operator android.graphics.Path plus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path xor(android.graphics.Path, android.graphics.Path p);
+ }
+
+ public final class PictureKt {
+ method public static inline android.graphics.Picture record(android.graphics.Picture, int width, int height, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class PointKt {
+ method public static inline operator int component1(android.graphics.Point);
+ method public static inline operator float component1(android.graphics.PointF);
+ method public static inline operator int component2(android.graphics.Point);
+ method public static inline operator float component2(android.graphics.PointF);
+ method public static inline operator android.graphics.Point div(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF div(android.graphics.PointF, float scalar);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point times(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF times(android.graphics.PointF, float scalar);
+ method public static inline android.graphics.Point toPoint(android.graphics.PointF);
+ method public static inline android.graphics.PointF toPointF(android.graphics.Point);
+ method public static inline operator android.graphics.Point unaryMinus(android.graphics.Point);
+ method public static inline operator android.graphics.PointF unaryMinus(android.graphics.PointF);
+ }
+
+ public final class PorterDuffKt {
+ method public static inline android.graphics.PorterDuffColorFilter toColorFilter(android.graphics.PorterDuff.Mode, int color);
+ method public static inline android.graphics.PorterDuffXfermode toXfermode(android.graphics.PorterDuff.Mode);
+ }
+
+ public final class RectKt {
+ method public static inline infix android.graphics.Rect and(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF and(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator int component1(android.graphics.Rect);
+ method public static inline operator float component1(android.graphics.RectF);
+ method public static inline operator int component2(android.graphics.Rect);
+ method public static inline operator float component2(android.graphics.RectF);
+ method public static inline operator int component3(android.graphics.Rect);
+ method public static inline operator float component3(android.graphics.RectF);
+ method public static inline operator int component4(android.graphics.Rect);
+ method public static inline operator float component4(android.graphics.RectF);
+ method public static inline operator boolean contains(android.graphics.Rect, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.RectF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Region minus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline infix android.graphics.Rect or(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF or(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline operator android.graphics.Rect times(android.graphics.Rect, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, float factor);
+ method public static inline android.graphics.Rect toRect(android.graphics.RectF);
+ method public static inline android.graphics.RectF toRectF(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.RectF);
+ method public static inline android.graphics.RectF transform(android.graphics.RectF, android.graphics.Matrix m);
+ method public static inline infix android.graphics.Region xor(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.RectF, android.graphics.RectF r);
+ }
+
+ public final class RegionKt {
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator boolean contains(android.graphics.Region, android.graphics.Point p);
+ method public static inline void forEach(android.graphics.Region, kotlin.jvm.functions.Function1<? super android.graphics.Rect,kotlin.Unit> action);
+ method public static operator java.util.Iterator<android.graphics.Rect> iterator(android.graphics.Region);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region not(android.graphics.Region);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region unaryMinus(android.graphics.Region);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Region r);
+ }
+
+ public final class ShaderKt {
+ method public static inline void transform(android.graphics.Shader, kotlin.jvm.functions.Function1<? super android.graphics.Matrix,kotlin.Unit> block);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class BitmapDrawableKt {
+ method public static inline android.graphics.drawable.BitmapDrawable toDrawable(android.graphics.Bitmap, android.content.res.Resources resources);
+ }
+
+ public final class ColorDrawableKt {
+ method public static inline android.graphics.drawable.ColorDrawable toDrawable(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.drawable.ColorDrawable toDrawable(android.graphics.Color);
+ }
+
+ public final class DrawableKt {
+ method public static android.graphics.Bitmap toBitmap(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static android.graphics.Bitmap? toBitmapOrNull(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static void updateBounds(android.graphics.drawable.Drawable, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ }
+
+ public final class IconKt {
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toAdaptiveIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.net.Uri);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(byte[]);
+ }
+
+}
+
+package androidx.core.location {
+
+ public final class LocationKt {
+ method public static inline operator double component1(android.location.Location);
+ method public static inline operator double component2(android.location.Location);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class UriKt {
+ method public static java.io.File toFile(android.net.Uri);
+ method public static inline android.net.Uri toUri(String);
+ method public static inline android.net.Uri toUri(java.io.File);
+ }
+
+}
+
+package androidx.core.os {
+
+ public final class BundleKt {
+ method public static android.os.Bundle bundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method public static android.os.Bundle bundleOf();
+ }
+
+ public final class HandlerKt {
+ method public static inline Runnable postAtTime(android.os.Handler, long uptimeMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline Runnable postDelayed(android.os.Handler, long delayInMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ }
+
+ @RequiresApi(31) public final class OutcomeReceiverKt {
+ method @RequiresApi(31) public static <R, E extends java.lang.Throwable> android.os.OutcomeReceiver<R,E> asOutcomeReceiver(kotlin.coroutines.Continuation<? super R>);
+ }
+
+ public final class PersistableBundleKt {
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf();
+ method @RequiresApi(21) public static android.os.PersistableBundle toPersistableBundle(java.util.Map<java.lang.String,?>);
+ }
+
+ public final class TraceKt {
+ method @Deprecated public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class CharSequenceKt {
+ method public static inline boolean isDigitsOnly(CharSequence);
+ method public static inline int trimmedLength(CharSequence);
+ }
+
+ public final class HtmlKt {
+ method public static inline android.text.Spanned parseAsHtml(String, optional int flags, optional android.text.Html.ImageGetter? imageGetter, optional android.text.Html.TagHandler? tagHandler);
+ method public static inline String toHtml(android.text.Spanned, optional int option);
+ }
+
+ public final class LocaleKt {
+ method @RequiresApi(17) public static inline int getLayoutDirection(java.util.Locale);
+ }
+
+ public final class SpannableStringBuilderKt {
+ method public static inline android.text.SpannableStringBuilder backgroundColor(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder bold(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannedString buildSpannedString(kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder color(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object![] spans, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object span, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder italic(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder scale(android.text.SpannableStringBuilder, float proportion, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder strikeThrough(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder subscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder superscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder underline(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ }
+
+ public final class SpannableStringKt {
+ method public static inline void clearSpans(android.text.Spannable);
+ method public static inline operator void set(android.text.Spannable, int start, int end, Object span);
+ method public static inline operator void set(android.text.Spannable, kotlin.ranges.IntRange range, Object span);
+ method public static inline android.text.Spannable toSpannable(CharSequence);
+ }
+
+ public final class SpannedStringKt {
+ method public static inline <reified T> T![] getSpans(android.text.Spanned, optional int start, optional int end);
+ method public static inline android.text.Spanned toSpanned(CharSequence);
+ }
+
+ public final class StringKt {
+ method public static inline String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.transition {
+
+ public final class TransitionKt {
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener addListener(android.transition.Transition, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onPause);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnCancel(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnEnd(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnPause(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnResume(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnStart(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.util {
+
+ public final class AndroidXConsumerKt {
+ method public static <T> androidx.core.util.Consumer<T> asAndroidXConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class AtomicFileKt {
+ method @RequiresApi(17) public static inline byte[] readBytes(android.util.AtomicFile);
+ method @RequiresApi(17) public static String readText(android.util.AtomicFile, optional java.nio.charset.Charset charset);
+ method @RequiresApi(17) public static inline void tryWrite(android.util.AtomicFile, kotlin.jvm.functions.Function1<? super java.io.FileOutputStream,kotlin.Unit> block);
+ method @RequiresApi(17) public static void writeBytes(android.util.AtomicFile, byte[] array);
+ method @RequiresApi(17) public static void writeText(android.util.AtomicFile, String text, optional java.nio.charset.Charset charset);
+ }
+
+ @RequiresApi(24) public final class ConsumerKt {
+ method @RequiresApi(24) public static <T> java.util.function.Consumer<T> asConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class HalfKt {
+ method @RequiresApi(26) public static inline android.util.Half toHalf(@HalfFloat short);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(float);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(double);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(String);
+ }
+
+ public final class LongSparseArrayKt {
+ method @RequiresApi(16) public static inline operator <T> boolean contains(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsKey(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsValue(android.util.LongSparseArray<T>, T? value);
+ method @RequiresApi(16) public static inline <T> void forEach(android.util.LongSparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Long,? super T,kotlin.Unit> action);
+ method @RequiresApi(16) public static inline <T> T! getOrDefault(android.util.LongSparseArray<T>, long key, T? defaultValue);
+ method @RequiresApi(16) public static inline <T> T! getOrElse(android.util.LongSparseArray<T>, long key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method @RequiresApi(16) public static inline <T> int getSize(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isNotEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static <T> kotlin.collections.LongIterator keyIterator(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static operator <T> android.util.LongSparseArray<T> plus(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> void putAll(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> boolean remove(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static inline operator <T> void set(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static <T> java.util.Iterator<T> valueIterator(android.util.LongSparseArray<T>);
+ }
+
+ public final class LruCacheKt {
+ method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, optional kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf, optional kotlin.jvm.functions.Function1<? super K,? extends V> create, optional kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved);
+ }
+
+ public final class PairKt {
+ method public static inline operator <F, S> F! component1(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> F! component1(android.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(android.util.Pair<F,S>);
+ method public static inline <F, S> android.util.Pair<F,S> toAndroidPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> androidx.core.util.Pair<F,S> toAndroidXPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(androidx.core.util.Pair<F,S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(android.util.Pair<F,S>);
+ }
+
+ public final class RangeKt {
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> and(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, T value);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> rangeTo(T, T that);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> kotlin.ranges.ClosedRange<T> toClosedRange(android.util.Range<T>);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> toRange(kotlin.ranges.ClosedRange<T>);
+ }
+
+ public final class RunnableKt {
+ method public static Runnable asRunnable(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ }
+
+ public final class SizeKt {
+ method @RequiresApi(21) public static inline operator int component1(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+ method public static inline operator float component1(androidx.core.util.SizeFCompat);
+ method @RequiresApi(21) public static inline operator int component2(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+ method public static inline operator float component2(androidx.core.util.SizeFCompat);
+ }
+
+ public final class SparseArrayKt {
+ method public static inline operator <T> boolean contains(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsKey(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsValue(android.util.SparseArray<T>, T? value);
+ method public static inline <T> void forEach(android.util.SparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+ method public static inline <T> T! getOrDefault(android.util.SparseArray<T>, int key, T? defaultValue);
+ method public static inline <T> T! getOrElse(android.util.SparseArray<T>, int key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method public static inline <T> int getSize(android.util.SparseArray<T>);
+ method public static inline <T> boolean isEmpty(android.util.SparseArray<T>);
+ method public static inline <T> boolean isNotEmpty(android.util.SparseArray<T>);
+ method public static <T> kotlin.collections.IntIterator keyIterator(android.util.SparseArray<T>);
+ method public static operator <T> android.util.SparseArray<T> plus(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> void putAll(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> boolean remove(android.util.SparseArray<T>, int key, T? value);
+ method public static inline operator <T> void set(android.util.SparseArray<T>, int key, T? value);
+ method public static <T> java.util.Iterator<T> valueIterator(android.util.SparseArray<T>);
+ }
+
+ public final class SparseBooleanArrayKt {
+ method public static inline operator boolean contains(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsKey(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsValue(android.util.SparseBooleanArray, boolean value);
+ method public static inline void forEach(android.util.SparseBooleanArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> action);
+ method public static inline boolean getOrDefault(android.util.SparseBooleanArray, int key, boolean defaultValue);
+ method public static inline boolean getOrElse(android.util.SparseBooleanArray, int key, kotlin.jvm.functions.Function0<java.lang.Boolean> defaultValue);
+ method public static inline int getSize(android.util.SparseBooleanArray);
+ method public static inline boolean isEmpty(android.util.SparseBooleanArray);
+ method public static inline boolean isNotEmpty(android.util.SparseBooleanArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseBooleanArray);
+ method public static operator android.util.SparseBooleanArray plus(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static void putAll(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static boolean remove(android.util.SparseBooleanArray, int key, boolean value);
+ method public static inline operator void set(android.util.SparseBooleanArray, int key, boolean value);
+ method public static kotlin.collections.BooleanIterator valueIterator(android.util.SparseBooleanArray);
+ }
+
+ public final class SparseIntArrayKt {
+ method public static inline operator boolean contains(android.util.SparseIntArray, int key);
+ method public static inline boolean containsKey(android.util.SparseIntArray, int key);
+ method public static inline boolean containsValue(android.util.SparseIntArray, int value);
+ method public static inline void forEach(android.util.SparseIntArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline int getOrDefault(android.util.SparseIntArray, int key, int defaultValue);
+ method public static inline int getOrElse(android.util.SparseIntArray, int key, kotlin.jvm.functions.Function0<java.lang.Integer> defaultValue);
+ method public static inline int getSize(android.util.SparseIntArray);
+ method public static inline boolean isEmpty(android.util.SparseIntArray);
+ method public static inline boolean isNotEmpty(android.util.SparseIntArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseIntArray);
+ method public static operator android.util.SparseIntArray plus(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static void putAll(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static boolean remove(android.util.SparseIntArray, int key, int value);
+ method public static inline operator void set(android.util.SparseIntArray, int key, int value);
+ method public static kotlin.collections.IntIterator valueIterator(android.util.SparseIntArray);
+ }
+
+ public final class SparseLongArrayKt {
+ method @RequiresApi(18) public static inline operator boolean contains(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsKey(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsValue(android.util.SparseLongArray, long value);
+ method @RequiresApi(18) public static inline void forEach(android.util.SparseLongArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Long,kotlin.Unit> action);
+ method @RequiresApi(18) public static inline long getOrDefault(android.util.SparseLongArray, int key, long defaultValue);
+ method @RequiresApi(18) public static inline long getOrElse(android.util.SparseLongArray, int key, kotlin.jvm.functions.Function0<java.lang.Long> defaultValue);
+ method @RequiresApi(18) public static inline int getSize(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isNotEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static kotlin.collections.IntIterator keyIterator(android.util.SparseLongArray);
+ method @RequiresApi(18) public static operator android.util.SparseLongArray plus(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static void putAll(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static boolean remove(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static inline operator void set(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static kotlin.collections.LongIterator valueIterator(android.util.SparseLongArray);
+ }
+
+}
+
+package androidx.core.view {
+
+ public final class MenuKt {
+ method public static operator boolean contains(android.view.Menu, android.view.MenuItem item);
+ method public static inline void forEach(android.view.Menu, kotlin.jvm.functions.Function1<? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.Menu, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline operator android.view.MenuItem get(android.view.Menu, int index);
+ method public static kotlin.sequences.Sequence<android.view.MenuItem> getChildren(android.view.Menu);
+ method public static inline int getSize(android.view.Menu);
+ method public static inline boolean isEmpty(android.view.Menu);
+ method public static inline boolean isNotEmpty(android.view.Menu);
+ method public static operator java.util.Iterator<android.view.MenuItem> iterator(android.view.Menu);
+ method public static inline operator void minusAssign(android.view.Menu, android.view.MenuItem item);
+ method public static inline void removeItemAt(android.view.Menu, int index);
+ }
+
+ public final class ViewGroupKt {
+ method public static inline operator boolean contains(android.view.ViewGroup, android.view.View view);
+ method public static inline void forEach(android.view.ViewGroup, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.ViewGroup, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.View,kotlin.Unit> action);
+ method public static operator android.view.View get(android.view.ViewGroup, int index);
+ method public static kotlin.sequences.Sequence<android.view.View> getChildren(android.view.ViewGroup);
+ method public static kotlin.sequences.Sequence<android.view.View> getDescendants(android.view.ViewGroup);
+ method public static inline kotlin.ranges.IntRange getIndices(android.view.ViewGroup);
+ method public static inline int getSize(android.view.ViewGroup);
+ method public static inline boolean isEmpty(android.view.ViewGroup);
+ method public static inline boolean isNotEmpty(android.view.ViewGroup);
+ method public static operator java.util.Iterator<android.view.View> iterator(android.view.ViewGroup);
+ method public static inline operator void minusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline operator void plusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline void setMargins(android.view.ViewGroup.MarginLayoutParams, @Px int size);
+ method public static inline void updateMargins(android.view.ViewGroup.MarginLayoutParams, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updateMarginsRelative(android.view.ViewGroup.MarginLayoutParams, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+ public final class ViewKt {
+ method public static inline void doOnAttach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnDetach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnNextLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline androidx.core.view.OneShotPreDrawListener doOnPreDraw(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static android.graphics.Bitmap drawToBitmap(android.view.View, optional android.graphics.Bitmap.Config config);
+ method public static kotlin.sequences.Sequence<android.view.View> getAllViews(android.view.View);
+ method public static kotlin.sequences.Sequence<android.view.ViewParent> getAncestors(android.view.View);
+ method public static inline int getMarginBottom(android.view.View);
+ method public static inline int getMarginEnd(android.view.View);
+ method public static inline int getMarginLeft(android.view.View);
+ method public static inline int getMarginRight(android.view.View);
+ method public static inline int getMarginStart(android.view.View);
+ method public static inline int getMarginTop(android.view.View);
+ method public static inline boolean isGone(android.view.View);
+ method public static inline boolean isInvisible(android.view.View);
+ method public static inline boolean isVisible(android.view.View);
+ method public static inline Runnable postDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method @RequiresApi(16) public static Runnable postOnAnimationDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline void setGone(android.view.View, boolean);
+ method public static inline void setInvisible(android.view.View, boolean);
+ method public static inline void setPadding(android.view.View, @Px int size);
+ method public static inline void setVisible(android.view.View, boolean);
+ method public static inline void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super android.view.ViewGroup.LayoutParams,kotlin.Unit> block);
+ method public static inline <reified T extends android.view.ViewGroup.LayoutParams> void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super T,? extends kotlin.Unit> block);
+ method public static inline void updatePadding(android.view.View, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updatePaddingRelative(android.view.View, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public final class TextViewKt {
+ method public static inline android.text.TextWatcher addTextChangedListener(android.widget.TextView, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> beforeTextChanged, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> onTextChanged, optional kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> afterTextChanged);
+ method public static inline android.text.TextWatcher doAfterTextChanged(android.widget.TextView, kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doBeforeTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doOnTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ }
+
+}
+
diff --git a/core/core-ktx/api/public_plus_experimental_1.10.0-beta01.txt b/core/core-ktx/api/public_plus_experimental_1.10.0-beta01.txt
new file mode 100644
index 0000000..801b56b
--- /dev/null
+++ b/core/core-ktx/api/public_plus_experimental_1.10.0-beta01.txt
@@ -0,0 +1,634 @@
+// Signature format: 4.0
+package androidx.core.animation {
+
+ public final class AnimatorKt {
+ method public static inline android.animation.Animator.AnimatorListener addListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onRepeat);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener addPauseListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onPause);
+ method public static inline android.animation.Animator.AnimatorListener doOnCancel(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnEnd(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnPause(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnRepeat(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnResume(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnStart(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentValuesKt {
+ method public static android.content.ContentValues contentValuesOf(kotlin.Pair<java.lang.String,?>... pairs);
+ }
+
+ public final class ContextKt {
+ method public static inline <reified T> T! getSystemService(android.content.Context);
+ method public static inline void withStyledAttributes(android.content.Context, optional android.util.AttributeSet? set, int[] attrs, optional @AttrRes int defStyleAttr, optional @StyleRes int defStyleRes, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ method public static inline void withStyledAttributes(android.content.Context, @StyleRes int resourceId, int[] attrs, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ }
+
+ public final class SharedPreferencesKt {
+ method public static inline void edit(android.content.SharedPreferences, optional boolean commit, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content.res {
+
+ public final class TypedArrayKt {
+ method public static boolean getBooleanOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @ColorInt public static int getColorOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.content.res.ColorStateList getColorStateListOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getDimensionOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelOffsetOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelSizeOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.graphics.drawable.Drawable getDrawableOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getFloatOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @RequiresApi(26) public static android.graphics.Typeface getFontOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntegerOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @AnyRes public static int getResourceIdOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static String getStringOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence![] getTextArrayOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence getTextOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static inline <R> R! use(android.content.res.TypedArray, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,? extends R> block);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorKt {
+ method public static inline byte[]? getBlobOrNull(android.database.Cursor, int index);
+ method public static inline Double? getDoubleOrNull(android.database.Cursor, int index);
+ method public static inline Float? getFloatOrNull(android.database.Cursor, int index);
+ method public static inline Integer? getIntOrNull(android.database.Cursor, int index);
+ method public static inline Long? getLongOrNull(android.database.Cursor, int index);
+ method public static inline Short? getShortOrNull(android.database.Cursor, int index);
+ method public static inline String? getStringOrNull(android.database.Cursor, int index);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteDatabaseKt {
+ method public static inline <T> T! transaction(android.database.sqlite.SQLiteDatabase, optional boolean exclusive, kotlin.jvm.functions.Function1<? super android.database.sqlite.SQLiteDatabase,? extends T> body);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapKt {
+ method public static inline android.graphics.Bitmap applyCanvas(android.graphics.Bitmap, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.PointF p);
+ method public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config);
+ method @RequiresApi(26) public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config, optional boolean hasAlpha, optional android.graphics.ColorSpace colorSpace);
+ method public static inline operator int get(android.graphics.Bitmap, int x, int y);
+ method public static inline android.graphics.Bitmap scale(android.graphics.Bitmap, int width, int height, optional boolean filter);
+ method public static inline operator void set(android.graphics.Bitmap, int x, int y, @ColorInt int color);
+ }
+
+ public final class CanvasKt {
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Rect clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.RectF clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, int left, int top, int right, int bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Path clipPath, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withMatrix(android.graphics.Canvas, optional android.graphics.Matrix matrix, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withRotation(android.graphics.Canvas, optional float degrees, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSave(android.graphics.Canvas, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withScale(android.graphics.Canvas, optional float x, optional float y, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSkew(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withTranslation(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class ColorKt {
+ method @RequiresApi(26) public static inline operator float component1(android.graphics.Color);
+ method public static inline operator int component1(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component1(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component2(android.graphics.Color);
+ method public static inline operator int component2(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component2(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component3(android.graphics.Color);
+ method public static inline operator int component3(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component3(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component4(android.graphics.Color);
+ method public static inline operator int component4(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component4(@ColorLong long);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace.Named colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace colorSpace);
+ method public static inline int getAlpha(@ColorInt int);
+ method @RequiresApi(26) public static inline float getAlpha(@ColorLong long);
+ method public static inline int getBlue(@ColorInt int);
+ method @RequiresApi(26) public static inline float getBlue(@ColorLong long);
+ method @RequiresApi(26) public static inline android.graphics.ColorSpace getColorSpace(@ColorLong long);
+ method public static inline int getGreen(@ColorInt int);
+ method @RequiresApi(26) public static inline float getGreen(@ColorLong long);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorInt int);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorLong long);
+ method public static inline int getRed(@ColorInt int);
+ method @RequiresApi(26) public static inline float getRed(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isSrgb(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isWideGamut(@ColorLong long);
+ method @RequiresApi(26) public static operator android.graphics.Color plus(android.graphics.Color, android.graphics.Color c);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorLong long);
+ method @ColorInt @RequiresApi(26) public static inline int toColorInt(@ColorLong long);
+ method @ColorInt public static inline int toColorInt(String);
+ method @ColorLong @RequiresApi(26) public static inline long toColorLong(@ColorInt int);
+ }
+
+ public final class ImageDecoderKt {
+ method @RequiresApi(28) public static inline android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ method @RequiresApi(28) public static inline android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ }
+
+ public final class MatrixKt {
+ method public static android.graphics.Matrix rotationMatrix(float degrees, optional float px, optional float py);
+ method public static android.graphics.Matrix scaleMatrix(optional float sx, optional float sy);
+ method public static inline operator android.graphics.Matrix times(android.graphics.Matrix, android.graphics.Matrix m);
+ method public static android.graphics.Matrix translationMatrix(optional float tx, optional float ty);
+ method public static inline float[] values(android.graphics.Matrix);
+ }
+
+ public final class PaintKt {
+ method public static inline boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat? blendModeCompat);
+ }
+
+ public final class PathKt {
+ method @RequiresApi(19) public static inline infix android.graphics.Path and(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(26) public static Iterable<androidx.core.graphics.PathSegment> flatten(android.graphics.Path, optional float error);
+ method @RequiresApi(19) public static inline operator android.graphics.Path minus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path or(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline operator android.graphics.Path plus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path xor(android.graphics.Path, android.graphics.Path p);
+ }
+
+ public final class PictureKt {
+ method public static inline android.graphics.Picture record(android.graphics.Picture, int width, int height, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class PointKt {
+ method public static inline operator int component1(android.graphics.Point);
+ method public static inline operator float component1(android.graphics.PointF);
+ method public static inline operator int component2(android.graphics.Point);
+ method public static inline operator float component2(android.graphics.PointF);
+ method public static inline operator android.graphics.Point div(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF div(android.graphics.PointF, float scalar);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point times(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF times(android.graphics.PointF, float scalar);
+ method public static inline android.graphics.Point toPoint(android.graphics.PointF);
+ method public static inline android.graphics.PointF toPointF(android.graphics.Point);
+ method public static inline operator android.graphics.Point unaryMinus(android.graphics.Point);
+ method public static inline operator android.graphics.PointF unaryMinus(android.graphics.PointF);
+ }
+
+ public final class PorterDuffKt {
+ method public static inline android.graphics.PorterDuffColorFilter toColorFilter(android.graphics.PorterDuff.Mode, int color);
+ method public static inline android.graphics.PorterDuffXfermode toXfermode(android.graphics.PorterDuff.Mode);
+ }
+
+ public final class RectKt {
+ method public static inline infix android.graphics.Rect and(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF and(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator int component1(android.graphics.Rect);
+ method public static inline operator float component1(android.graphics.RectF);
+ method public static inline operator int component2(android.graphics.Rect);
+ method public static inline operator float component2(android.graphics.RectF);
+ method public static inline operator int component3(android.graphics.Rect);
+ method public static inline operator float component3(android.graphics.RectF);
+ method public static inline operator int component4(android.graphics.Rect);
+ method public static inline operator float component4(android.graphics.RectF);
+ method public static inline operator boolean contains(android.graphics.Rect, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.RectF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Region minus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline infix android.graphics.Rect or(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF or(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline operator android.graphics.Rect times(android.graphics.Rect, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, float factor);
+ method public static inline android.graphics.Rect toRect(android.graphics.RectF);
+ method public static inline android.graphics.RectF toRectF(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.RectF);
+ method public static inline android.graphics.RectF transform(android.graphics.RectF, android.graphics.Matrix m);
+ method public static inline infix android.graphics.Region xor(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.RectF, android.graphics.RectF r);
+ }
+
+ public final class RegionKt {
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator boolean contains(android.graphics.Region, android.graphics.Point p);
+ method public static inline void forEach(android.graphics.Region, kotlin.jvm.functions.Function1<? super android.graphics.Rect,kotlin.Unit> action);
+ method public static operator java.util.Iterator<android.graphics.Rect> iterator(android.graphics.Region);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region not(android.graphics.Region);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region unaryMinus(android.graphics.Region);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Region r);
+ }
+
+ public final class ShaderKt {
+ method public static inline void transform(android.graphics.Shader, kotlin.jvm.functions.Function1<? super android.graphics.Matrix,kotlin.Unit> block);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class BitmapDrawableKt {
+ method public static inline android.graphics.drawable.BitmapDrawable toDrawable(android.graphics.Bitmap, android.content.res.Resources resources);
+ }
+
+ public final class ColorDrawableKt {
+ method public static inline android.graphics.drawable.ColorDrawable toDrawable(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.drawable.ColorDrawable toDrawable(android.graphics.Color);
+ }
+
+ public final class DrawableKt {
+ method public static android.graphics.Bitmap toBitmap(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static android.graphics.Bitmap? toBitmapOrNull(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static void updateBounds(android.graphics.drawable.Drawable, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ }
+
+ public final class IconKt {
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toAdaptiveIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.net.Uri);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(byte[]);
+ }
+
+}
+
+package androidx.core.location {
+
+ public final class LocationKt {
+ method public static inline operator double component1(android.location.Location);
+ method public static inline operator double component2(android.location.Location);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class UriKt {
+ method public static java.io.File toFile(android.net.Uri);
+ method public static inline android.net.Uri toUri(String);
+ method public static inline android.net.Uri toUri(java.io.File);
+ }
+
+}
+
+package androidx.core.os {
+
+ public final class BundleKt {
+ method public static android.os.Bundle bundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method public static android.os.Bundle bundleOf();
+ }
+
+ public final class HandlerKt {
+ method public static inline Runnable postAtTime(android.os.Handler, long uptimeMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline Runnable postDelayed(android.os.Handler, long delayInMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ }
+
+ @RequiresApi(31) public final class OutcomeReceiverKt {
+ method @RequiresApi(31) public static <R, E extends java.lang.Throwable> android.os.OutcomeReceiver<R,E> asOutcomeReceiver(kotlin.coroutines.Continuation<? super R>);
+ }
+
+ public final class PersistableBundleKt {
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf();
+ method @RequiresApi(21) public static android.os.PersistableBundle toPersistableBundle(java.util.Map<java.lang.String,?>);
+ }
+
+ public final class TraceKt {
+ method @Deprecated public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class CharSequenceKt {
+ method public static inline boolean isDigitsOnly(CharSequence);
+ method public static inline int trimmedLength(CharSequence);
+ }
+
+ public final class HtmlKt {
+ method public static inline android.text.Spanned parseAsHtml(String, optional int flags, optional android.text.Html.ImageGetter? imageGetter, optional android.text.Html.TagHandler? tagHandler);
+ method public static inline String toHtml(android.text.Spanned, optional int option);
+ }
+
+ public final class LocaleKt {
+ method @RequiresApi(17) public static inline int getLayoutDirection(java.util.Locale);
+ }
+
+ public final class SpannableStringBuilderKt {
+ method public static inline android.text.SpannableStringBuilder backgroundColor(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder bold(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannedString buildSpannedString(kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder color(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object![] spans, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object span, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder italic(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder scale(android.text.SpannableStringBuilder, float proportion, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder strikeThrough(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder subscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder superscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder underline(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ }
+
+ public final class SpannableStringKt {
+ method public static inline void clearSpans(android.text.Spannable);
+ method public static inline operator void set(android.text.Spannable, int start, int end, Object span);
+ method public static inline operator void set(android.text.Spannable, kotlin.ranges.IntRange range, Object span);
+ method public static inline android.text.Spannable toSpannable(CharSequence);
+ }
+
+ public final class SpannedStringKt {
+ method public static inline <reified T> T![] getSpans(android.text.Spanned, optional int start, optional int end);
+ method public static inline android.text.Spanned toSpanned(CharSequence);
+ }
+
+ public final class StringKt {
+ method public static inline String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.transition {
+
+ public final class TransitionKt {
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener addListener(android.transition.Transition, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onPause);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnCancel(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnEnd(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnPause(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnResume(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnStart(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.util {
+
+ public final class AndroidXConsumerKt {
+ method public static <T> androidx.core.util.Consumer<T> asAndroidXConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class AtomicFileKt {
+ method @RequiresApi(17) public static inline byte[] readBytes(android.util.AtomicFile);
+ method @RequiresApi(17) public static String readText(android.util.AtomicFile, optional java.nio.charset.Charset charset);
+ method @RequiresApi(17) public static inline void tryWrite(android.util.AtomicFile, kotlin.jvm.functions.Function1<? super java.io.FileOutputStream,kotlin.Unit> block);
+ method @RequiresApi(17) public static void writeBytes(android.util.AtomicFile, byte[] array);
+ method @RequiresApi(17) public static void writeText(android.util.AtomicFile, String text, optional java.nio.charset.Charset charset);
+ }
+
+ @RequiresApi(24) public final class ConsumerKt {
+ method @RequiresApi(24) public static <T> java.util.function.Consumer<T> asConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class HalfKt {
+ method @RequiresApi(26) public static inline android.util.Half toHalf(@HalfFloat short);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(float);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(double);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(String);
+ }
+
+ public final class LongSparseArrayKt {
+ method @RequiresApi(16) public static inline operator <T> boolean contains(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsKey(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsValue(android.util.LongSparseArray<T>, T? value);
+ method @RequiresApi(16) public static inline <T> void forEach(android.util.LongSparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Long,? super T,kotlin.Unit> action);
+ method @RequiresApi(16) public static inline <T> T! getOrDefault(android.util.LongSparseArray<T>, long key, T? defaultValue);
+ method @RequiresApi(16) public static inline <T> T! getOrElse(android.util.LongSparseArray<T>, long key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method @RequiresApi(16) public static inline <T> int getSize(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isNotEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static <T> kotlin.collections.LongIterator keyIterator(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static operator <T> android.util.LongSparseArray<T> plus(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> void putAll(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> boolean remove(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static inline operator <T> void set(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static <T> java.util.Iterator<T> valueIterator(android.util.LongSparseArray<T>);
+ }
+
+ public final class LruCacheKt {
+ method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, optional kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf, optional kotlin.jvm.functions.Function1<? super K,? extends V> create, optional kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved);
+ }
+
+ public final class PairKt {
+ method public static inline operator <F, S> F! component1(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> F! component1(android.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(android.util.Pair<F,S>);
+ method public static inline <F, S> android.util.Pair<F,S> toAndroidPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> androidx.core.util.Pair<F,S> toAndroidXPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(androidx.core.util.Pair<F,S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(android.util.Pair<F,S>);
+ }
+
+ public final class RangeKt {
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> and(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, T value);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> rangeTo(T, T that);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> kotlin.ranges.ClosedRange<T> toClosedRange(android.util.Range<T>);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> toRange(kotlin.ranges.ClosedRange<T>);
+ }
+
+ public final class RunnableKt {
+ method public static Runnable asRunnable(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ }
+
+ public final class SizeKt {
+ method @RequiresApi(21) public static inline operator int component1(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+ method public static inline operator float component1(androidx.core.util.SizeFCompat);
+ method @RequiresApi(21) public static inline operator int component2(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+ method public static inline operator float component2(androidx.core.util.SizeFCompat);
+ }
+
+ public final class SparseArrayKt {
+ method public static inline operator <T> boolean contains(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsKey(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsValue(android.util.SparseArray<T>, T? value);
+ method public static inline <T> void forEach(android.util.SparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+ method public static inline <T> T! getOrDefault(android.util.SparseArray<T>, int key, T? defaultValue);
+ method public static inline <T> T! getOrElse(android.util.SparseArray<T>, int key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method public static inline <T> int getSize(android.util.SparseArray<T>);
+ method public static inline <T> boolean isEmpty(android.util.SparseArray<T>);
+ method public static inline <T> boolean isNotEmpty(android.util.SparseArray<T>);
+ method public static <T> kotlin.collections.IntIterator keyIterator(android.util.SparseArray<T>);
+ method public static operator <T> android.util.SparseArray<T> plus(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> void putAll(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> boolean remove(android.util.SparseArray<T>, int key, T? value);
+ method public static inline operator <T> void set(android.util.SparseArray<T>, int key, T? value);
+ method public static <T> java.util.Iterator<T> valueIterator(android.util.SparseArray<T>);
+ }
+
+ public final class SparseBooleanArrayKt {
+ method public static inline operator boolean contains(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsKey(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsValue(android.util.SparseBooleanArray, boolean value);
+ method public static inline void forEach(android.util.SparseBooleanArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> action);
+ method public static inline boolean getOrDefault(android.util.SparseBooleanArray, int key, boolean defaultValue);
+ method public static inline boolean getOrElse(android.util.SparseBooleanArray, int key, kotlin.jvm.functions.Function0<java.lang.Boolean> defaultValue);
+ method public static inline int getSize(android.util.SparseBooleanArray);
+ method public static inline boolean isEmpty(android.util.SparseBooleanArray);
+ method public static inline boolean isNotEmpty(android.util.SparseBooleanArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseBooleanArray);
+ method public static operator android.util.SparseBooleanArray plus(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static void putAll(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static boolean remove(android.util.SparseBooleanArray, int key, boolean value);
+ method public static inline operator void set(android.util.SparseBooleanArray, int key, boolean value);
+ method public static kotlin.collections.BooleanIterator valueIterator(android.util.SparseBooleanArray);
+ }
+
+ public final class SparseIntArrayKt {
+ method public static inline operator boolean contains(android.util.SparseIntArray, int key);
+ method public static inline boolean containsKey(android.util.SparseIntArray, int key);
+ method public static inline boolean containsValue(android.util.SparseIntArray, int value);
+ method public static inline void forEach(android.util.SparseIntArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline int getOrDefault(android.util.SparseIntArray, int key, int defaultValue);
+ method public static inline int getOrElse(android.util.SparseIntArray, int key, kotlin.jvm.functions.Function0<java.lang.Integer> defaultValue);
+ method public static inline int getSize(android.util.SparseIntArray);
+ method public static inline boolean isEmpty(android.util.SparseIntArray);
+ method public static inline boolean isNotEmpty(android.util.SparseIntArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseIntArray);
+ method public static operator android.util.SparseIntArray plus(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static void putAll(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static boolean remove(android.util.SparseIntArray, int key, int value);
+ method public static inline operator void set(android.util.SparseIntArray, int key, int value);
+ method public static kotlin.collections.IntIterator valueIterator(android.util.SparseIntArray);
+ }
+
+ public final class SparseLongArrayKt {
+ method @RequiresApi(18) public static inline operator boolean contains(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsKey(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsValue(android.util.SparseLongArray, long value);
+ method @RequiresApi(18) public static inline void forEach(android.util.SparseLongArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Long,kotlin.Unit> action);
+ method @RequiresApi(18) public static inline long getOrDefault(android.util.SparseLongArray, int key, long defaultValue);
+ method @RequiresApi(18) public static inline long getOrElse(android.util.SparseLongArray, int key, kotlin.jvm.functions.Function0<java.lang.Long> defaultValue);
+ method @RequiresApi(18) public static inline int getSize(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isNotEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static kotlin.collections.IntIterator keyIterator(android.util.SparseLongArray);
+ method @RequiresApi(18) public static operator android.util.SparseLongArray plus(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static void putAll(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static boolean remove(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static inline operator void set(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static kotlin.collections.LongIterator valueIterator(android.util.SparseLongArray);
+ }
+
+}
+
+package androidx.core.view {
+
+ public final class MenuKt {
+ method public static operator boolean contains(android.view.Menu, android.view.MenuItem item);
+ method public static inline void forEach(android.view.Menu, kotlin.jvm.functions.Function1<? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.Menu, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline operator android.view.MenuItem get(android.view.Menu, int index);
+ method public static kotlin.sequences.Sequence<android.view.MenuItem> getChildren(android.view.Menu);
+ method public static inline int getSize(android.view.Menu);
+ method public static inline boolean isEmpty(android.view.Menu);
+ method public static inline boolean isNotEmpty(android.view.Menu);
+ method public static operator java.util.Iterator<android.view.MenuItem> iterator(android.view.Menu);
+ method public static inline operator void minusAssign(android.view.Menu, android.view.MenuItem item);
+ method public static inline void removeItemAt(android.view.Menu, int index);
+ }
+
+ public final class ViewGroupKt {
+ method public static inline operator boolean contains(android.view.ViewGroup, android.view.View view);
+ method public static inline void forEach(android.view.ViewGroup, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.ViewGroup, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.View,kotlin.Unit> action);
+ method public static operator android.view.View get(android.view.ViewGroup, int index);
+ method public static kotlin.sequences.Sequence<android.view.View> getChildren(android.view.ViewGroup);
+ method public static kotlin.sequences.Sequence<android.view.View> getDescendants(android.view.ViewGroup);
+ method public static inline kotlin.ranges.IntRange getIndices(android.view.ViewGroup);
+ method public static inline int getSize(android.view.ViewGroup);
+ method public static inline boolean isEmpty(android.view.ViewGroup);
+ method public static inline boolean isNotEmpty(android.view.ViewGroup);
+ method public static operator java.util.Iterator<android.view.View> iterator(android.view.ViewGroup);
+ method public static inline operator void minusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline operator void plusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline void setMargins(android.view.ViewGroup.MarginLayoutParams, @Px int size);
+ method public static inline void updateMargins(android.view.ViewGroup.MarginLayoutParams, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updateMarginsRelative(android.view.ViewGroup.MarginLayoutParams, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+ public final class ViewKt {
+ method public static inline void doOnAttach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnDetach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnNextLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline androidx.core.view.OneShotPreDrawListener doOnPreDraw(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static android.graphics.Bitmap drawToBitmap(android.view.View, optional android.graphics.Bitmap.Config config);
+ method public static kotlin.sequences.Sequence<android.view.View> getAllViews(android.view.View);
+ method public static kotlin.sequences.Sequence<android.view.ViewParent> getAncestors(android.view.View);
+ method public static inline int getMarginBottom(android.view.View);
+ method public static inline int getMarginEnd(android.view.View);
+ method public static inline int getMarginLeft(android.view.View);
+ method public static inline int getMarginRight(android.view.View);
+ method public static inline int getMarginStart(android.view.View);
+ method public static inline int getMarginTop(android.view.View);
+ method public static inline boolean isGone(android.view.View);
+ method public static inline boolean isInvisible(android.view.View);
+ method public static inline boolean isVisible(android.view.View);
+ method public static inline Runnable postDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method @RequiresApi(16) public static Runnable postOnAnimationDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline void setGone(android.view.View, boolean);
+ method public static inline void setInvisible(android.view.View, boolean);
+ method public static inline void setPadding(android.view.View, @Px int size);
+ method public static inline void setVisible(android.view.View, boolean);
+ method public static inline void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super android.view.ViewGroup.LayoutParams,kotlin.Unit> block);
+ method public static inline <reified T extends android.view.ViewGroup.LayoutParams> void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super T,? extends kotlin.Unit> block);
+ method public static inline void updatePadding(android.view.View, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updatePaddingRelative(android.view.View, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public final class TextViewKt {
+ method public static inline android.text.TextWatcher addTextChangedListener(android.widget.TextView, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> beforeTextChanged, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> onTextChanged, optional kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> afterTextChanged);
+ method public static inline android.text.TextWatcher doAfterTextChanged(android.widget.TextView, kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doBeforeTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doOnTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ }
+
+}
+
diff --git a/core/core-ktx/api/res-1.10.0-beta01.txt b/core/core-ktx/api/res-1.10.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/core-ktx/api/res-1.10.0-beta01.txt
diff --git a/core/core-ktx/api/restricted_1.10.0-beta01.txt b/core/core-ktx/api/restricted_1.10.0-beta01.txt
new file mode 100644
index 0000000..801b56b
--- /dev/null
+++ b/core/core-ktx/api/restricted_1.10.0-beta01.txt
@@ -0,0 +1,634 @@
+// Signature format: 4.0
+package androidx.core.animation {
+
+ public final class AnimatorKt {
+ method public static inline android.animation.Animator.AnimatorListener addListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onRepeat);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener addPauseListener(android.animation.Animator, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> onPause);
+ method public static inline android.animation.Animator.AnimatorListener doOnCancel(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnEnd(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnPause(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnRepeat(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method @RequiresApi(19) public static android.animation.Animator.AnimatorPauseListener doOnResume(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ method public static inline android.animation.Animator.AnimatorListener doOnStart(android.animation.Animator, kotlin.jvm.functions.Function1<? super android.animation.Animator,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentValuesKt {
+ method public static android.content.ContentValues contentValuesOf(kotlin.Pair<java.lang.String,?>... pairs);
+ }
+
+ public final class ContextKt {
+ method public static inline <reified T> T! getSystemService(android.content.Context);
+ method public static inline void withStyledAttributes(android.content.Context, optional android.util.AttributeSet? set, int[] attrs, optional @AttrRes int defStyleAttr, optional @StyleRes int defStyleRes, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ method public static inline void withStyledAttributes(android.content.Context, @StyleRes int resourceId, int[] attrs, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ }
+
+ public final class SharedPreferencesKt {
+ method public static inline void edit(android.content.SharedPreferences, optional boolean commit, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.content.res {
+
+ public final class TypedArrayKt {
+ method public static boolean getBooleanOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @ColorInt public static int getColorOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.content.res.ColorStateList getColorStateListOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getDimensionOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelOffsetOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @Dimension public static int getDimensionPixelSizeOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static android.graphics.drawable.Drawable getDrawableOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static float getFloatOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @RequiresApi(26) public static android.graphics.Typeface getFontOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static int getIntegerOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method @AnyRes public static int getResourceIdOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static String getStringOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence![] getTextArrayOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static CharSequence getTextOrThrow(android.content.res.TypedArray, @StyleableRes int index);
+ method public static inline <R> R! use(android.content.res.TypedArray, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,? extends R> block);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorKt {
+ method public static inline byte[]? getBlobOrNull(android.database.Cursor, int index);
+ method public static inline Double? getDoubleOrNull(android.database.Cursor, int index);
+ method public static inline Float? getFloatOrNull(android.database.Cursor, int index);
+ method public static inline Integer? getIntOrNull(android.database.Cursor, int index);
+ method public static inline Long? getLongOrNull(android.database.Cursor, int index);
+ method public static inline Short? getShortOrNull(android.database.Cursor, int index);
+ method public static inline String? getStringOrNull(android.database.Cursor, int index);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteDatabaseKt {
+ method public static inline <T> T! transaction(android.database.sqlite.SQLiteDatabase, optional boolean exclusive, kotlin.jvm.functions.Function1<? super android.database.sqlite.SQLiteDatabase,? extends T> body);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapKt {
+ method public static inline android.graphics.Bitmap applyCanvas(android.graphics.Bitmap, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.Bitmap, android.graphics.PointF p);
+ method public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config);
+ method @RequiresApi(26) public static inline android.graphics.Bitmap createBitmap(int width, int height, optional android.graphics.Bitmap.Config config, optional boolean hasAlpha, optional android.graphics.ColorSpace colorSpace);
+ method public static inline operator int get(android.graphics.Bitmap, int x, int y);
+ method public static inline android.graphics.Bitmap scale(android.graphics.Bitmap, int width, int height, optional boolean filter);
+ method public static inline operator void set(android.graphics.Bitmap, int x, int y, @ColorInt int color);
+ }
+
+ public final class CanvasKt {
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Rect clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.RectF clipRect, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, int left, int top, int right, int bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withClip(android.graphics.Canvas, android.graphics.Path clipPath, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withMatrix(android.graphics.Canvas, optional android.graphics.Matrix matrix, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withRotation(android.graphics.Canvas, optional float degrees, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSave(android.graphics.Canvas, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withScale(android.graphics.Canvas, optional float x, optional float y, optional float pivotX, optional float pivotY, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withSkew(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ method public static inline void withTranslation(android.graphics.Canvas, optional float x, optional float y, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class ColorKt {
+ method @RequiresApi(26) public static inline operator float component1(android.graphics.Color);
+ method public static inline operator int component1(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component1(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component2(android.graphics.Color);
+ method public static inline operator int component2(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component2(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component3(android.graphics.Color);
+ method public static inline operator int component3(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component3(@ColorLong long);
+ method @RequiresApi(26) public static inline operator float component4(android.graphics.Color);
+ method public static inline operator int component4(@ColorInt int);
+ method @RequiresApi(26) public static inline operator float component4(@ColorLong long);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorInt int, android.graphics.ColorSpace colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace.Named colorSpace);
+ method @ColorLong @RequiresApi(26) public static inline infix long convertTo(@ColorLong long, android.graphics.ColorSpace colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace.Named colorSpace);
+ method @RequiresApi(26) public static inline infix android.graphics.Color convertTo(android.graphics.Color, android.graphics.ColorSpace colorSpace);
+ method public static inline int getAlpha(@ColorInt int);
+ method @RequiresApi(26) public static inline float getAlpha(@ColorLong long);
+ method public static inline int getBlue(@ColorInt int);
+ method @RequiresApi(26) public static inline float getBlue(@ColorLong long);
+ method @RequiresApi(26) public static inline android.graphics.ColorSpace getColorSpace(@ColorLong long);
+ method public static inline int getGreen(@ColorInt int);
+ method @RequiresApi(26) public static inline float getGreen(@ColorLong long);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorInt int);
+ method @RequiresApi(26) public static inline float getLuminance(@ColorLong long);
+ method public static inline int getRed(@ColorInt int);
+ method @RequiresApi(26) public static inline float getRed(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isSrgb(@ColorLong long);
+ method @RequiresApi(26) public static inline boolean isWideGamut(@ColorLong long);
+ method @RequiresApi(26) public static operator android.graphics.Color plus(android.graphics.Color, android.graphics.Color c);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.Color toColor(@ColorLong long);
+ method @ColorInt @RequiresApi(26) public static inline int toColorInt(@ColorLong long);
+ method @ColorInt public static inline int toColorInt(String);
+ method @ColorLong @RequiresApi(26) public static inline long toColorLong(@ColorInt int);
+ }
+
+ public final class ImageDecoderKt {
+ method @RequiresApi(28) public static inline android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ method @RequiresApi(28) public static inline android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, kotlin.jvm.functions.Function3<? super android.graphics.ImageDecoder,? super android.graphics.ImageDecoder.ImageInfo,? super android.graphics.ImageDecoder.Source,kotlin.Unit> action);
+ }
+
+ public final class MatrixKt {
+ method public static android.graphics.Matrix rotationMatrix(float degrees, optional float px, optional float py);
+ method public static android.graphics.Matrix scaleMatrix(optional float sx, optional float sy);
+ method public static inline operator android.graphics.Matrix times(android.graphics.Matrix, android.graphics.Matrix m);
+ method public static android.graphics.Matrix translationMatrix(optional float tx, optional float ty);
+ method public static inline float[] values(android.graphics.Matrix);
+ }
+
+ public final class PaintKt {
+ method public static inline boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat? blendModeCompat);
+ }
+
+ public final class PathKt {
+ method @RequiresApi(19) public static inline infix android.graphics.Path and(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(26) public static Iterable<androidx.core.graphics.PathSegment> flatten(android.graphics.Path, optional float error);
+ method @RequiresApi(19) public static inline operator android.graphics.Path minus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path or(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline operator android.graphics.Path plus(android.graphics.Path, android.graphics.Path p);
+ method @RequiresApi(19) public static inline infix android.graphics.Path xor(android.graphics.Path, android.graphics.Path p);
+ }
+
+ public final class PictureKt {
+ method public static inline android.graphics.Picture record(android.graphics.Picture, int width, int height, kotlin.jvm.functions.Function1<? super android.graphics.Canvas,kotlin.Unit> block);
+ }
+
+ public final class PointKt {
+ method public static inline operator int component1(android.graphics.Point);
+ method public static inline operator float component1(android.graphics.PointF);
+ method public static inline operator int component2(android.graphics.Point);
+ method public static inline operator float component2(android.graphics.PointF);
+ method public static inline operator android.graphics.Point div(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF div(android.graphics.PointF, float scalar);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point minus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF minus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, android.graphics.Point p);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Point plus(android.graphics.Point, int xy);
+ method public static inline operator android.graphics.PointF plus(android.graphics.PointF, float xy);
+ method public static inline operator android.graphics.Point times(android.graphics.Point, float scalar);
+ method public static inline operator android.graphics.PointF times(android.graphics.PointF, float scalar);
+ method public static inline android.graphics.Point toPoint(android.graphics.PointF);
+ method public static inline android.graphics.PointF toPointF(android.graphics.Point);
+ method public static inline operator android.graphics.Point unaryMinus(android.graphics.Point);
+ method public static inline operator android.graphics.PointF unaryMinus(android.graphics.PointF);
+ }
+
+ public final class PorterDuffKt {
+ method public static inline android.graphics.PorterDuffColorFilter toColorFilter(android.graphics.PorterDuff.Mode, int color);
+ method public static inline android.graphics.PorterDuffXfermode toXfermode(android.graphics.PorterDuff.Mode);
+ }
+
+ public final class RectKt {
+ method public static inline infix android.graphics.Rect and(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF and(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator int component1(android.graphics.Rect);
+ method public static inline operator float component1(android.graphics.RectF);
+ method public static inline operator int component2(android.graphics.Rect);
+ method public static inline operator float component2(android.graphics.RectF);
+ method public static inline operator int component3(android.graphics.Rect);
+ method public static inline operator float component3(android.graphics.RectF);
+ method public static inline operator int component4(android.graphics.Rect);
+ method public static inline operator float component4(android.graphics.RectF);
+ method public static inline operator boolean contains(android.graphics.Rect, android.graphics.Point p);
+ method public static inline operator boolean contains(android.graphics.RectF, android.graphics.PointF p);
+ method public static inline operator android.graphics.Region minus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect minus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF minus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline infix android.graphics.Rect or(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.RectF or(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.RectF r);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, int xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, float xy);
+ method public static inline operator android.graphics.Rect plus(android.graphics.Rect, android.graphics.Point xy);
+ method public static inline operator android.graphics.RectF plus(android.graphics.RectF, android.graphics.PointF xy);
+ method public static inline operator android.graphics.Rect times(android.graphics.Rect, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, int factor);
+ method public static inline operator android.graphics.RectF times(android.graphics.RectF, float factor);
+ method public static inline android.graphics.Rect toRect(android.graphics.RectF);
+ method public static inline android.graphics.RectF toRectF(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.Rect);
+ method public static inline android.graphics.Region toRegion(android.graphics.RectF);
+ method public static inline android.graphics.RectF transform(android.graphics.RectF, android.graphics.Matrix m);
+ method public static inline infix android.graphics.Region xor(android.graphics.Rect, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.RectF, android.graphics.RectF r);
+ }
+
+ public final class RegionKt {
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region and(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator boolean contains(android.graphics.Region, android.graphics.Point p);
+ method public static inline void forEach(android.graphics.Region, kotlin.jvm.functions.Function1<? super android.graphics.Rect,kotlin.Unit> action);
+ method public static operator java.util.Iterator<android.graphics.Rect> iterator(android.graphics.Region);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region minus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region not(android.graphics.Region);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region or(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Rect r);
+ method public static inline operator android.graphics.Region plus(android.graphics.Region, android.graphics.Region r);
+ method public static inline operator android.graphics.Region unaryMinus(android.graphics.Region);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Rect r);
+ method public static inline infix android.graphics.Region xor(android.graphics.Region, android.graphics.Region r);
+ }
+
+ public final class ShaderKt {
+ method public static inline void transform(android.graphics.Shader, kotlin.jvm.functions.Function1<? super android.graphics.Matrix,kotlin.Unit> block);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class BitmapDrawableKt {
+ method public static inline android.graphics.drawable.BitmapDrawable toDrawable(android.graphics.Bitmap, android.content.res.Resources resources);
+ }
+
+ public final class ColorDrawableKt {
+ method public static inline android.graphics.drawable.ColorDrawable toDrawable(@ColorInt int);
+ method @RequiresApi(26) public static inline android.graphics.drawable.ColorDrawable toDrawable(android.graphics.Color);
+ }
+
+ public final class DrawableKt {
+ method public static android.graphics.Bitmap toBitmap(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static android.graphics.Bitmap? toBitmapOrNull(android.graphics.drawable.Drawable, optional @Px int width, optional @Px int height, optional android.graphics.Bitmap.Config? config);
+ method public static void updateBounds(android.graphics.drawable.Drawable, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ }
+
+ public final class IconKt {
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toAdaptiveIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.graphics.Bitmap);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(android.net.Uri);
+ method @RequiresApi(26) public static inline android.graphics.drawable.Icon toIcon(byte[]);
+ }
+
+}
+
+package androidx.core.location {
+
+ public final class LocationKt {
+ method public static inline operator double component1(android.location.Location);
+ method public static inline operator double component2(android.location.Location);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class UriKt {
+ method public static java.io.File toFile(android.net.Uri);
+ method public static inline android.net.Uri toUri(String);
+ method public static inline android.net.Uri toUri(java.io.File);
+ }
+
+}
+
+package androidx.core.os {
+
+ public final class BundleKt {
+ method public static android.os.Bundle bundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method public static android.os.Bundle bundleOf();
+ }
+
+ public final class HandlerKt {
+ method public static inline Runnable postAtTime(android.os.Handler, long uptimeMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline Runnable postDelayed(android.os.Handler, long delayInMillis, optional Object? token, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ }
+
+ @RequiresApi(31) public final class OutcomeReceiverKt {
+ method @RequiresApi(31) public static <R, E extends java.lang.Throwable> android.os.OutcomeReceiver<R,E> asOutcomeReceiver(kotlin.coroutines.Continuation<? super R>);
+ }
+
+ public final class PersistableBundleKt {
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf(kotlin.Pair<java.lang.String,?>... pairs);
+ method @RequiresApi(21) public static android.os.PersistableBundle persistableBundleOf();
+ method @RequiresApi(21) public static android.os.PersistableBundle toPersistableBundle(java.util.Map<java.lang.String,?>);
+ }
+
+ public final class TraceKt {
+ method @Deprecated public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class CharSequenceKt {
+ method public static inline boolean isDigitsOnly(CharSequence);
+ method public static inline int trimmedLength(CharSequence);
+ }
+
+ public final class HtmlKt {
+ method public static inline android.text.Spanned parseAsHtml(String, optional int flags, optional android.text.Html.ImageGetter? imageGetter, optional android.text.Html.TagHandler? tagHandler);
+ method public static inline String toHtml(android.text.Spanned, optional int option);
+ }
+
+ public final class LocaleKt {
+ method @RequiresApi(17) public static inline int getLayoutDirection(java.util.Locale);
+ }
+
+ public final class SpannableStringBuilderKt {
+ method public static inline android.text.SpannableStringBuilder backgroundColor(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder bold(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannedString buildSpannedString(kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder color(android.text.SpannableStringBuilder, @ColorInt int color, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object![] spans, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder inSpans(android.text.SpannableStringBuilder, Object span, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder italic(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder scale(android.text.SpannableStringBuilder, float proportion, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder strikeThrough(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder subscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder superscript(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ method public static inline android.text.SpannableStringBuilder underline(android.text.SpannableStringBuilder, kotlin.jvm.functions.Function1<? super android.text.SpannableStringBuilder,kotlin.Unit> builderAction);
+ }
+
+ public final class SpannableStringKt {
+ method public static inline void clearSpans(android.text.Spannable);
+ method public static inline operator void set(android.text.Spannable, int start, int end, Object span);
+ method public static inline operator void set(android.text.Spannable, kotlin.ranges.IntRange range, Object span);
+ method public static inline android.text.Spannable toSpannable(CharSequence);
+ }
+
+ public final class SpannedStringKt {
+ method public static inline <reified T> T![] getSpans(android.text.Spanned, optional int start, optional int end);
+ method public static inline android.text.Spanned toSpanned(CharSequence);
+ }
+
+ public final class StringKt {
+ method public static inline String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.transition {
+
+ public final class TransitionKt {
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener addListener(android.transition.Transition, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onEnd, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onStart, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onCancel, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onResume, optional kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> onPause);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnCancel(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnEnd(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnPause(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnResume(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ method @RequiresApi(19) public static inline android.transition.Transition.TransitionListener doOnStart(android.transition.Transition, kotlin.jvm.functions.Function1<? super android.transition.Transition,kotlin.Unit> action);
+ }
+
+}
+
+package androidx.core.util {
+
+ public final class AndroidXConsumerKt {
+ method public static <T> androidx.core.util.Consumer<T> asAndroidXConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class AtomicFileKt {
+ method @RequiresApi(17) public static inline byte[] readBytes(android.util.AtomicFile);
+ method @RequiresApi(17) public static String readText(android.util.AtomicFile, optional java.nio.charset.Charset charset);
+ method @RequiresApi(17) public static inline void tryWrite(android.util.AtomicFile, kotlin.jvm.functions.Function1<? super java.io.FileOutputStream,kotlin.Unit> block);
+ method @RequiresApi(17) public static void writeBytes(android.util.AtomicFile, byte[] array);
+ method @RequiresApi(17) public static void writeText(android.util.AtomicFile, String text, optional java.nio.charset.Charset charset);
+ }
+
+ @RequiresApi(24) public final class ConsumerKt {
+ method @RequiresApi(24) public static <T> java.util.function.Consumer<T> asConsumer(kotlin.coroutines.Continuation<? super T>);
+ }
+
+ public final class HalfKt {
+ method @RequiresApi(26) public static inline android.util.Half toHalf(@HalfFloat short);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(float);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(double);
+ method @RequiresApi(26) public static inline android.util.Half toHalf(String);
+ }
+
+ public final class LongSparseArrayKt {
+ method @RequiresApi(16) public static inline operator <T> boolean contains(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsKey(android.util.LongSparseArray<T>, long key);
+ method @RequiresApi(16) public static inline <T> boolean containsValue(android.util.LongSparseArray<T>, T? value);
+ method @RequiresApi(16) public static inline <T> void forEach(android.util.LongSparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Long,? super T,kotlin.Unit> action);
+ method @RequiresApi(16) public static inline <T> T! getOrDefault(android.util.LongSparseArray<T>, long key, T? defaultValue);
+ method @RequiresApi(16) public static inline <T> T! getOrElse(android.util.LongSparseArray<T>, long key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method @RequiresApi(16) public static inline <T> int getSize(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static inline <T> boolean isNotEmpty(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static <T> kotlin.collections.LongIterator keyIterator(android.util.LongSparseArray<T>);
+ method @RequiresApi(16) public static operator <T> android.util.LongSparseArray<T> plus(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> void putAll(android.util.LongSparseArray<T>, android.util.LongSparseArray<T> other);
+ method @RequiresApi(16) public static <T> boolean remove(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static inline operator <T> void set(android.util.LongSparseArray<T>, long key, T? value);
+ method @RequiresApi(16) public static <T> java.util.Iterator<T> valueIterator(android.util.LongSparseArray<T>);
+ }
+
+ public final class LruCacheKt {
+ method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, optional kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf, optional kotlin.jvm.functions.Function1<? super K,? extends V> create, optional kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved);
+ }
+
+ public final class PairKt {
+ method public static inline operator <F, S> F! component1(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> F! component1(android.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(androidx.core.util.Pair<F,S>);
+ method public static inline operator <F, S> S! component2(android.util.Pair<F,S>);
+ method public static inline <F, S> android.util.Pair<F,S> toAndroidPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> androidx.core.util.Pair<F,S> toAndroidXPair(kotlin.Pair<? extends F,? extends S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(androidx.core.util.Pair<F,S>);
+ method public static inline <F, S> kotlin.Pair<F,S> toKotlinPair(android.util.Pair<F,S>);
+ }
+
+ public final class RangeKt {
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> and(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, T value);
+ method @RequiresApi(21) public static inline operator <T extends java.lang.Comparable<? super T>> android.util.Range<T> plus(android.util.Range<T>, android.util.Range<T> other);
+ method @RequiresApi(21) public static inline infix <T extends java.lang.Comparable<? super T>> android.util.Range<T> rangeTo(T, T that);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> kotlin.ranges.ClosedRange<T> toClosedRange(android.util.Range<T>);
+ method @RequiresApi(21) public static <T extends java.lang.Comparable<? super T>> android.util.Range<T> toRange(kotlin.ranges.ClosedRange<T>);
+ }
+
+ public final class RunnableKt {
+ method public static Runnable asRunnable(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ }
+
+ public final class SizeKt {
+ method @RequiresApi(21) public static inline operator int component1(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+ method public static inline operator float component1(androidx.core.util.SizeFCompat);
+ method @RequiresApi(21) public static inline operator int component2(android.util.Size);
+ method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+ method public static inline operator float component2(androidx.core.util.SizeFCompat);
+ }
+
+ public final class SparseArrayKt {
+ method public static inline operator <T> boolean contains(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsKey(android.util.SparseArray<T>, int key);
+ method public static inline <T> boolean containsValue(android.util.SparseArray<T>, T? value);
+ method public static inline <T> void forEach(android.util.SparseArray<T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+ method public static inline <T> T! getOrDefault(android.util.SparseArray<T>, int key, T? defaultValue);
+ method public static inline <T> T! getOrElse(android.util.SparseArray<T>, int key, kotlin.jvm.functions.Function0<? extends T> defaultValue);
+ method public static inline <T> int getSize(android.util.SparseArray<T>);
+ method public static inline <T> boolean isEmpty(android.util.SparseArray<T>);
+ method public static inline <T> boolean isNotEmpty(android.util.SparseArray<T>);
+ method public static <T> kotlin.collections.IntIterator keyIterator(android.util.SparseArray<T>);
+ method public static operator <T> android.util.SparseArray<T> plus(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> void putAll(android.util.SparseArray<T>, android.util.SparseArray<T> other);
+ method public static <T> boolean remove(android.util.SparseArray<T>, int key, T? value);
+ method public static inline operator <T> void set(android.util.SparseArray<T>, int key, T? value);
+ method public static <T> java.util.Iterator<T> valueIterator(android.util.SparseArray<T>);
+ }
+
+ public final class SparseBooleanArrayKt {
+ method public static inline operator boolean contains(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsKey(android.util.SparseBooleanArray, int key);
+ method public static inline boolean containsValue(android.util.SparseBooleanArray, boolean value);
+ method public static inline void forEach(android.util.SparseBooleanArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> action);
+ method public static inline boolean getOrDefault(android.util.SparseBooleanArray, int key, boolean defaultValue);
+ method public static inline boolean getOrElse(android.util.SparseBooleanArray, int key, kotlin.jvm.functions.Function0<java.lang.Boolean> defaultValue);
+ method public static inline int getSize(android.util.SparseBooleanArray);
+ method public static inline boolean isEmpty(android.util.SparseBooleanArray);
+ method public static inline boolean isNotEmpty(android.util.SparseBooleanArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseBooleanArray);
+ method public static operator android.util.SparseBooleanArray plus(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static void putAll(android.util.SparseBooleanArray, android.util.SparseBooleanArray other);
+ method public static boolean remove(android.util.SparseBooleanArray, int key, boolean value);
+ method public static inline operator void set(android.util.SparseBooleanArray, int key, boolean value);
+ method public static kotlin.collections.BooleanIterator valueIterator(android.util.SparseBooleanArray);
+ }
+
+ public final class SparseIntArrayKt {
+ method public static inline operator boolean contains(android.util.SparseIntArray, int key);
+ method public static inline boolean containsKey(android.util.SparseIntArray, int key);
+ method public static inline boolean containsValue(android.util.SparseIntArray, int value);
+ method public static inline void forEach(android.util.SparseIntArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline int getOrDefault(android.util.SparseIntArray, int key, int defaultValue);
+ method public static inline int getOrElse(android.util.SparseIntArray, int key, kotlin.jvm.functions.Function0<java.lang.Integer> defaultValue);
+ method public static inline int getSize(android.util.SparseIntArray);
+ method public static inline boolean isEmpty(android.util.SparseIntArray);
+ method public static inline boolean isNotEmpty(android.util.SparseIntArray);
+ method public static kotlin.collections.IntIterator keyIterator(android.util.SparseIntArray);
+ method public static operator android.util.SparseIntArray plus(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static void putAll(android.util.SparseIntArray, android.util.SparseIntArray other);
+ method public static boolean remove(android.util.SparseIntArray, int key, int value);
+ method public static inline operator void set(android.util.SparseIntArray, int key, int value);
+ method public static kotlin.collections.IntIterator valueIterator(android.util.SparseIntArray);
+ }
+
+ public final class SparseLongArrayKt {
+ method @RequiresApi(18) public static inline operator boolean contains(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsKey(android.util.SparseLongArray, int key);
+ method @RequiresApi(18) public static inline boolean containsValue(android.util.SparseLongArray, long value);
+ method @RequiresApi(18) public static inline void forEach(android.util.SparseLongArray, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Long,kotlin.Unit> action);
+ method @RequiresApi(18) public static inline long getOrDefault(android.util.SparseLongArray, int key, long defaultValue);
+ method @RequiresApi(18) public static inline long getOrElse(android.util.SparseLongArray, int key, kotlin.jvm.functions.Function0<java.lang.Long> defaultValue);
+ method @RequiresApi(18) public static inline int getSize(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static inline boolean isNotEmpty(android.util.SparseLongArray);
+ method @RequiresApi(18) public static kotlin.collections.IntIterator keyIterator(android.util.SparseLongArray);
+ method @RequiresApi(18) public static operator android.util.SparseLongArray plus(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static void putAll(android.util.SparseLongArray, android.util.SparseLongArray other);
+ method @RequiresApi(18) public static boolean remove(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static inline operator void set(android.util.SparseLongArray, int key, long value);
+ method @RequiresApi(18) public static kotlin.collections.LongIterator valueIterator(android.util.SparseLongArray);
+ }
+
+}
+
+package androidx.core.view {
+
+ public final class MenuKt {
+ method public static operator boolean contains(android.view.Menu, android.view.MenuItem item);
+ method public static inline void forEach(android.view.Menu, kotlin.jvm.functions.Function1<? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.Menu, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.MenuItem,kotlin.Unit> action);
+ method public static inline operator android.view.MenuItem get(android.view.Menu, int index);
+ method public static kotlin.sequences.Sequence<android.view.MenuItem> getChildren(android.view.Menu);
+ method public static inline int getSize(android.view.Menu);
+ method public static inline boolean isEmpty(android.view.Menu);
+ method public static inline boolean isNotEmpty(android.view.Menu);
+ method public static operator java.util.Iterator<android.view.MenuItem> iterator(android.view.Menu);
+ method public static inline operator void minusAssign(android.view.Menu, android.view.MenuItem item);
+ method public static inline void removeItemAt(android.view.Menu, int index);
+ }
+
+ public final class ViewGroupKt {
+ method public static inline operator boolean contains(android.view.ViewGroup, android.view.View view);
+ method public static inline void forEach(android.view.ViewGroup, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void forEachIndexed(android.view.ViewGroup, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super android.view.View,kotlin.Unit> action);
+ method public static operator android.view.View get(android.view.ViewGroup, int index);
+ method public static kotlin.sequences.Sequence<android.view.View> getChildren(android.view.ViewGroup);
+ method public static kotlin.sequences.Sequence<android.view.View> getDescendants(android.view.ViewGroup);
+ method public static inline kotlin.ranges.IntRange getIndices(android.view.ViewGroup);
+ method public static inline int getSize(android.view.ViewGroup);
+ method public static inline boolean isEmpty(android.view.ViewGroup);
+ method public static inline boolean isNotEmpty(android.view.ViewGroup);
+ method public static operator java.util.Iterator<android.view.View> iterator(android.view.ViewGroup);
+ method public static inline operator void minusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline operator void plusAssign(android.view.ViewGroup, android.view.View view);
+ method public static inline void setMargins(android.view.ViewGroup.MarginLayoutParams, @Px int size);
+ method public static inline void updateMargins(android.view.ViewGroup.MarginLayoutParams, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updateMarginsRelative(android.view.ViewGroup.MarginLayoutParams, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+ public final class ViewKt {
+ method public static inline void doOnAttach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnDetach(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline void doOnNextLayout(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static inline androidx.core.view.OneShotPreDrawListener doOnPreDraw(android.view.View, kotlin.jvm.functions.Function1<? super android.view.View,kotlin.Unit> action);
+ method public static android.graphics.Bitmap drawToBitmap(android.view.View, optional android.graphics.Bitmap.Config config);
+ method public static kotlin.sequences.Sequence<android.view.View> getAllViews(android.view.View);
+ method public static kotlin.sequences.Sequence<android.view.ViewParent> getAncestors(android.view.View);
+ method public static inline int getMarginBottom(android.view.View);
+ method public static inline int getMarginEnd(android.view.View);
+ method public static inline int getMarginLeft(android.view.View);
+ method public static inline int getMarginRight(android.view.View);
+ method public static inline int getMarginStart(android.view.View);
+ method public static inline int getMarginTop(android.view.View);
+ method public static inline boolean isGone(android.view.View);
+ method public static inline boolean isInvisible(android.view.View);
+ method public static inline boolean isVisible(android.view.View);
+ method public static inline Runnable postDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method @RequiresApi(16) public static Runnable postOnAnimationDelayed(android.view.View, long delayInMillis, kotlin.jvm.functions.Function0<kotlin.Unit> action);
+ method public static inline void setGone(android.view.View, boolean);
+ method public static inline void setInvisible(android.view.View, boolean);
+ method public static inline void setPadding(android.view.View, @Px int size);
+ method public static inline void setVisible(android.view.View, boolean);
+ method public static inline void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super android.view.ViewGroup.LayoutParams,kotlin.Unit> block);
+ method public static inline <reified T extends android.view.ViewGroup.LayoutParams> void updateLayoutParams(android.view.View, kotlin.jvm.functions.Function1<? super T,? extends kotlin.Unit> block);
+ method public static inline void updatePadding(android.view.View, optional @Px int left, optional @Px int top, optional @Px int right, optional @Px int bottom);
+ method @RequiresApi(17) public static inline void updatePaddingRelative(android.view.View, optional @Px int start, optional @Px int top, optional @Px int end, optional @Px int bottom);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public final class TextViewKt {
+ method public static inline android.text.TextWatcher addTextChangedListener(android.widget.TextView, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> beforeTextChanged, optional kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> onTextChanged, optional kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> afterTextChanged);
+ method public static inline android.text.TextWatcher doAfterTextChanged(android.widget.TextView, kotlin.jvm.functions.Function1<? super android.text.Editable,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doBeforeTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ method public static inline android.text.TextWatcher doOnTextChanged(android.widget.TextView, kotlin.jvm.functions.Function4<? super java.lang.CharSequence,? super java.lang.Integer,? super java.lang.Integer,? super java.lang.Integer,kotlin.Unit> action);
+ }
+
+}
+
diff --git a/core/core/api/1.10.0-beta01.txt b/core/core/api/1.10.0-beta01.txt
new file mode 100644
index 0000000..f8aa350
--- /dev/null
+++ b/core/core/api/1.10.0-beta01.txt
@@ -0,0 +1,3929 @@
+// Signature format: 4.0
+package androidx.core.accessibilityservice {
+
+ public final class AccessibilityServiceInfoCompat {
+ method public static String capabilityToString(int);
+ method public static String feedbackTypeToString(int);
+ method public static String? flagToString(int);
+ method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
+ method public static String? loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
+ field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
+ field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
+ field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
+ field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
+ field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
+ field public static final int FEEDBACK_BRAILLE = 32; // 0x20
+ field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
+ field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
+ field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
+ field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
+ }
+
+}
+
+package androidx.core.app {
+
+ public class ActivityCompat extends androidx.core.content.ContextCompat {
+ ctor protected ActivityCompat();
+ method public static void finishAffinity(android.app.Activity);
+ method public static void finishAfterTransition(android.app.Activity);
+ method public static android.net.Uri? getReferrer(android.app.Activity);
+ method @Deprecated public static boolean invalidateOptionsMenu(android.app.Activity!);
+ method public static boolean isLaunchedFromBubble(android.app.Activity);
+ method public static void postponeEnterTransition(android.app.Activity);
+ method public static void recreate(android.app.Activity);
+ method public static androidx.core.view.DragAndDropPermissionsCompat? requestDragAndDropPermissions(android.app.Activity, android.view.DragEvent);
+ method public static void requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ method public static <T extends android.view.View> T requireViewById(android.app.Activity, @IdRes int);
+ method public static void setEnterSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setExitSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setLocusContext(android.app.Activity, androidx.core.content.LocusIdCompat?, android.os.Bundle?);
+ method public static void setPermissionCompatDelegate(androidx.core.app.ActivityCompat.PermissionCompatDelegate?);
+ method public static boolean shouldShowRequestPermissionRationale(android.app.Activity, String);
+ method public static void startActivityForResult(android.app.Activity, android.content.Intent, int, android.os.Bundle?);
+ method public static void startIntentSenderForResult(android.app.Activity, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public static void startPostponedEnterTransition(android.app.Activity);
+ }
+
+ public static interface ActivityCompat.OnRequestPermissionsResultCallback {
+ method public void onRequestPermissionsResult(int, String![], int[]);
+ }
+
+ public static interface ActivityCompat.PermissionCompatDelegate {
+ method public boolean onActivityResult(android.app.Activity, @IntRange(from=0) int, int, android.content.Intent?);
+ method public boolean requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ }
+
+ public final class ActivityManagerCompat {
+ method public static boolean isLowRamDevice(android.app.ActivityManager);
+ }
+
+ public class ActivityOptionsCompat {
+ ctor protected ActivityOptionsCompat();
+ method public android.graphics.Rect? getLaunchBounds();
+ method public static androidx.core.app.ActivityOptionsCompat makeBasic();
+ method public static androidx.core.app.ActivityOptionsCompat makeClipRevealAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeCustomAnimation(android.content.Context, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeScaleUpAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, android.view.View, String);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, androidx.core.util.Pair<android.view.View!,java.lang.String!>!...);
+ method public static androidx.core.app.ActivityOptionsCompat makeTaskLaunchBehind();
+ method public static androidx.core.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+ method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public androidx.core.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect?);
+ method public android.os.Bundle? toBundle();
+ method public void update(androidx.core.app.ActivityOptionsCompat);
+ field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
+ field public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
+ }
+
+ public final class AlarmManagerCompat {
+ method public static void setAlarmClock(android.app.AlarmManager, long, android.app.PendingIntent, android.app.PendingIntent);
+ method public static void setAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExact(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExactAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ }
+
+ @RequiresApi(28) public class AppComponentFactory extends android.app.AppComponentFactory {
+ ctor public AppComponentFactory();
+ method public final android.app.Activity instantiateActivity(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Activity instantiateActivityCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Application instantiateApplication(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Application instantiateApplicationCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.ContentProvider instantiateProvider(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.ContentProvider instantiateProviderCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.BroadcastReceiver instantiateReceiver(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.BroadcastReceiver instantiateReceiverCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Service instantiateService(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Service instantiateServiceCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ }
+
+ public class AppLaunchChecker {
+ ctor @Deprecated public AppLaunchChecker();
+ method public static boolean hasStartedFromLauncher(android.content.Context);
+ method public static void onActivityCreate(android.app.Activity);
+ }
+
+ public final class AppOpsManagerCompat {
+ method public static int checkOrNoteProxyOp(android.content.Context, int, String, String);
+ method public static int noteOp(android.content.Context, String, int, String);
+ method public static int noteOpNoThrow(android.content.Context, String, int, String);
+ method public static int noteProxyOp(android.content.Context, String, String);
+ method public static int noteProxyOpNoThrow(android.content.Context, String, String);
+ method public static String? permissionToOp(String);
+ field public static final int MODE_ALLOWED = 0; // 0x0
+ field public static final int MODE_DEFAULT = 3; // 0x3
+ field public static final int MODE_ERRORED = 2; // 0x2
+ field public static final int MODE_IGNORED = 1; // 0x1
+ }
+
+ public final class BundleCompat {
+ method public static android.os.IBinder? getBinder(android.os.Bundle, String?);
+ method public static void putBinder(android.os.Bundle, String?, android.os.IBinder?);
+ }
+
+ public class DialogCompat {
+ method public static android.view.View requireViewById(android.app.Dialog, int);
+ }
+
+ public class FrameMetricsAggregator {
+ ctor public FrameMetricsAggregator();
+ ctor public FrameMetricsAggregator(int);
+ method public void add(android.app.Activity);
+ method public android.util.SparseIntArray![]? getMetrics();
+ method public android.util.SparseIntArray![]? remove(android.app.Activity);
+ method public android.util.SparseIntArray![]? reset();
+ method public android.util.SparseIntArray![]? stop();
+ field public static final int ANIMATION_DURATION = 256; // 0x100
+ field public static final int ANIMATION_INDEX = 8; // 0x8
+ field public static final int COMMAND_DURATION = 32; // 0x20
+ field public static final int COMMAND_INDEX = 5; // 0x5
+ field public static final int DELAY_DURATION = 128; // 0x80
+ field public static final int DELAY_INDEX = 7; // 0x7
+ field public static final int DRAW_DURATION = 8; // 0x8
+ field public static final int DRAW_INDEX = 3; // 0x3
+ field public static final int EVERY_DURATION = 511; // 0x1ff
+ field public static final int INPUT_DURATION = 2; // 0x2
+ field public static final int INPUT_INDEX = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 4; // 0x4
+ field public static final int LAYOUT_MEASURE_INDEX = 2; // 0x2
+ field public static final int SWAP_DURATION = 64; // 0x40
+ field public static final int SWAP_INDEX = 6; // 0x6
+ field public static final int SYNC_DURATION = 16; // 0x10
+ field public static final int SYNC_INDEX = 4; // 0x4
+ field public static final int TOTAL_DURATION = 1; // 0x1
+ field public static final int TOTAL_INDEX = 0; // 0x0
+ }
+
+ @Deprecated public abstract class JobIntentService extends android.app.Service {
+ ctor @Deprecated public JobIntentService();
+ method @Deprecated public static void enqueueWork(android.content.Context, Class<?>, int, android.content.Intent);
+ method @Deprecated public static void enqueueWork(android.content.Context, android.content.ComponentName, int, android.content.Intent);
+ method @Deprecated public boolean isStopped();
+ method @Deprecated public android.os.IBinder! onBind(android.content.Intent);
+ method @Deprecated protected abstract void onHandleWork(android.content.Intent);
+ method @Deprecated public boolean onStopCurrentWork();
+ method @Deprecated public void setInterruptIfStopped(boolean);
+ }
+
+ public final class LocaleManagerCompat {
+ method @AnyThread public static androidx.core.os.LocaleListCompat getSystemLocales(android.content.Context);
+ }
+
+ public final class MultiWindowModeChangedInfo {
+ ctor public MultiWindowModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public MultiWindowModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInMultiWindowMode();
+ }
+
+ public final class NavUtils {
+ method public static android.content.Intent? getParentActivityIntent(android.app.Activity);
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, Class<?>) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static String? getParentActivityName(android.app.Activity);
+ method public static String? getParentActivityName(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void navigateUpFromSameTask(android.app.Activity);
+ method public static void navigateUpTo(android.app.Activity, android.content.Intent);
+ method public static boolean shouldUpRecreateTask(android.app.Activity, android.content.Intent);
+ field public static final String PARENT_ACTIVITY = "android.support.PARENT_ACTIVITY";
+ }
+
+ public class NotificationChannelCompat {
+ method public boolean canBubble();
+ method public boolean canBypassDnd();
+ method public boolean canShowBadge();
+ method public android.media.AudioAttributes? getAudioAttributes();
+ method public String? getConversationId();
+ method public String? getDescription();
+ method public String? getGroup();
+ method public String getId();
+ method public int getImportance();
+ method public int getLightColor();
+ method public int getLockscreenVisibility();
+ method public CharSequence? getName();
+ method public String? getParentChannelId();
+ method public android.net.Uri? getSound();
+ method public long[]? getVibrationPattern();
+ method public boolean isImportantConversation();
+ method public boolean shouldShowLights();
+ method public boolean shouldVibrate();
+ method public androidx.core.app.NotificationChannelCompat.Builder toBuilder();
+ field public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
+ }
+
+ public static class NotificationChannelCompat.Builder {
+ ctor public NotificationChannelCompat.Builder(String, int);
+ method public androidx.core.app.NotificationChannelCompat build();
+ method public androidx.core.app.NotificationChannelCompat.Builder setConversationId(String, String);
+ method public androidx.core.app.NotificationChannelCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setImportance(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightColor(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightsEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setName(CharSequence?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setShowBadge(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setSound(android.net.Uri?, android.media.AudioAttributes?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationPattern(long[]?);
+ }
+
+ public class NotificationChannelGroupCompat {
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getChannels();
+ method public String? getDescription();
+ method public String getId();
+ method public CharSequence? getName();
+ method public boolean isBlocked();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder toBuilder();
+ }
+
+ public static class NotificationChannelGroupCompat.Builder {
+ ctor public NotificationChannelGroupCompat.Builder(String);
+ method public androidx.core.app.NotificationChannelGroupCompat build();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setName(CharSequence?);
+ }
+
+ public class NotificationCompat {
+ ctor @Deprecated public NotificationCompat();
+ method public static androidx.core.app.NotificationCompat.Action? getAction(android.app.Notification, int);
+ method public static int getActionCount(android.app.Notification);
+ method public static boolean getAllowSystemGeneratedContextualActions(android.app.Notification);
+ method public static boolean getAutoCancel(android.app.Notification);
+ method public static int getBadgeIconType(android.app.Notification);
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? getBubbleMetadata(android.app.Notification);
+ method public static String? getCategory(android.app.Notification);
+ method public static String? getChannelId(android.app.Notification);
+ method public static int getColor(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentInfo(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentText(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentTitle(android.app.Notification);
+ method public static android.os.Bundle? getExtras(android.app.Notification);
+ method public static String? getGroup(android.app.Notification);
+ method public static int getGroupAlertBehavior(android.app.Notification);
+ method @RequiresApi(21) public static java.util.List<androidx.core.app.NotificationCompat.Action!> getInvisibleActions(android.app.Notification);
+ method public static boolean getLocalOnly(android.app.Notification);
+ method public static androidx.core.content.LocusIdCompat? getLocusId(android.app.Notification);
+ method public static boolean getOngoing(android.app.Notification);
+ method public static boolean getOnlyAlertOnce(android.app.Notification);
+ method public static java.util.List<androidx.core.app.Person!> getPeople(android.app.Notification);
+ method public static android.app.Notification? getPublicVersion(android.app.Notification);
+ method public static CharSequence? getSettingsText(android.app.Notification);
+ method public static String? getShortcutId(android.app.Notification);
+ method @RequiresApi(19) public static boolean getShowWhen(android.app.Notification);
+ method public static String? getSortKey(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getSubText(android.app.Notification);
+ method public static long getTimeoutAfter(android.app.Notification);
+ method @RequiresApi(19) public static boolean getUsesChronometer(android.app.Notification);
+ method public static int getVisibility(android.app.Notification);
+ method public static boolean isGroupSummary(android.app.Notification);
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
+ field public static final String CATEGORY_ALARM = "alarm";
+ field public static final String CATEGORY_CALL = "call";
+ field public static final String CATEGORY_EMAIL = "email";
+ field public static final String CATEGORY_ERROR = "err";
+ field public static final String CATEGORY_EVENT = "event";
+ field public static final String CATEGORY_LOCATION_SHARING = "location_sharing";
+ field public static final String CATEGORY_MESSAGE = "msg";
+ field public static final String CATEGORY_MISSED_CALL = "missed_call";
+ field public static final String CATEGORY_NAVIGATION = "navigation";
+ field public static final String CATEGORY_PROGRESS = "progress";
+ field public static final String CATEGORY_PROMO = "promo";
+ field public static final String CATEGORY_RECOMMENDATION = "recommendation";
+ field public static final String CATEGORY_REMINDER = "reminder";
+ field public static final String CATEGORY_SERVICE = "service";
+ field public static final String CATEGORY_SOCIAL = "social";
+ field public static final String CATEGORY_STATUS = "status";
+ field public static final String CATEGORY_STOPWATCH = "stopwatch";
+ field public static final String CATEGORY_SYSTEM = "sys";
+ field public static final String CATEGORY_TRANSPORT = "transport";
+ field public static final String CATEGORY_WORKOUT = "workout";
+ field @ColorInt public static final int COLOR_DEFAULT = 0; // 0x0
+ field public static final int DEFAULT_ALL = -1; // 0xffffffff
+ field public static final int DEFAULT_LIGHTS = 4; // 0x4
+ field public static final int DEFAULT_SOUND = 1; // 0x1
+ field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
+ field public static final String EXTRA_ANSWER_INTENT = "android.answerIntent";
+ field public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
+ field public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
+ field public static final String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final String EXTRA_CALL_IS_VIDEO = "android.callIsVideo";
+ field public static final String EXTRA_CALL_PERSON = "android.callPerson";
+ field public static final String EXTRA_CALL_PERSON_COMPAT = "android.callPersonCompat";
+ field public static final String EXTRA_CALL_TYPE = "android.callType";
+ field public static final String EXTRA_CHANNEL_GROUP_ID = "android.intent.extra.CHANNEL_GROUP_ID";
+ field public static final String EXTRA_CHANNEL_ID = "android.intent.extra.CHANNEL_ID";
+ field public static final String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+ field public static final String EXTRA_COLORIZED = "android.colorized";
+ field public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
+ field public static final String EXTRA_COMPAT_TEMPLATE = "androidx.core.app.extra.COMPAT_TEMPLATE";
+ field public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
+ field public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
+ field public static final String EXTRA_DECLINE_INTENT = "android.declineIntent";
+ field public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
+ field public static final String EXTRA_HIDDEN_CONVERSATION_TITLE = "android.hiddenConversationTitle";
+ field public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
+ field public static final String EXTRA_INFO_TEXT = "android.infoText";
+ field public static final String EXTRA_IS_GROUP_CONVERSATION = "android.isGroupConversation";
+ field public static final String EXTRA_LARGE_ICON = "android.largeIcon";
+ field public static final String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
+ field public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final String EXTRA_MESSAGES = "android.messages";
+ field public static final String EXTRA_MESSAGING_STYLE_USER = "android.messagingStyleUser";
+ field public static final String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
+ field public static final String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
+ field @Deprecated public static final String EXTRA_PEOPLE = "android.people";
+ field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
+ field public static final String EXTRA_PICTURE = "android.picture";
+ field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
+ field public static final String EXTRA_PICTURE_ICON = "android.pictureIcon";
+ field public static final String EXTRA_PROGRESS = "android.progress";
+ field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
+ field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
+ field public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+ field public static final String EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED = "android.showBigPictureWhenCollapsed";
+ field public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
+ field public static final String EXTRA_SHOW_WHEN = "android.showWhen";
+ field public static final String EXTRA_SMALL_ICON = "android.icon";
+ field public static final String EXTRA_SUB_TEXT = "android.subText";
+ field public static final String EXTRA_SUMMARY_TEXT = "android.summaryText";
+ field public static final String EXTRA_TEMPLATE = "android.template";
+ field public static final String EXTRA_TEXT = "android.text";
+ field public static final String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final String EXTRA_TITLE = "android.title";
+ field public static final String EXTRA_TITLE_BIG = "android.title.big";
+ field public static final String EXTRA_VERIFICATION_ICON = "android.verificationIcon";
+ field public static final String EXTRA_VERIFICATION_ICON_COMPAT = "android.verificationIconCompat";
+ field public static final String EXTRA_VERIFICATION_TEXT = "android.verificationText";
+ field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
+ field public static final int FLAG_BUBBLE = 4096; // 0x1000
+ field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+ field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
+ field @Deprecated public static final int FLAG_HIGH_PRIORITY = 128; // 0x80
+ field public static final int FLAG_INSISTENT = 4; // 0x4
+ field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
+ field public static final int FLAG_NO_CLEAR = 32; // 0x20
+ field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
+ field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
+ field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
+ field public static final int FOREGROUND_SERVICE_DEFAULT = 0; // 0x0
+ field public static final int FOREGROUND_SERVICE_DEFERRED = 2; // 0x2
+ field public static final int FOREGROUND_SERVICE_IMMEDIATE = 1; // 0x1
+ field public static final int GROUP_ALERT_ALL = 0; // 0x0
+ field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2
+ field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1
+ field public static final String GROUP_KEY_SILENT = "silent";
+ field public static final String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+ field public static final int PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int PRIORITY_HIGH = 1; // 0x1
+ field public static final int PRIORITY_LOW = -1; // 0xffffffff
+ field public static final int PRIORITY_MAX = 2; // 0x2
+ field public static final int PRIORITY_MIN = -2; // 0xfffffffe
+ field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+ field public static final int VISIBILITY_PRIVATE = 0; // 0x0
+ field public static final int VISIBILITY_PUBLIC = 1; // 0x1
+ field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
+ }
+
+ public static class NotificationCompat.Action {
+ ctor public NotificationCompat.Action(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ method public android.app.PendingIntent? getActionIntent();
+ method public boolean getAllowGeneratedReplies();
+ method public androidx.core.app.RemoteInput![]? getDataOnlyRemoteInputs();
+ method public android.os.Bundle getExtras();
+ method @Deprecated public int getIcon();
+ method public androidx.core.graphics.drawable.IconCompat? getIconCompat();
+ method public androidx.core.app.RemoteInput![]? getRemoteInputs();
+ method @androidx.core.app.NotificationCompat.Action.SemanticAction public int getSemanticAction();
+ method public boolean getShowsUserInterface();
+ method public CharSequence? getTitle();
+ method public boolean isAuthenticationRequired();
+ method public boolean isContextual();
+ field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
+ field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa
+ field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
+ field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
+ field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
+ field public static final int SEMANTIC_ACTION_MUTE = 6; // 0x6
+ field public static final int SEMANTIC_ACTION_NONE = 0; // 0x0
+ field public static final int SEMANTIC_ACTION_REPLY = 1; // 0x1
+ field public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9; // 0x9
+ field public static final int SEMANTIC_ACTION_THUMBS_UP = 8; // 0x8
+ field public static final int SEMANTIC_ACTION_UNMUTE = 7; // 0x7
+ field public android.app.PendingIntent? actionIntent;
+ field @Deprecated public int icon;
+ field public CharSequence! title;
+ }
+
+ public static final class NotificationCompat.Action.Builder {
+ ctor public NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.Builder addExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Action.Builder addRemoteInput(androidx.core.app.RemoteInput?);
+ method public androidx.core.app.NotificationCompat.Action build();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Extender);
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.NotificationCompat.Action.Builder setAllowGeneratedReplies(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setAuthenticationRequired(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setContextual(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setSemanticAction(@androidx.core.app.NotificationCompat.Action.SemanticAction int);
+ method public androidx.core.app.NotificationCompat.Action.Builder setShowsUserInterface(boolean);
+ }
+
+ public static interface NotificationCompat.Action.Extender {
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_NONE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_REPLY, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_UNREAD, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_DELETE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_UNMUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_UP, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_DOWN, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_CALL}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.Action.SemanticAction {
+ }
+
+ public static final class NotificationCompat.Action.WearableExtender implements androidx.core.app.NotificationCompat.Action.Extender {
+ ctor public NotificationCompat.Action.WearableExtender();
+ ctor public NotificationCompat.Action.WearableExtender(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ method @Deprecated public CharSequence? getCancelLabel();
+ method @Deprecated public CharSequence? getConfirmLabel();
+ method public boolean getHintDisplayActionInline();
+ method public boolean getHintLaunchesActivity();
+ method @Deprecated public CharSequence? getInProgressLabel();
+ method public boolean isAvailableOffline();
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setCancelLabel(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setConfirmLabel(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintDisplayActionInline(boolean);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setInProgressLabel(CharSequence?);
+ }
+
+ public static class NotificationCompat.BigPictureStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigPictureStyle();
+ ctor public NotificationCompat.BigPictureStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.Bitmap?);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.Bitmap?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setBigContentTitle(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle setContentDescription(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setSummaryText(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle showBigPictureWhenCollapsed(boolean);
+ }
+
+ public static class NotificationCompat.BigTextStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigTextStyle();
+ ctor public NotificationCompat.BigTextStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle bigText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setSummaryText(CharSequence?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata {
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? fromPlatform(android.app.Notification.BubbleMetadata?);
+ method public boolean getAutoExpandBubble();
+ method public android.app.PendingIntent? getDeleteIntent();
+ method @Dimension(unit=androidx.annotation.Dimension.DP) public int getDesiredHeight();
+ method @DimenRes public int getDesiredHeightResId();
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public android.app.PendingIntent? getIntent();
+ method public String? getShortcutId();
+ method public boolean isNotificationSuppressed();
+ method public static android.app.Notification.BubbleMetadata? toPlatform(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata.Builder {
+ ctor @Deprecated public NotificationCompat.BubbleMetadata.Builder();
+ ctor @RequiresApi(30) public NotificationCompat.BubbleMetadata.Builder(String);
+ ctor public NotificationCompat.BubbleMetadata.Builder(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata build();
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeight(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setSuppressNotification(boolean);
+ }
+
+ public static class NotificationCompat.Builder {
+ ctor @RequiresApi(19) public NotificationCompat.Builder(android.content.Context, android.app.Notification);
+ ctor public NotificationCompat.Builder(android.content.Context, String);
+ ctor @Deprecated public NotificationCompat.Builder(android.content.Context);
+ method public androidx.core.app.NotificationCompat.Builder addAction(int, CharSequence?, android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder addAction(androidx.core.app.NotificationCompat.Action?);
+ method public androidx.core.app.NotificationCompat.Builder addExtras(android.os.Bundle?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(int, CharSequence?, android.app.PendingIntent?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(androidx.core.app.NotificationCompat.Action?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder addPerson(String?);
+ method public androidx.core.app.NotificationCompat.Builder addPerson(androidx.core.app.Person?);
+ method public android.app.Notification build();
+ method public androidx.core.app.NotificationCompat.Builder clearActions();
+ method public androidx.core.app.NotificationCompat.Builder clearInvisibleActions();
+ method public androidx.core.app.NotificationCompat.Builder clearPeople();
+ method public android.widget.RemoteViews? createBigContentView();
+ method public android.widget.RemoteViews? createContentView();
+ method public android.widget.RemoteViews? createHeadsUpContentView();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Extender);
+ method public android.os.Bundle getExtras();
+ method @Deprecated public android.app.Notification getNotification();
+ method protected static CharSequence? limitCharSequenceLength(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setAllowSystemGeneratedContextualActions(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setAutoCancel(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setBadgeIconType(int);
+ method public androidx.core.app.NotificationCompat.Builder setBubbleMetadata(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ method public androidx.core.app.NotificationCompat.Builder setCategory(String?);
+ method public androidx.core.app.NotificationCompat.Builder setChannelId(String);
+ method @RequiresApi(24) public androidx.core.app.NotificationCompat.Builder setChronometerCountDown(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.Builder setColorized(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setContent(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setContentInfo(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setContentText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomBigContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomHeadsUpContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setDefaults(int);
+ method public androidx.core.app.NotificationCompat.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Builder setForegroundServiceBehavior(int);
+ method public androidx.core.app.NotificationCompat.Builder setFullScreenIntent(android.app.PendingIntent?, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationCompat.Builder setGroupAlertBehavior(int);
+ method public androidx.core.app.NotificationCompat.Builder setGroupSummary(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLargeIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.Builder setLights(@ColorInt int, int, int);
+ method public androidx.core.app.NotificationCompat.Builder setLocalOnly(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setNotificationSilent();
+ method public androidx.core.app.NotificationCompat.Builder setNumber(int);
+ method public androidx.core.app.NotificationCompat.Builder setOngoing(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setOnlyAlertOnce(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPriority(int);
+ method public androidx.core.app.NotificationCompat.Builder setProgress(int, int, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPublicVersion(android.app.Notification?);
+ method public androidx.core.app.NotificationCompat.Builder setRemoteInputHistory(CharSequence![]?);
+ method public androidx.core.app.NotificationCompat.Builder setSettingsText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutId(String?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutInfo(androidx.core.content.pm.ShortcutInfoCompat?);
+ method public androidx.core.app.NotificationCompat.Builder setShowWhen(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setSilent(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.Builder setSmallIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int, int);
+ method public androidx.core.app.NotificationCompat.Builder setSortKey(String?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?, int);
+ method public androidx.core.app.NotificationCompat.Builder setStyle(androidx.core.app.NotificationCompat.Style?);
+ method public androidx.core.app.NotificationCompat.Builder setSubText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?, android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setTimeoutAfter(long);
+ method public androidx.core.app.NotificationCompat.Builder setUsesChronometer(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setVibrate(long[]?);
+ method public androidx.core.app.NotificationCompat.Builder setVisibility(int);
+ method public androidx.core.app.NotificationCompat.Builder setWhen(long);
+ field @Deprecated public java.util.ArrayList<java.lang.String!>! mPeople;
+ }
+
+ public static class NotificationCompat.CallStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.CallStyle();
+ ctor public NotificationCompat.CallStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public static androidx.core.app.NotificationCompat.CallStyle forIncomingCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forOngoingCall(androidx.core.app.Person, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forScreeningCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method public androidx.core.app.NotificationCompat.CallStyle setAnswerButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setDeclineButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setIsVideo(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationText(CharSequence?);
+ field public static final int CALL_TYPE_INCOMING = 1; // 0x1
+ field public static final int CALL_TYPE_ONGOING = 2; // 0x2
+ field public static final int CALL_TYPE_SCREENING = 3; // 0x3
+ field public static final int CALL_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public static final class NotificationCompat.CarExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.CarExtender();
+ ctor public NotificationCompat.CarExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method @ColorInt public int getColor();
+ method public android.graphics.Bitmap? getLargeIcon();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation? getUnreadConversation();
+ method public androidx.core.app.NotificationCompat.CarExtender setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CarExtender setLargeIcon(android.graphics.Bitmap?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender setUnreadConversation(androidx.core.app.NotificationCompat.CarExtender.UnreadConversation?);
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation {
+ method @Deprecated public long getLatestTimestamp();
+ method @Deprecated public String![]? getMessages();
+ method @Deprecated public String? getParticipant();
+ method @Deprecated public String![]? getParticipants();
+ method @Deprecated public android.app.PendingIntent? getReadPendingIntent();
+ method @Deprecated public androidx.core.app.RemoteInput? getRemoteInput();
+ method @Deprecated public android.app.PendingIntent? getReplyPendingIntent();
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation.Builder {
+ ctor @Deprecated public NotificationCompat.CarExtender.UnreadConversation.Builder(String);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder addMessage(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation build();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setLatestTimestamp(long);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReadPendingIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReplyAction(android.app.PendingIntent?, androidx.core.app.RemoteInput?);
+ }
+
+ public static class NotificationCompat.DecoratedCustomViewStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.DecoratedCustomViewStyle();
+ }
+
+ public static interface NotificationCompat.Extender {
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ }
+
+ public static class NotificationCompat.InboxStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.InboxStyle();
+ ctor public NotificationCompat.InboxStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.InboxStyle addLine(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setSummaryText(CharSequence?);
+ }
+
+ public static class NotificationCompat.MessagingStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor @Deprecated public NotificationCompat.MessagingStyle(CharSequence);
+ ctor public NotificationCompat.MessagingStyle(androidx.core.app.Person);
+ method public void addCompatExtras(android.os.Bundle);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addHistoricMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method @Deprecated public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, androidx.core.app.Person?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method public static androidx.core.app.NotificationCompat.MessagingStyle? extractMessagingStyleFromNotification(android.app.Notification);
+ method public CharSequence? getConversationTitle();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getHistoricMessages();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getMessages();
+ method public androidx.core.app.Person getUser();
+ method @Deprecated public CharSequence? getUserDisplayName();
+ method public boolean isGroupConversation();
+ method public androidx.core.app.NotificationCompat.MessagingStyle setConversationTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle setGroupConversation(boolean);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class NotificationCompat.MessagingStyle.Message {
+ ctor public NotificationCompat.MessagingStyle.Message(CharSequence?, long, androidx.core.app.Person?);
+ ctor @Deprecated public NotificationCompat.MessagingStyle.Message(CharSequence?, long, CharSequence?);
+ method public String? getDataMimeType();
+ method public android.net.Uri? getDataUri();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.Person? getPerson();
+ method @Deprecated public CharSequence? getSender();
+ method public CharSequence? getText();
+ method public long getTimestamp();
+ method public androidx.core.app.NotificationCompat.MessagingStyle.Message setData(String?, android.net.Uri?);
+ }
+
+ public abstract static class NotificationCompat.Style {
+ ctor public NotificationCompat.Style();
+ method public android.app.Notification? build();
+ method public void setBuilder(androidx.core.app.NotificationCompat.Builder?);
+ }
+
+ public static final class NotificationCompat.WearableExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.WearableExtender();
+ ctor public NotificationCompat.WearableExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.WearableExtender addAction(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.WearableExtender addActions(java.util.List<androidx.core.app.NotificationCompat.Action!>);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPage(android.app.Notification);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPages(java.util.List<android.app.Notification!>);
+ method public androidx.core.app.NotificationCompat.WearableExtender clearActions();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender clearPages();
+ method public androidx.core.app.NotificationCompat.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method public java.util.List<androidx.core.app.NotificationCompat.Action!> getActions();
+ method @Deprecated public android.graphics.Bitmap? getBackground();
+ method public String? getBridgeTag();
+ method public int getContentAction();
+ method @Deprecated public int getContentIcon();
+ method @Deprecated public int getContentIconGravity();
+ method public boolean getContentIntentAvailableOffline();
+ method @Deprecated public int getCustomContentHeight();
+ method @Deprecated public int getCustomSizePreset();
+ method public String? getDismissalId();
+ method @Deprecated public android.app.PendingIntent? getDisplayIntent();
+ method @Deprecated public int getGravity();
+ method @Deprecated public boolean getHintAmbientBigPicture();
+ method @Deprecated public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
+ method @Deprecated public boolean getHintHideIcon();
+ method @Deprecated public int getHintScreenTimeout();
+ method @Deprecated public boolean getHintShowBackgroundOnly();
+ method @Deprecated public java.util.List<android.app.Notification!> getPages();
+ method public boolean getStartScrollBottom();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setBackground(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setBridgeTag(String?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentAction(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIcon(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIconGravity(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentIntentAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomContentHeight(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomSizePreset(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setDismissalId(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setDisplayIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setGravity(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAmbientBigPicture(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setHintContentIntentLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintHideIcon(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintScreenTimeout(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintShowBackgroundOnly(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setStartScrollBottom(boolean);
+ field @Deprecated public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff
+ field @Deprecated public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0
+ field @Deprecated public static final int SIZE_DEFAULT = 0; // 0x0
+ field @Deprecated public static final int SIZE_FULL_SCREEN = 5; // 0x5
+ field @Deprecated public static final int SIZE_LARGE = 4; // 0x4
+ field @Deprecated public static final int SIZE_MEDIUM = 3; // 0x3
+ field @Deprecated public static final int SIZE_SMALL = 2; // 0x2
+ field @Deprecated public static final int SIZE_XSMALL = 1; // 0x1
+ field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+ }
+
+ public final class NotificationCompatExtras {
+ field public static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras";
+ field public static final String EXTRA_GROUP_KEY = "android.support.groupKey";
+ field public static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary";
+ field public static final String EXTRA_LOCAL_ONLY = "android.support.localOnly";
+ field public static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs";
+ field public static final String EXTRA_SORT_KEY = "android.support.sortKey";
+ }
+
+ public abstract class NotificationCompatSideChannelService extends android.app.Service {
+ ctor public NotificationCompatSideChannelService();
+ method public abstract void cancel(String!, int, String!);
+ method public abstract void cancelAll(String!);
+ method public abstract void notify(String!, int, String!, android.app.Notification!);
+ method public android.os.IBinder! onBind(android.content.Intent!);
+ }
+
+ public final class NotificationManagerCompat {
+ method public boolean areNotificationsEnabled();
+ method public void cancel(int);
+ method public void cancel(String?, int);
+ method public void cancelAll();
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(androidx.core.app.NotificationChannelCompat);
+ method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+ method public void createNotificationChannelGroup(androidx.core.app.NotificationChannelGroupCompat);
+ method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup!>);
+ method public void createNotificationChannelGroupsCompat(java.util.List<androidx.core.app.NotificationChannelGroupCompat!>);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel!>);
+ method public void createNotificationChannelsCompat(java.util.List<androidx.core.app.NotificationChannelCompat!>);
+ method public void deleteNotificationChannel(String);
+ method public void deleteNotificationChannelGroup(String);
+ method public void deleteUnlistedNotificationChannels(java.util.Collection<java.lang.String!>);
+ method public static androidx.core.app.NotificationManagerCompat from(android.content.Context);
+ method public static java.util.Set<java.lang.String!> getEnabledListenerPackages(android.content.Context);
+ method public int getImportance();
+ method public android.app.NotificationChannel? getNotificationChannel(String);
+ method public android.app.NotificationChannel? getNotificationChannel(String, String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String, String);
+ method public android.app.NotificationChannelGroup? getNotificationChannelGroup(String);
+ method public androidx.core.app.NotificationChannelGroupCompat? getNotificationChannelGroupCompat(String);
+ method public java.util.List<android.app.NotificationChannelGroup!> getNotificationChannelGroups();
+ method public java.util.List<androidx.core.app.NotificationChannelGroupCompat!> getNotificationChannelGroupsCompat();
+ method public java.util.List<android.app.NotificationChannel!> getNotificationChannels();
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getNotificationChannelsCompat();
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(int, android.app.Notification);
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(String?, int, android.app.Notification);
+ field public static final String ACTION_BIND_SIDE_CHANNEL = "android.support.BIND_NOTIFICATION_SIDE_CHANNEL";
+ field public static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
+ field public static final int IMPORTANCE_NONE = 0; // 0x0
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
+ }
+
+ public interface OnMultiWindowModeChangedProvider {
+ method public void addOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ method public void removeOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ }
+
+ public interface OnNewIntentProvider {
+ method public void addOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ method public void removeOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ }
+
+ public interface OnPictureInPictureModeChangedProvider {
+ method public void addOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ method public void removeOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ }
+
+ public final class PendingIntentCompat {
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int, boolean);
+ method @RequiresApi(26) public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int, boolean);
+ }
+
+ public class Person {
+ method public static androidx.core.app.Person fromBundle(android.os.Bundle);
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public String? getKey();
+ method public CharSequence? getName();
+ method public String? getUri();
+ method public boolean isBot();
+ method public boolean isImportant();
+ method public androidx.core.app.Person.Builder toBuilder();
+ method public android.os.Bundle toBundle();
+ }
+
+ public static class Person.Builder {
+ ctor public Person.Builder();
+ method public androidx.core.app.Person build();
+ method public androidx.core.app.Person.Builder setBot(boolean);
+ method public androidx.core.app.Person.Builder setIcon(androidx.core.graphics.drawable.IconCompat?);
+ method public androidx.core.app.Person.Builder setImportant(boolean);
+ method public androidx.core.app.Person.Builder setKey(String?);
+ method public androidx.core.app.Person.Builder setName(CharSequence?);
+ method public androidx.core.app.Person.Builder setUri(String?);
+ }
+
+ public final class PictureInPictureModeChangedInfo {
+ ctor public PictureInPictureModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public PictureInPictureModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInPictureInPictureMode();
+ }
+
+ public final class RemoteActionCompat implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public RemoteActionCompat(androidx.core.graphics.drawable.IconCompat, CharSequence, CharSequence, android.app.PendingIntent);
+ ctor public RemoteActionCompat(androidx.core.app.RemoteActionCompat);
+ method @RequiresApi(26) public static androidx.core.app.RemoteActionCompat createFromRemoteAction(android.app.RemoteAction);
+ method public android.app.PendingIntent getActionIntent();
+ method public CharSequence getContentDescription();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
+ method public CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
+ method public void setShouldShowIcon(boolean);
+ method public boolean shouldShowIcon();
+ method @RequiresApi(26) public android.app.RemoteAction toRemoteAction();
+ }
+
+ public final class RemoteInput {
+ method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+ method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
+ method public boolean getAllowFreeFormInput();
+ method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+ method public CharSequence![]? getChoices();
+ method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
+ method public int getEditChoicesBeforeSending();
+ method public android.os.Bundle getExtras();
+ method public CharSequence? getLabel();
+ method public String getResultKey();
+ method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
+ method public static int getResultsSource(android.content.Intent);
+ method public boolean isDataOnly();
+ method public static void setResultsSource(android.content.Intent, int);
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_AUTO = 0; // 0x0
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_DISABLED = 1; // 0x1
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_ENABLED = 2; // 0x2
+ field public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+ field public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+ field public static final int SOURCE_CHOICE = 1; // 0x1
+ field public static final int SOURCE_FREE_FORM_INPUT = 0; // 0x0
+ }
+
+ public static final class RemoteInput.Builder {
+ ctor public RemoteInput.Builder(String);
+ method public androidx.core.app.RemoteInput.Builder addExtras(android.os.Bundle);
+ method public androidx.core.app.RemoteInput build();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.RemoteInput.Builder setAllowDataType(String, boolean);
+ method public androidx.core.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+ method public androidx.core.app.RemoteInput.Builder setChoices(CharSequence![]?);
+ method public androidx.core.app.RemoteInput.Builder setEditChoicesBeforeSending(int);
+ method public androidx.core.app.RemoteInput.Builder setLabel(CharSequence?);
+ }
+
+ public final class ServiceCompat {
+ method public static void stopForeground(android.app.Service, int);
+ field public static final int START_STICKY = 1; // 0x1
+ field public static final int STOP_FOREGROUND_DETACH = 2; // 0x2
+ field public static final int STOP_FOREGROUND_REMOVE = 1; // 0x1
+ }
+
+ public final class ShareCompat {
+ method @Deprecated public static void configureMenuItem(android.view.MenuItem, androidx.core.app.ShareCompat.IntentBuilder);
+ method @Deprecated public static void configureMenuItem(android.view.Menu, @IdRes int, androidx.core.app.ShareCompat.IntentBuilder);
+ method public static android.content.ComponentName? getCallingActivity(android.app.Activity);
+ method public static String? getCallingPackage(android.app.Activity);
+ field public static final String EXTRA_CALLING_ACTIVITY = "androidx.core.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_ACTIVITY_INTEROP = "android.support.v4.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_PACKAGE = "androidx.core.app.EXTRA_CALLING_PACKAGE";
+ field public static final String EXTRA_CALLING_PACKAGE_INTEROP = "android.support.v4.app.EXTRA_CALLING_PACKAGE";
+ }
+
+ public static class ShareCompat.IntentBuilder {
+ ctor public ShareCompat.IntentBuilder(android.content.Context);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addStream(android.net.Uri);
+ method public android.content.Intent createChooserIntent();
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentBuilder from(android.app.Activity);
+ method public android.content.Intent getIntent();
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(@StringRes int);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailBcc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailCc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailTo(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setHtmlText(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setStream(android.net.Uri?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setSubject(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setText(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setType(String?);
+ method public void startChooser();
+ }
+
+ public static class ShareCompat.IntentReader {
+ ctor public ShareCompat.IntentReader(android.app.Activity);
+ ctor public ShareCompat.IntentReader(android.content.Context, android.content.Intent);
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentReader from(android.app.Activity);
+ method public android.content.ComponentName? getCallingActivity();
+ method public android.graphics.drawable.Drawable? getCallingActivityIcon();
+ method public android.graphics.drawable.Drawable? getCallingApplicationIcon();
+ method public CharSequence? getCallingApplicationLabel();
+ method public String? getCallingPackage();
+ method public String![]? getEmailBcc();
+ method public String![]? getEmailCc();
+ method public String![]? getEmailTo();
+ method public String? getHtmlText();
+ method public android.net.Uri? getStream();
+ method public android.net.Uri? getStream(int);
+ method public int getStreamCount();
+ method public String? getSubject();
+ method public CharSequence? getText();
+ method public String? getType();
+ method public boolean isMultipleShare();
+ method public boolean isShareIntent();
+ method public boolean isSingleShare();
+ }
+
+ public abstract class SharedElementCallback {
+ ctor public SharedElementCallback();
+ method public android.os.Parcelable! onCaptureSharedElementSnapshot(android.view.View!, android.graphics.Matrix!, android.graphics.RectF!);
+ method public android.view.View! onCreateSnapshotView(android.content.Context!, android.os.Parcelable!);
+ method public void onMapSharedElements(java.util.List<java.lang.String!>!, java.util.Map<java.lang.String!,android.view.View!>!);
+ method public void onRejectSharedElements(java.util.List<android.view.View!>!);
+ method public void onSharedElementEnd(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementStart(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementsArrived(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, androidx.core.app.SharedElementCallback.OnSharedElementsReadyListener!);
+ }
+
+ public static interface SharedElementCallback.OnSharedElementsReadyListener {
+ method public void onSharedElementsReady();
+ }
+
+ public final class TaskStackBuilder implements java.lang.Iterable<android.content.Intent> {
+ method public androidx.core.app.TaskStackBuilder addNextIntent(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
+ method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
+ method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
+ method public android.content.Intent? editIntentAt(int);
+ method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
+ method @Deprecated public android.content.Intent! getIntent(int);
+ method public int getIntentCount();
+ method public android.content.Intent![] getIntents();
+ method public android.app.PendingIntent? getPendingIntent(int, int);
+ method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
+ method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
+ method public void startActivities();
+ method public void startActivities(android.os.Bundle?);
+ }
+
+ public static interface TaskStackBuilder.SupportParentable {
+ method public android.content.Intent? getSupportParentActivityIntent();
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentProviderCompat {
+ method public static android.content.Context requireContext(android.content.ContentProvider);
+ }
+
+ public final class ContentResolverCompat {
+ method public static android.database.Cursor? query(android.content.ContentResolver, android.net.Uri, String![]?, String?, String![]?, String?, androidx.core.os.CancellationSignal?);
+ }
+
+ public class ContextCompat {
+ ctor protected ContextCompat();
+ method public static int checkSelfPermission(android.content.Context, String);
+ method public static android.content.Context? createDeviceProtectedStorageContext(android.content.Context);
+ method public static String? getAttributionTag(android.content.Context);
+ method public static java.io.File getCodeCacheDir(android.content.Context);
+ method @ColorInt public static int getColor(android.content.Context, @ColorRes int);
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.Context, @ColorRes int);
+ method public static java.io.File? getDataDir(android.content.Context);
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.Context, @DrawableRes int);
+ method public static java.io.File![] getExternalCacheDirs(android.content.Context);
+ method public static java.io.File![] getExternalFilesDirs(android.content.Context, String?);
+ method public static java.util.concurrent.Executor getMainExecutor(android.content.Context);
+ method public static java.io.File? getNoBackupFilesDir(android.content.Context);
+ method public static java.io.File![] getObbDirs(android.content.Context);
+ method public static <T> T? getSystemService(android.content.Context, Class<T!>);
+ method public static String? getSystemServiceName(android.content.Context, Class<?>);
+ method public static boolean isDeviceProtectedStorage(android.content.Context);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![]);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
+ method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
+ method public static void startForegroundService(android.content.Context, android.content.Intent);
+ field public static final int RECEIVER_EXPORTED = 2; // 0x2
+ field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+ field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
+ }
+
+ public class FileProvider extends android.content.ContentProvider {
+ ctor public FileProvider();
+ ctor protected FileProvider(@XmlRes int);
+ method public int delete(android.net.Uri, String?, String![]?);
+ method public String? getType(android.net.Uri);
+ method public static android.net.Uri! getUriForFile(android.content.Context, String, java.io.File);
+ method public static android.net.Uri getUriForFile(android.content.Context, String, java.io.File, String);
+ method public android.net.Uri! insert(android.net.Uri, android.content.ContentValues);
+ method public boolean onCreate();
+ method public android.database.Cursor query(android.net.Uri, String![]?, String?, String![]?, String?);
+ method public int update(android.net.Uri, android.content.ContentValues, String?, String![]?);
+ }
+
+ public final class IntentCompat {
+ method public static android.content.Intent createManageUnusedAppRestrictionsIntent(android.content.Context, String);
+ method public static android.os.Parcelable![]? getParcelableArrayExtra(android.content.Intent, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayListExtra(android.content.Intent, String?, Class<? extends T>);
+ method public static <T> T? getParcelableExtra(android.content.Intent, String?, Class<T!>);
+ method public static android.content.Intent makeMainSelectorActivity(String, String);
+ field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
+ field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
+ field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
+ field public static final String EXTRA_TIME = "android.intent.extra.TIME";
+ }
+
+ public class IntentSanitizer {
+ method public android.content.Intent sanitize(android.content.Intent, androidx.core.util.Consumer<java.lang.String!>);
+ method public android.content.Intent sanitizeByFiltering(android.content.Intent);
+ method public android.content.Intent sanitizeByThrowing(android.content.Intent);
+ }
+
+ public static final class IntentSanitizer.Builder {
+ ctor public IntentSanitizer.Builder();
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowAnyComponent();
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipData(androidx.core.util.Predicate<android.content.ClipData!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataText();
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUri(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(android.content.ComponentName);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(androidx.core.util.Predicate<android.content.ComponentName!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponentWithPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowData(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowDataWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<?>);
+ method public <T> androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<T!>, androidx.core.util.Predicate<T!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, androidx.core.util.Predicate<java.lang.Object!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStream(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStreamUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowFlags(int);
+ method public androidx.core.content.IntentSanitizer.Builder allowHistoryStackFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowIdentifier();
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowReceiverFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowSelector();
+ method public androidx.core.content.IntentSanitizer.Builder allowSourceBounds();
+ method public androidx.core.content.IntentSanitizer.Builder allowType(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowType(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer build();
+ }
+
+ public final class LocusIdCompat {
+ ctor public LocusIdCompat(String);
+ method public String getId();
+ method @RequiresApi(29) public android.content.LocusId toLocusId();
+ method @RequiresApi(29) public static androidx.core.content.LocusIdCompat toLocusIdCompat(android.content.LocusId);
+ }
+
+ public final class MimeTypeFilter {
+ method public static boolean matches(String?, String);
+ method public static String? matches(String?, String![]);
+ method public static String? matches(String![]?, String);
+ method public static String![] matchesMany(String![]?, String);
+ }
+
+ public interface OnConfigurationChangedProvider {
+ method public void addOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ method public void removeOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ }
+
+ public interface OnTrimMemoryProvider {
+ method public void addOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ method public void removeOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ }
+
+ public final class PackageManagerCompat {
+ method public static com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> getUnusedAppRestrictionsStatus(android.content.Context);
+ field public static final String ACTION_PERMISSION_REVOCATION_SETTINGS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
+ }
+
+ public final class PermissionChecker {
+ method public static int checkCallingOrSelfPermission(android.content.Context, String);
+ method public static int checkCallingPermission(android.content.Context, String, String?);
+ method public static int checkPermission(android.content.Context, String, int, int, String?);
+ method public static int checkSelfPermission(android.content.Context, String);
+ field public static final int PERMISSION_DENIED = -1; // 0xffffffff
+ field public static final int PERMISSION_DENIED_APP_OP = -2; // 0xfffffffe
+ field public static final int PERMISSION_GRANTED = 0; // 0x0
+ }
+
+ @Deprecated public final class SharedPreferencesCompat {
+ }
+
+ @Deprecated public static final class SharedPreferencesCompat.EditorCompat {
+ method @Deprecated public void apply(android.content.SharedPreferences.Editor);
+ method @Deprecated public static androidx.core.content.SharedPreferencesCompat.EditorCompat! getInstance();
+ }
+
+ public class UnusedAppRestrictionsBackportCallback {
+ method public void onResult(boolean, boolean) throws android.os.RemoteException;
+ }
+
+ public abstract class UnusedAppRestrictionsBackportService extends android.app.Service {
+ ctor public UnusedAppRestrictionsBackportService();
+ method protected abstract void isPermissionRevocationEnabled(androidx.core.content.UnusedAppRestrictionsBackportCallback);
+ method public android.os.IBinder? onBind(android.content.Intent?);
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS_BACKPORT_CONNECTION = "android.support.unusedapprestrictions.action.CustomUnusedAppRestrictionsBackportService";
+ }
+
+ public final class UnusedAppRestrictionsConstants {
+ field public static final int API_30 = 4; // 0x4
+ field public static final int API_30_BACKPORT = 3; // 0x3
+ field public static final int API_31 = 5; // 0x5
+ field public static final int DISABLED = 2; // 0x2
+ field public static final int ERROR = 0; // 0x0
+ field public static final int FEATURE_NOT_AVAILABLE = 1; // 0x1
+ }
+
+ public class UriMatcherCompat {
+ method public static androidx.core.util.Predicate<android.net.Uri!> asPredicate(android.content.UriMatcher);
+ }
+
+}
+
+package androidx.core.content.pm {
+
+ @Deprecated public final class ActivityInfoCompat {
+ field @Deprecated public static final int CONFIG_UI_MODE = 512; // 0x200
+ }
+
+ public final class PackageInfoCompat {
+ method public static long getLongVersionCode(android.content.pm.PackageInfo);
+ method public static java.util.List<android.content.pm.Signature!> getSignatures(android.content.pm.PackageManager, String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static boolean hasSignatures(android.content.pm.PackageManager, String, @Size(min=1) java.util.Map<byte[]!,java.lang.Integer!>, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
+ }
+
+ public final class PermissionInfoCompat {
+ method public static int getProtection(android.content.pm.PermissionInfo);
+ method public static int getProtectionFlags(android.content.pm.PermissionInfo);
+ }
+
+ public class ShortcutInfoCompat {
+ method public android.content.ComponentName? getActivity();
+ method public java.util.Set<java.lang.String!>? getCategories();
+ method public CharSequence? getDisabledMessage();
+ method public int getDisabledReason();
+ method public int getExcludedFromSurfaces();
+ method public android.os.PersistableBundle? getExtras();
+ method public String getId();
+ method public android.content.Intent getIntent();
+ method public android.content.Intent![] getIntents();
+ method public long getLastChangedTimestamp();
+ method public androidx.core.content.LocusIdCompat? getLocusId();
+ method public CharSequence? getLongLabel();
+ method public String getPackage();
+ method public int getRank();
+ method public CharSequence getShortLabel();
+ method public android.os.UserHandle? getUserHandle();
+ method public boolean hasKeyFieldsOnly();
+ method public boolean isCached();
+ method public boolean isDeclaredInManifest();
+ method public boolean isDynamic();
+ method public boolean isEnabled();
+ method public boolean isExcludedFromSurfaces(int);
+ method public boolean isImmutable();
+ method public boolean isPinned();
+ method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+ field public static final int SURFACE_LAUNCHER = 1; // 0x1
+ }
+
+ public static class ShortcutInfoCompat.Builder {
+ ctor public ShortcutInfoCompat.Builder(android.content.Context, String);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String, String, java.util.List<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat build();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setActivity(android.content.ComponentName);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedFromSurfaces(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
+ method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived(boolean);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPerson(androidx.core.app.Person);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPersons(androidx.core.app.Person![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setRank(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setShortLabel(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setSliceUri(android.net.Uri);
+ }
+
+ public class ShortcutManagerCompat {
+ method public static boolean addDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static android.content.Intent createShortcutResultIntent(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void disableShortcuts(android.content.Context, java.util.List<java.lang.String!>, CharSequence?);
+ method public static void enableShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getDynamicShortcuts(android.content.Context);
+ method public static int getIconMaxHeight(android.content.Context);
+ method public static int getIconMaxWidth(android.content.Context);
+ method public static int getMaxShortcutCountPerActivity(android.content.Context);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getShortcuts(android.content.Context, int);
+ method public static boolean isRateLimitingActive(android.content.Context);
+ method public static boolean isRequestPinShortcutSupported(android.content.Context);
+ method public static boolean pushDynamicShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void removeAllDynamicShortcuts(android.content.Context);
+ method public static void removeDynamicShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void removeLongLivedShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void reportShortcutUsed(android.content.Context, String);
+ method public static boolean requestPinShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat, android.content.IntentSender?);
+ method public static boolean setDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static boolean updateShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ field public static final String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID";
+ field public static final int FLAG_MATCH_CACHED = 8; // 0x8
+ field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
+ field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
+ field public static final int FLAG_MATCH_PINNED = 4; // 0x4
+ }
+
+}
+
+package androidx.core.content.res {
+
+ public final class ConfigurationHelper {
+ method public static int getDensityDpi(android.content.res.Resources);
+ }
+
+ public final class ResourcesCompat {
+ method public static void clearCachesForTheme(android.content.res.Resources.Theme);
+ method public static android.graphics.Typeface? getCachedFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method @ColorInt public static int getColor(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.res.Resources, @DrawableRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawableForDensity(android.content.res.Resources, @DrawableRes int, int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static float getFloat(android.content.res.Resources, @DimenRes int);
+ method public static android.graphics.Typeface? getFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method public static void getFont(android.content.Context, @FontRes int, androidx.core.content.res.ResourcesCompat.FontCallback, android.os.Handler?) throws android.content.res.Resources.NotFoundException;
+ field @AnyRes public static final int ID_NULL = 0; // 0x0
+ }
+
+ public abstract static class ResourcesCompat.FontCallback {
+ ctor public ResourcesCompat.FontCallback();
+ method public abstract void onFontRetrievalFailed(int);
+ method public abstract void onFontRetrieved(android.graphics.Typeface);
+ }
+
+ public static final class ResourcesCompat.ThemeCompat {
+ method public static void rebase(android.content.res.Resources.Theme);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorWindowCompat {
+ method public static android.database.CursorWindow create(String?, long);
+ }
+
+ @Deprecated public final class DatabaseUtilsCompat {
+ method @Deprecated public static String![]! appendSelectionArgs(String![]!, String![]!);
+ method @Deprecated public static String! concatenateWhere(String!, String!);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteCursorCompat {
+ method public static void setFillWindowForwardOnly(android.database.sqlite.SQLiteCursor, boolean);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapCompat {
+ method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, android.graphics.Rect?, boolean);
+ method public static int getAllocationByteCount(android.graphics.Bitmap);
+ method public static boolean hasMipMap(android.graphics.Bitmap);
+ method public static void setHasMipMap(android.graphics.Bitmap, boolean);
+ }
+
+ public class BlendModeColorFilterCompat {
+ method public static android.graphics.ColorFilter? createBlendModeColorFilterCompat(int, androidx.core.graphics.BlendModeCompat);
+ }
+
+ public enum BlendModeCompat {
+ enum_constant public static final androidx.core.graphics.BlendModeCompat CLEAR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_BURN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_DODGE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DARKEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat DIFFERENCE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OVER;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat EXCLUSION;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HARD_LIGHT;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HUE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat LIGHTEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat LUMINOSITY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat MODULATE;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat MULTIPLY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat OVERLAY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat PLUS;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SATURATION;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SCREEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SOFT_LIGHT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OVER;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat XOR;
+ }
+
+ public final class ColorUtils {
+ method @ColorInt public static int HSLToColor(float[]);
+ method @ColorInt public static int LABToColor(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double);
+ method public static void LABToXYZ(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double, double[]);
+ method public static void RGBToHSL(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, float[]);
+ method public static void RGBToLAB(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method public static void RGBToXYZ(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method @ColorInt public static int XYZToColor(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double);
+ method public static void XYZToLAB(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double, double[]);
+ method @ColorInt public static int blendARGB(@ColorInt int, @ColorInt int, @FloatRange(from=0.0, to=1.0) float);
+ method public static void blendHSL(float[], float[], @FloatRange(from=0.0, to=1.0) float, float[]);
+ method public static void blendLAB(double[], double[], @FloatRange(from=0.0, to=1.0) double, double[]);
+ method public static double calculateContrast(@ColorInt int, @ColorInt int);
+ method @FloatRange(from=0.0, to=1.0) public static double calculateLuminance(@ColorInt int);
+ method public static int calculateMinimumAlpha(@ColorInt int, @ColorInt int, float);
+ method public static void colorToHSL(@ColorInt int, float[]);
+ method public static void colorToLAB(@ColorInt int, double[]);
+ method public static void colorToXYZ(@ColorInt int, double[]);
+ method public static int compositeColors(@ColorInt int, @ColorInt int);
+ method @RequiresApi(26) public static android.graphics.Color compositeColors(android.graphics.Color, android.graphics.Color);
+ method public static double distanceEuclidean(double[], double[]);
+ method @ColorInt public static int setAlphaComponent(@ColorInt int, @IntRange(from=0, to=255) int);
+ }
+
+ public final class Insets {
+ method public static androidx.core.graphics.Insets add(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets max(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets min(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets of(int, int, int, int);
+ method public static androidx.core.graphics.Insets of(android.graphics.Rect);
+ method public static androidx.core.graphics.Insets subtract(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method @RequiresApi(api=29) public static androidx.core.graphics.Insets toCompatInsets(android.graphics.Insets);
+ method @RequiresApi(29) public android.graphics.Insets toPlatformInsets();
+ field public static final androidx.core.graphics.Insets NONE;
+ field public final int bottom;
+ field public final int left;
+ field public final int right;
+ field public final int top;
+ }
+
+ public final class PaintCompat {
+ method public static boolean hasGlyph(android.graphics.Paint, String);
+ method public static boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat?);
+ }
+
+ public final class PathSegment {
+ ctor public PathSegment(android.graphics.PointF, float, android.graphics.PointF, float);
+ method public android.graphics.PointF getEnd();
+ method public float getEndFraction();
+ method public android.graphics.PointF getStart();
+ method public float getStartFraction();
+ }
+
+ public final class PathUtils {
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path);
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path, @FloatRange(from=0) float);
+ }
+
+ public class TypefaceCompat {
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, int);
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, @IntRange(from=1, to=1000) int, boolean);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class DrawableCompat {
+ method public static void applyTheme(android.graphics.drawable.Drawable, android.content.res.Resources.Theme);
+ method public static boolean canApplyTheme(android.graphics.drawable.Drawable);
+ method public static void clearColorFilter(android.graphics.drawable.Drawable);
+ method public static int getAlpha(android.graphics.drawable.Drawable);
+ method public static android.graphics.ColorFilter? getColorFilter(android.graphics.drawable.Drawable);
+ method public static int getLayoutDirection(android.graphics.drawable.Drawable);
+ method public static void inflate(android.graphics.drawable.Drawable, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
+ method @Deprecated public static void jumpToCurrentState(android.graphics.drawable.Drawable);
+ method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
+ method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
+ method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
+ method public static boolean setLayoutDirection(android.graphics.drawable.Drawable, int);
+ method public static void setTint(android.graphics.drawable.Drawable, @ColorInt int);
+ method public static void setTintList(android.graphics.drawable.Drawable, android.content.res.ColorStateList?);
+ method public static void setTintMode(android.graphics.drawable.Drawable, android.graphics.PorterDuff.Mode?);
+ method public static <T extends android.graphics.drawable.Drawable> T! unwrap(android.graphics.drawable.Drawable);
+ method public static android.graphics.drawable.Drawable wrap(android.graphics.drawable.Drawable);
+ }
+
+ public class IconCompat implements androidx.versionedparcelable.VersionedParcelable {
+ method public static androidx.core.graphics.drawable.IconCompat? createFromBundle(android.os.Bundle);
+ method @RequiresApi(23) public static androidx.core.graphics.drawable.IconCompat? createFromIcon(android.content.Context, android.graphics.drawable.Icon);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithData(byte[], int, int);
+ method public static androidx.core.graphics.drawable.IconCompat createWithResource(android.content.Context, @DrawableRes int);
+ method @DrawableRes public int getResId();
+ method public String getResPackage();
+ method public int getType();
+ method public android.net.Uri getUri();
+ method public android.graphics.drawable.Drawable? loadDrawable(android.content.Context);
+ method public void onPostParceling();
+ method public void onPreParceling(boolean);
+ method public androidx.core.graphics.drawable.IconCompat setTint(@ColorInt int);
+ method public androidx.core.graphics.drawable.IconCompat setTintList(android.content.res.ColorStateList?);
+ method public androidx.core.graphics.drawable.IconCompat setTintMode(android.graphics.PorterDuff.Mode?);
+ method public android.os.Bundle toBundle();
+ method @Deprecated @RequiresApi(23) public android.graphics.drawable.Icon toIcon();
+ method @RequiresApi(23) public android.graphics.drawable.Icon toIcon(android.content.Context?);
+ field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5
+ field public static final int TYPE_BITMAP = 1; // 0x1
+ field public static final int TYPE_DATA = 3; // 0x3
+ field public static final int TYPE_RESOURCE = 2; // 0x2
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ field public static final int TYPE_URI = 4; // 0x4
+ field public static final int TYPE_URI_ADAPTIVE_BITMAP = 6; // 0x6
+ }
+
+ public abstract class RoundedBitmapDrawable extends android.graphics.drawable.Drawable {
+ method public void draw(android.graphics.Canvas);
+ method public final android.graphics.Bitmap? getBitmap();
+ method public float getCornerRadius();
+ method public int getGravity();
+ method public int getOpacity();
+ method public final android.graphics.Paint getPaint();
+ method public boolean hasAntiAlias();
+ method public boolean hasMipMap();
+ method public boolean isCircular();
+ method public void setAlpha(int);
+ method public void setAntiAlias(boolean);
+ method public void setCircular(boolean);
+ method public void setColorFilter(android.graphics.ColorFilter!);
+ method public void setCornerRadius(float);
+ method public void setDither(boolean);
+ method public void setGravity(int);
+ method public void setMipMap(boolean);
+ method public void setTargetDensity(android.graphics.Canvas);
+ method public void setTargetDensity(android.util.DisplayMetrics);
+ method public void setTargetDensity(int);
+ }
+
+ public final class RoundedBitmapDrawableFactory {
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, android.graphics.Bitmap?);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, String);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, java.io.InputStream);
+ }
+
+}
+
+package androidx.core.hardware.display {
+
+ public final class DisplayManagerCompat {
+ method public android.view.Display? getDisplay(int);
+ method public android.view.Display![] getDisplays();
+ method public android.view.Display![] getDisplays(String?);
+ method public static androidx.core.hardware.display.DisplayManagerCompat getInstance(android.content.Context);
+ field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+ }
+
+}
+
+package androidx.core.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManagerCompat {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public void authenticate(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject?, int, androidx.core.os.CancellationSignal?, androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationCallback, android.os.Handler?);
+ method @Deprecated public static androidx.core.hardware.fingerprint.FingerprintManagerCompat from(android.content.Context);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected();
+ }
+
+ @Deprecated public abstract static class FingerprintManagerCompat.AuthenticationCallback {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationCallback();
+ method @Deprecated public void onAuthenticationError(int, CharSequence!);
+ method @Deprecated public void onAuthenticationFailed();
+ method @Deprecated public void onAuthenticationHelp(int, CharSequence!);
+ method @Deprecated public void onAuthenticationSucceeded(androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationResult!);
+ }
+
+ @Deprecated public static final class FingerprintManagerCompat.AuthenticationResult {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationResult(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject!);
+ method @Deprecated public androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject! getCryptoObject();
+ }
+
+ @Deprecated public static class FingerprintManagerCompat.CryptoObject {
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(java.security.Signature);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Cipher);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Mac);
+ method @Deprecated public javax.crypto.Cipher? getCipher();
+ method @Deprecated public javax.crypto.Mac? getMac();
+ method @Deprecated public java.security.Signature? getSignature();
+ }
+
+}
+
+package androidx.core.location {
+
+ public abstract class GnssStatusCompat {
+ method @FloatRange(from=0, to=360) public abstract float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public abstract float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getCn0DbHz(@IntRange(from=0) int);
+ method public abstract int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public abstract float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public abstract int getSatelliteCount();
+ method @IntRange(from=1, to=200) public abstract int getSvid(@IntRange(from=0) int);
+ method public abstract boolean hasAlmanacData(@IntRange(from=0) int);
+ method public abstract boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public abstract boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public abstract boolean hasEphemerisData(@IntRange(from=0) int);
+ method public abstract boolean usedInFix(@IntRange(from=0) int);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static androidx.core.location.GnssStatusCompat wrap(android.location.GnssStatus);
+ method public static androidx.core.location.GnssStatusCompat wrap(android.location.GpsStatus);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssStatusCompat.Callback {
+ ctor public GnssStatusCompat.Callback();
+ method public void onFirstFix(@IntRange(from=0) int);
+ method public void onSatelliteStatusChanged(androidx.core.location.GnssStatusCompat);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public final class LocationCompat {
+ method public static float getBearingAccuracyDegrees(android.location.Location);
+ method public static long getElapsedRealtimeMillis(android.location.Location);
+ method public static long getElapsedRealtimeNanos(android.location.Location);
+ method @FloatRange(from=0.0) public static float getMslAltitudeAccuracyMeters(android.location.Location);
+ method public static double getMslAltitudeMeters(android.location.Location);
+ method public static float getSpeedAccuracyMetersPerSecond(android.location.Location);
+ method public static float getVerticalAccuracyMeters(android.location.Location);
+ method public static boolean hasBearingAccuracy(android.location.Location);
+ method public static boolean hasMslAltitude(android.location.Location);
+ method public static boolean hasMslAltitudeAccuracy(android.location.Location);
+ method public static boolean hasSpeedAccuracy(android.location.Location);
+ method public static boolean hasVerticalAccuracy(android.location.Location);
+ method public static boolean isMock(android.location.Location);
+ method public static void removeMslAltitude(android.location.Location);
+ method public static void removeMslAltitudeAccuracy(android.location.Location);
+ method public static void setBearingAccuracyDegrees(android.location.Location, float);
+ method public static void setMock(android.location.Location, boolean);
+ method public static void setMslAltitudeAccuracyMeters(android.location.Location, @FloatRange(from=0.0) float);
+ method public static void setMslAltitudeMeters(android.location.Location, double);
+ method public static void setSpeedAccuracyMetersPerSecond(android.location.Location, float);
+ method public static void setVerticalAccuracyMeters(android.location.Location, float);
+ field public static final String EXTRA_BEARING_ACCURACY = "bearingAccuracy";
+ field public static final String EXTRA_IS_MOCK = "mockLocation";
+ field public static final String EXTRA_MSL_ALTITUDE = "androidx.core.location.extra.MSL_ALTITUDE";
+ field public static final String EXTRA_MSL_ALTITUDE_ACCURACY = "androidx.core.location.extra.MSL_ALTITUDE_ACCURACY";
+ field public static final String EXTRA_SPEED_ACCURACY = "speedAccuracy";
+ field public static final String EXTRA_VERTICAL_ACCURACY = "verticalAccuracy";
+ }
+
+ public interface LocationListenerCompat extends android.location.LocationListener {
+ method public default void onStatusChanged(String, int, android.os.Bundle?);
+ }
+
+ public final class LocationManagerCompat {
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void getCurrentLocation(android.location.LocationManager, String, androidx.core.os.CancellationSignal?, java.util.concurrent.Executor, androidx.core.util.Consumer<android.location.Location!>);
+ method public static String? getGnssHardwareModelName(android.location.LocationManager);
+ method public static int getGnssYearOfHardware(android.location.LocationManager);
+ method public static boolean hasProvider(android.location.LocationManager, String);
+ method public static boolean isLocationEnabled(android.location.LocationManager);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback, android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, java.util.concurrent.Executor, androidx.core.location.GnssStatusCompat.Callback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void removeUpdates(android.location.LocationManager, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, java.util.concurrent.Executor, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, androidx.core.location.LocationListenerCompat, android.os.Looper);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static void unregisterGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback);
+ method public static void unregisterGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback);
+ }
+
+ public final class LocationRequestCompat {
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method @RequiresApi(31) public android.location.LocationRequest toLocationRequest();
+ method @RequiresApi(19) public android.location.LocationRequest? toLocationRequest(String);
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequestCompat.Builder {
+ ctor public LocationRequestCompat.Builder(long);
+ ctor public LocationRequestCompat.Builder(androidx.core.location.LocationRequestCompat);
+ method public androidx.core.location.LocationRequestCompat build();
+ method public androidx.core.location.LocationRequestCompat.Builder clearMinUpdateIntervalMillis();
+ method public androidx.core.location.LocationRequestCompat.Builder setDurationMillis(@IntRange(from=1) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setQuality(int);
+ }
+
+}
+
+package androidx.core.math {
+
+ public class MathUtils {
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
+ method public static float clamp(float, float, float);
+ method public static double clamp(double, double, double);
+ method public static int clamp(int, int, int);
+ method public static long clamp(long, long, long);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
+ method public static int toIntExact(long);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class ConnectivityManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static android.net.NetworkInfo? getNetworkInfoFromBroadcast(android.net.ConnectivityManager, android.content.Intent);
+ method public static int getRestrictBackgroundStatus(android.net.ConnectivityManager);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static boolean isActiveNetworkMetered(android.net.ConnectivityManager);
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
+ }
+
+ public final class MailTo {
+ method public String? getBcc();
+ method public String? getBody();
+ method public String? getCc();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getHeaders();
+ method public String? getSubject();
+ method public String? getTo();
+ method public static boolean isMailTo(String?);
+ method public static boolean isMailTo(android.net.Uri?);
+ method public static androidx.core.net.MailTo parse(String) throws androidx.core.net.ParseException;
+ method public static androidx.core.net.MailTo parse(android.net.Uri) throws androidx.core.net.ParseException;
+ field public static final String MAILTO_SCHEME = "mailto:";
+ }
+
+ public class ParseException extends java.lang.RuntimeException {
+ field public final String response;
+ }
+
+ public final class TrafficStatsCompat {
+ method @Deprecated public static void clearThreadStatsTag();
+ method @Deprecated public static int getThreadStatsTag();
+ method @Deprecated public static void incrementOperationCount(int);
+ method @Deprecated public static void incrementOperationCount(int, int);
+ method @Deprecated public static void setThreadStatsTag(int);
+ method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void tagSocket(java.net.Socket!) throws java.net.SocketException;
+ method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void untagSocket(java.net.Socket!) throws java.net.SocketException;
+ }
+
+ public final class UriCompat {
+ method public static String toSafeString(android.net.Uri);
+ }
+
+}
+
+package androidx.core.os {
+
+ public class BuildCompat {
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N) public static boolean isAtLeastN();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N_MR1) public static boolean isAtLeastNMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O) public static boolean isAtLeastO();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O_MR1) public static boolean isAtLeastOMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.P) public static boolean isAtLeastP();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.Q) public static boolean isAtLeastQ();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.R) public static boolean isAtLeastR();
+ method @Deprecated @ChecksSdkIntAtLeast(api=31, codename="S") public static boolean isAtLeastS();
+ field @ChecksSdkIntAtLeast(extension=android.os.ext.SdkExtensions.AD_SERVICES) public static final int AD_SERVICES_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.R) public static final int R_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.S) public static final int S_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.TIRAMISU) public static final int T_EXTENSION_INT;
+ }
+
+ public final class BundleCompat {
+ method public static <T> T? getParcelable(android.os.Bundle, String?, Class<T!>);
+ method public static android.os.Parcelable![]? getParcelableArray(android.os.Bundle, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayList(android.os.Bundle, String?, Class<? extends T>);
+ method public static <T> android.util.SparseArray<T!>? getSparseParcelableArray(android.os.Bundle, String?, Class<? extends T>);
+ }
+
+ public final class CancellationSignal {
+ ctor public CancellationSignal();
+ method public void cancel();
+ method public Object? getCancellationSignalObject();
+ method public boolean isCanceled();
+ method public void setOnCancelListener(androidx.core.os.CancellationSignal.OnCancelListener?);
+ method public void throwIfCanceled();
+ }
+
+ public static interface CancellationSignal.OnCancelListener {
+ method public void onCancel();
+ }
+
+ public final class ConfigurationCompat {
+ method public static androidx.core.os.LocaleListCompat getLocales(android.content.res.Configuration);
+ }
+
+ public final class EnvironmentCompat {
+ method public static String getStorageState(java.io.File);
+ field public static final String MEDIA_UNKNOWN = "unknown";
+ }
+
+ public final class ExecutorCompat {
+ method public static java.util.concurrent.Executor create(android.os.Handler);
+ }
+
+ public final class HandlerCompat {
+ method public static android.os.Handler createAsync(android.os.Looper);
+ method public static android.os.Handler createAsync(android.os.Looper, android.os.Handler.Callback);
+ method @RequiresApi(16) public static boolean hasCallbacks(android.os.Handler, Runnable);
+ method public static boolean postDelayed(android.os.Handler, Runnable, Object?, long);
+ }
+
+ public final class LocaleListCompat {
+ method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
+ method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
+ method public java.util.Locale? get(int);
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
+ method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
+ method public java.util.Locale? getFirstMatch(String![]);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
+ method public boolean isEmpty();
+ method @RequiresApi(21) public static boolean matchesLanguageAndScript(java.util.Locale, java.util.Locale);
+ method @IntRange(from=0) public int size();
+ method public String toLanguageTags();
+ method public Object? unwrap();
+ method @Deprecated @RequiresApi(24) public static androidx.core.os.LocaleListCompat! wrap(Object!);
+ method @RequiresApi(24) public static androidx.core.os.LocaleListCompat wrap(android.os.LocaleList);
+ }
+
+ public final class MessageCompat {
+ method public static boolean isAsynchronous(android.os.Message);
+ method public static void setAsynchronous(android.os.Message, boolean);
+ }
+
+ public class OperationCanceledException extends java.lang.RuntimeException {
+ ctor public OperationCanceledException();
+ ctor public OperationCanceledException(String?);
+ }
+
+ public final class ParcelCompat {
+ method public static <T> Object![]? readArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> java.util.ArrayList<T!>? readArrayList(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static boolean readBoolean(android.os.Parcel);
+ method public static <K, V> java.util.HashMap<K!,V!>? readHashMap(android.os.Parcel, ClassLoader?, Class<? extends K>, Class<? extends V>);
+ method public static <T> void readList(android.os.Parcel, java.util.List<? super T>, ClassLoader?, Class<T!>);
+ method public static <K, V> void readMap(android.os.Parcel, java.util.Map<? super K,? super V>, ClassLoader?, Class<K!>, Class<V!>);
+ method public static <T extends android.os.Parcelable> T? readParcelable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @Deprecated public static <T> T![]? readParcelableArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.os.Parcelable![]? readParcelableArrayTyped(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(30) public static <T> android.os.Parcelable.Creator<T!>? readParcelableCreator(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(api=android.os.Build.VERSION_CODES.Q) public static <T> java.util.List<T!> readParcelableList(android.os.Parcel, java.util.List<T!>, ClassLoader?, Class<T!>);
+ method public static <T extends java.io.Serializable> T? readSerializable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.util.SparseArray<T!>? readSparseArray(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static void writeBoolean(android.os.Parcel, boolean);
+ }
+
+ @Deprecated public final class ParcelableCompat {
+ method @Deprecated public static <T> android.os.Parcelable.Creator<T!>! newCreator(androidx.core.os.ParcelableCompatCreatorCallbacks<T!>!);
+ }
+
+ @Deprecated public interface ParcelableCompatCreatorCallbacks<T> {
+ method @Deprecated public T! createFromParcel(android.os.Parcel!, ClassLoader!);
+ method @Deprecated public T![]! newArray(int);
+ }
+
+ public final class ProcessCompat {
+ method public static boolean isApplicationUid(int);
+ }
+
+ @Deprecated public final class TraceCompat {
+ method @Deprecated public static void beginAsyncSection(String, int);
+ method @Deprecated public static void beginSection(String);
+ method @Deprecated public static void endAsyncSection(String, int);
+ method @Deprecated public static void endSection();
+ method @Deprecated public static boolean isEnabled();
+ method @Deprecated public static void setCounter(String, int);
+ }
+
+ @RequiresApi(17) public class UserHandleCompat {
+ method public static android.os.UserHandle getUserHandleForUid(int);
+ }
+
+ public class UserManagerCompat {
+ method public static boolean isUserUnlocked(android.content.Context);
+ }
+
+}
+
+package androidx.core.provider {
+
+ public final class DocumentsContractCompat {
+ method public static android.net.Uri? buildChildDocumentsUri(String, String?);
+ method public static android.net.Uri? buildChildDocumentsUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildDocumentUri(String, String);
+ method public static android.net.Uri? buildDocumentUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildTreeDocumentUri(String, String);
+ method public static android.net.Uri? createDocument(android.content.ContentResolver, android.net.Uri, String, String) throws java.io.FileNotFoundException;
+ method public static String? getDocumentId(android.net.Uri);
+ method public static String? getTreeDocumentId(android.net.Uri);
+ method public static boolean isDocumentUri(android.content.Context, android.net.Uri?);
+ method public static boolean isTreeUri(android.net.Uri);
+ method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+ method public static android.net.Uri? renameDocument(android.content.ContentResolver, android.net.Uri, String) throws java.io.FileNotFoundException;
+ }
+
+ public static final class DocumentsContractCompat.DocumentCompat {
+ field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
+ }
+
+ public final class FontRequest {
+ ctor public FontRequest(String, String, String, java.util.List<java.util.List<byte[]!>!>);
+ ctor public FontRequest(String, String, String, @ArrayRes int);
+ method public java.util.List<java.util.List<byte[]!>!>? getCertificates();
+ method @ArrayRes public int getCertificatesArrayResId();
+ method public String getProviderAuthority();
+ method public String getProviderPackage();
+ method public String getQuery();
+ }
+
+ public class FontsContractCompat {
+ method public static android.graphics.Typeface? buildTypeface(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![]);
+ method public static androidx.core.provider.FontsContractCompat.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, androidx.core.provider.FontRequest, androidx.core.provider.FontsContractCompat.FontRequestCallback, android.os.Handler);
+ }
+
+ public static final class FontsContractCompat.Columns implements android.provider.BaseColumns {
+ ctor public FontsContractCompat.Columns();
+ field public static final String FILE_ID = "file_id";
+ field public static final String ITALIC = "font_italic";
+ field public static final String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
+ field public static final String TTC_INDEX = "font_ttc_index";
+ field public static final String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final String WEIGHT = "font_weight";
+ }
+
+ public static class FontsContractCompat.FontFamilyResult {
+ method public androidx.core.provider.FontsContractCompat.FontInfo![]! getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContractCompat.FontInfo {
+ method public int getResultCode();
+ method @IntRange(from=0) public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method @IntRange(from=1, to=1000) public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContractCompat.FontRequestCallback {
+ ctor public FontsContractCompat.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface!);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_SECURITY_VIOLATION = -4; // 0xfffffffc
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
+}
+
+package androidx.core.telephony {
+
+ @RequiresApi(22) public class SubscriptionManagerCompat {
+ method public static int getSlotIndex(int);
+ }
+
+ public class TelephonyManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static String? getImei(android.telephony.TelephonyManager);
+ method public static int getSubscriptionId(android.telephony.TelephonyManager);
+ }
+
+}
+
+package androidx.core.telephony.mbms {
+
+ public final class MbmsHelper {
+ method public static CharSequence? getBestNameForService(android.content.Context, android.telephony.mbms.ServiceInfo);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class BidiFormatter {
+ method public static androidx.core.text.BidiFormatter! getInstance();
+ method public static androidx.core.text.BidiFormatter! getInstance(boolean);
+ method public static androidx.core.text.BidiFormatter! getInstance(java.util.Locale!);
+ method public boolean getStereoReset();
+ method public boolean isRtl(String!);
+ method public boolean isRtl(CharSequence!);
+ method public boolean isRtlContext();
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public String! unicodeWrap(String!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, boolean);
+ method public String! unicodeWrap(String!);
+ method public CharSequence! unicodeWrap(CharSequence!);
+ }
+
+ public static final class BidiFormatter.Builder {
+ ctor public BidiFormatter.Builder();
+ ctor public BidiFormatter.Builder(boolean);
+ ctor public BidiFormatter.Builder(java.util.Locale!);
+ method public androidx.core.text.BidiFormatter! build();
+ method public androidx.core.text.BidiFormatter.Builder! setTextDirectionHeuristic(androidx.core.text.TextDirectionHeuristicCompat!);
+ method public androidx.core.text.BidiFormatter.Builder! stereoReset(boolean);
+ }
+
+ public final class HtmlCompat {
+ method public static android.text.Spanned fromHtml(String, int);
+ method public static android.text.Spanned fromHtml(String, int, android.text.Html.ImageGetter?, android.text.Html.TagHandler?);
+ method public static String toHtml(android.text.Spanned, int);
+ field public static final int FROM_HTML_MODE_COMPACT = 63; // 0x3f
+ field public static final int FROM_HTML_MODE_LEGACY = 0; // 0x0
+ field public static final int FROM_HTML_OPTION_USE_CSS_COLORS = 256; // 0x100
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE = 32; // 0x20
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_DIV = 16; // 0x10
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_HEADING = 2; // 0x2
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST = 8; // 0x8
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM = 4; // 0x4
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH = 1; // 0x1
+ field public static final int TO_HTML_PARAGRAPH_LINES_CONSECUTIVE = 0; // 0x0
+ field public static final int TO_HTML_PARAGRAPH_LINES_INDIVIDUAL = 1; // 0x1
+ }
+
+ public final class ICUCompat {
+ method public static String? maximizeAndGetScript(java.util.Locale);
+ }
+
+ public class PrecomputedTextCompat implements android.text.Spannable {
+ method public char charAt(int);
+ method public static androidx.core.text.PrecomputedTextCompat! create(CharSequence, androidx.core.text.PrecomputedTextCompat.Params);
+ method @IntRange(from=0) public int getParagraphCount();
+ method @IntRange(from=0) public int getParagraphEnd(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getParagraphStart(@IntRange(from=0) int);
+ method public androidx.core.text.PrecomputedTextCompat.Params getParams();
+ method public int getSpanEnd(Object!);
+ method public int getSpanFlags(Object!);
+ method public int getSpanStart(Object!);
+ method public <T> T![]! getSpans(int, int, Class<T!>!);
+ method @UiThread public static java.util.concurrent.Future<androidx.core.text.PrecomputedTextCompat!>! getTextFuture(CharSequence, androidx.core.text.PrecomputedTextCompat.Params, java.util.concurrent.Executor?);
+ method public int length();
+ method public int nextSpanTransition(int, int, Class!);
+ method public void removeSpan(Object!);
+ method public void setSpan(Object!, int, int, int);
+ method public CharSequence! subSequence(int, int);
+ }
+
+ public static final class PrecomputedTextCompat.Params {
+ ctor @RequiresApi(28) public PrecomputedTextCompat.Params(android.text.PrecomputedText.Params);
+ method @RequiresApi(23) public int getBreakStrategy();
+ method @RequiresApi(23) public int getHyphenationFrequency();
+ method @RequiresApi(18) public android.text.TextDirectionHeuristic? getTextDirection();
+ method public android.text.TextPaint getTextPaint();
+ }
+
+ public static class PrecomputedTextCompat.Params.Builder {
+ ctor public PrecomputedTextCompat.Params.Builder(android.text.TextPaint);
+ method public androidx.core.text.PrecomputedTextCompat.Params build();
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setBreakStrategy(int);
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setHyphenationFrequency(int);
+ method @RequiresApi(18) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setTextDirection(android.text.TextDirectionHeuristic);
+ }
+
+ public interface TextDirectionHeuristicCompat {
+ method public boolean isRtl(char[]!, int, int);
+ method public boolean isRtl(CharSequence!, int, int);
+ }
+
+ public final class TextDirectionHeuristicsCompat {
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! ANYRTL_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_RTL;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LOCALE;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! RTL;
+ }
+
+ public final class TextUtilsCompat {
+ method public static int getLayoutDirectionFromLocale(java.util.Locale?);
+ method public static String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.text.util {
+
+ public final class LinkifyCompat {
+ method public static boolean addLinks(android.text.Spannable, int);
+ method public static boolean addLinks(android.widget.TextView, int);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ }
+
+}
+
+package androidx.core.util {
+
+ public class AtomicFile {
+ ctor public AtomicFile(java.io.File);
+ method public void delete();
+ method public void failWrite(java.io.FileOutputStream?);
+ method public void finishWrite(java.io.FileOutputStream?);
+ method public java.io.File getBaseFile();
+ method public java.io.FileInputStream openRead() throws java.io.FileNotFoundException;
+ method public byte[] readFully() throws java.io.IOException;
+ method public java.io.FileOutputStream startWrite() throws java.io.IOException;
+ }
+
+ public interface Consumer<T> {
+ method public void accept(T!);
+ }
+
+ public class ObjectsCompat {
+ method public static boolean equals(Object?, Object?);
+ method public static int hash(java.lang.Object!...);
+ method public static int hashCode(Object?);
+ method public static <T> T requireNonNull(T?);
+ method public static <T> T requireNonNull(T?, String);
+ method public static String? toString(Object?, String?);
+ }
+
+ public class Pair<F, S> {
+ ctor public Pair(F!, S!);
+ method public static <A, B> androidx.core.util.Pair<A!,B!> create(A!, B!);
+ field public final F! first;
+ field public final S! second;
+ }
+
+ public final class PatternsCompat {
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
+ }
+
+ public final class Pools {
+ }
+
+ public static interface Pools.Pool<T> {
+ method public T? acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SimplePool<T> implements androidx.core.util.Pools.Pool<T> {
+ ctor public Pools.SimplePool(int);
+ method public T! acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SynchronizedPool<T> extends androidx.core.util.Pools.SimplePool<T> {
+ ctor public Pools.SynchronizedPool(int);
+ }
+
+ public interface Predicate<T> {
+ method public default androidx.core.util.Predicate<T!>! and(androidx.core.util.Predicate<? super T>!);
+ method public static <T> androidx.core.util.Predicate<T!>! isEqual(Object!);
+ method public default androidx.core.util.Predicate<T!>! negate();
+ method public static <T> androidx.core.util.Predicate<T!>! not(androidx.core.util.Predicate<? super T>!);
+ method public default androidx.core.util.Predicate<T!>! or(androidx.core.util.Predicate<? super T>!);
+ method public boolean test(T!);
+ }
+
+ public final class SizeFCompat {
+ ctor public SizeFCompat(float, float);
+ method public float getHeight();
+ method public float getWidth();
+ method @RequiresApi(21) public android.util.SizeF toSizeF();
+ method @RequiresApi(21) public static androidx.core.util.SizeFCompat toSizeFCompat(android.util.SizeF);
+ }
+
+ public interface Supplier<T> {
+ method public T! get();
+ }
+
+}
+
+package androidx.core.view {
+
+ public class AccessibilityDelegateCompat {
+ ctor public AccessibilityDelegateCompat();
+ method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public void sendAccessibilityEvent(android.view.View, int);
+ method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
+ }
+
+ public abstract class ActionProvider {
+ ctor public ActionProvider(android.content.Context);
+ method public android.content.Context getContext();
+ method public boolean hasSubMenu();
+ method public boolean isVisible();
+ method public abstract android.view.View onCreateActionView();
+ method public android.view.View onCreateActionView(android.view.MenuItem);
+ method public boolean onPerformDefaultAction();
+ method public void onPrepareSubMenu(android.view.SubMenu);
+ method public boolean overridesItemVisibility();
+ method public void refreshVisibility();
+ method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
+ }
+
+ public static interface ActionProvider.VisibilityListener {
+ method public void onActionProviderVisibilityChanged(boolean);
+ }
+
+ public final class ContentInfoCompat {
+ method public android.content.ClipData getClip();
+ method public android.os.Bundle? getExtras();
+ method public int getFlags();
+ method public android.net.Uri? getLinkUri();
+ method public int getSource();
+ method public android.util.Pair<androidx.core.view.ContentInfoCompat!,androidx.core.view.ContentInfoCompat!> partition(androidx.core.util.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public static android.util.Pair<android.view.ContentInfo!,android.view.ContentInfo!> partition(android.view.ContentInfo, java.util.function.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public android.view.ContentInfo toContentInfo();
+ method @RequiresApi(31) public static androidx.core.view.ContentInfoCompat toContentInfoCompat(android.view.ContentInfo);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_APP = 0; // 0x0
+ field public static final int SOURCE_AUTOFILL = 4; // 0x4
+ field public static final int SOURCE_CLIPBOARD = 1; // 0x1
+ field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3
+ field public static final int SOURCE_INPUT_METHOD = 2; // 0x2
+ field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5
+ }
+
+ public static final class ContentInfoCompat.Builder {
+ ctor public ContentInfoCompat.Builder(androidx.core.view.ContentInfoCompat);
+ ctor public ContentInfoCompat.Builder(android.content.ClipData, int);
+ method public androidx.core.view.ContentInfoCompat build();
+ method public androidx.core.view.ContentInfoCompat.Builder setClip(android.content.ClipData);
+ method public androidx.core.view.ContentInfoCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.view.ContentInfoCompat.Builder setFlags(int);
+ method public androidx.core.view.ContentInfoCompat.Builder setLinkUri(android.net.Uri?);
+ method public androidx.core.view.ContentInfoCompat.Builder setSource(int);
+ }
+
+ public final class DisplayCompat {
+ method public static androidx.core.view.DisplayCompat.ModeCompat getMode(android.content.Context, android.view.Display);
+ method public static androidx.core.view.DisplayCompat.ModeCompat![] getSupportedModes(android.content.Context, android.view.Display);
+ }
+
+ public static final class DisplayCompat.ModeCompat {
+ method public int getPhysicalHeight();
+ method public int getPhysicalWidth();
+ method @Deprecated public boolean isNative();
+ method @RequiresApi(android.os.Build.VERSION_CODES.M) public android.view.Display.Mode? toMode();
+ }
+
+ public final class DisplayCutoutCompat {
+ ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
+ ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
+ method public java.util.List<android.graphics.Rect!> getBoundingRects();
+ method public int getSafeInsetBottom();
+ method public int getSafeInsetLeft();
+ method public int getSafeInsetRight();
+ method public int getSafeInsetTop();
+ method public androidx.core.graphics.Insets getWaterfallInsets();
+ }
+
+ public final class DragAndDropPermissionsCompat {
+ method public void release();
+ }
+
+ public class DragStartHelper {
+ ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
+ method public void attach();
+ method public void detach();
+ method public void getTouchPosition(android.graphics.Point);
+ method public boolean onLongClick(android.view.View);
+ method public boolean onTouch(android.view.View, android.view.MotionEvent);
+ }
+
+ public static interface DragStartHelper.OnDragStartListener {
+ method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
+ }
+
+ public final class GestureDetectorCompat {
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener);
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener, android.os.Handler?);
+ method public boolean isLongpressEnabled();
+ method public boolean onTouchEvent(android.view.MotionEvent);
+ method public void setIsLongpressEnabled(boolean);
+ method public void setOnDoubleTapListener(android.view.GestureDetector.OnDoubleTapListener?);
+ }
+
+ public final class GravityCompat {
+ method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
+ method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static int getAbsoluteGravity(int, int);
+ field public static final int END = 8388613; // 0x800005
+ field public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = 8388615; // 0x800007
+ field public static final int RELATIVE_LAYOUT_DIRECTION = 8388608; // 0x800000
+ field public static final int START = 8388611; // 0x800003
+ }
+
+ public final class InputDeviceCompat {
+ field public static final int SOURCE_ANY = -256; // 0xffffff00
+ field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
+ field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
+ field public static final int SOURCE_CLASS_MASK = 255; // 0xff
+ field public static final int SOURCE_CLASS_NONE = 0; // 0x0
+ field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
+ field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
+ field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
+ field public static final int SOURCE_DPAD = 513; // 0x201
+ field public static final int SOURCE_GAMEPAD = 1025; // 0x401
+ field public static final int SOURCE_HDMI = 33554433; // 0x2000001
+ field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
+ field public static final int SOURCE_KEYBOARD = 257; // 0x101
+ field public static final int SOURCE_MOUSE = 8194; // 0x2002
+ field public static final int SOURCE_ROTARY_ENCODER = 4194304; // 0x400000
+ field public static final int SOURCE_STYLUS = 16386; // 0x4002
+ field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
+ field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
+ field public static final int SOURCE_TOUCH_NAVIGATION = 2097152; // 0x200000
+ field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
+ field public static final int SOURCE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class LayoutInflaterCompat {
+ method @Deprecated public static androidx.core.view.LayoutInflaterFactory! getFactory(android.view.LayoutInflater!);
+ method @Deprecated public static void setFactory(android.view.LayoutInflater, androidx.core.view.LayoutInflaterFactory);
+ method public static void setFactory2(android.view.LayoutInflater, android.view.LayoutInflater.Factory2);
+ }
+
+ @Deprecated public interface LayoutInflaterFactory {
+ method @Deprecated public android.view.View! onCreateView(android.view.View!, String!, android.content.Context!, android.util.AttributeSet!);
+ }
+
+ public final class MarginLayoutParamsCompat {
+ method public static int getLayoutDirection(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginEnd(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginStart(android.view.ViewGroup.MarginLayoutParams);
+ method public static boolean isMarginRelative(android.view.ViewGroup.MarginLayoutParams);
+ method public static void resolveLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginEnd(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginStart(android.view.ViewGroup.MarginLayoutParams, int);
+ }
+
+ public final class MenuCompat {
+ method public static void setGroupDividerEnabled(android.view.Menu, boolean);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ }
+
+ public interface MenuHost {
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void invalidateMenu();
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public class MenuHostHelper {
+ ctor public MenuHostHelper(Runnable);
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public void onPrepareMenu(android.view.Menu);
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public final class MenuItemCompat {
+ method @Deprecated public static boolean collapseActionView(android.view.MenuItem!);
+ method @Deprecated public static boolean expandActionView(android.view.MenuItem!);
+ method public static androidx.core.view.ActionProvider? getActionProvider(android.view.MenuItem);
+ method @Deprecated public static android.view.View! getActionView(android.view.MenuItem!);
+ method public static int getAlphabeticModifiers(android.view.MenuItem);
+ method public static CharSequence? getContentDescription(android.view.MenuItem);
+ method public static android.content.res.ColorStateList? getIconTintList(android.view.MenuItem);
+ method public static android.graphics.PorterDuff.Mode? getIconTintMode(android.view.MenuItem);
+ method public static int getNumericModifiers(android.view.MenuItem);
+ method public static CharSequence? getTooltipText(android.view.MenuItem);
+ method @Deprecated public static boolean isActionViewExpanded(android.view.MenuItem!);
+ method public static android.view.MenuItem? setActionProvider(android.view.MenuItem, androidx.core.view.ActionProvider?);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, android.view.View!);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, int);
+ method public static void setAlphabeticShortcut(android.view.MenuItem, char, int);
+ method public static void setContentDescription(android.view.MenuItem, CharSequence?);
+ method public static void setIconTintList(android.view.MenuItem, android.content.res.ColorStateList?);
+ method public static void setIconTintMode(android.view.MenuItem, android.graphics.PorterDuff.Mode?);
+ method public static void setNumericShortcut(android.view.MenuItem, char, int);
+ method @Deprecated public static android.view.MenuItem! setOnActionExpandListener(android.view.MenuItem!, androidx.core.view.MenuItemCompat.OnActionExpandListener!);
+ method public static void setShortcut(android.view.MenuItem, char, char, int, int);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ method public static void setTooltipText(android.view.MenuItem, CharSequence?);
+ field @Deprecated public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+ field @Deprecated public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
+ field @Deprecated public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
+ field @Deprecated public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
+ field @Deprecated public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
+ }
+
+ @Deprecated public static interface MenuItemCompat.OnActionExpandListener {
+ method @Deprecated public boolean onMenuItemActionCollapse(android.view.MenuItem!);
+ method @Deprecated public boolean onMenuItemActionExpand(android.view.MenuItem!);
+ }
+
+ public interface MenuProvider {
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public default void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public default void onPrepareMenu(android.view.Menu);
+ }
+
+ public final class MotionEventCompat {
+ method @Deprecated public static int findPointerIndex(android.view.MotionEvent!, int);
+ method @Deprecated public static int getActionIndex(android.view.MotionEvent!);
+ method @Deprecated public static int getActionMasked(android.view.MotionEvent!);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int, int);
+ method @Deprecated public static int getButtonState(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerCount(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerId(android.view.MotionEvent!, int);
+ method @Deprecated public static int getSource(android.view.MotionEvent!);
+ method @Deprecated public static float getX(android.view.MotionEvent!, int);
+ method @Deprecated public static float getY(android.view.MotionEvent!, int);
+ method public static boolean isFromSource(android.view.MotionEvent, int);
+ field @Deprecated public static final int ACTION_HOVER_ENTER = 9; // 0x9
+ field @Deprecated public static final int ACTION_HOVER_EXIT = 10; // 0xa
+ field @Deprecated public static final int ACTION_HOVER_MOVE = 7; // 0x7
+ field @Deprecated public static final int ACTION_MASK = 255; // 0xff
+ field @Deprecated public static final int ACTION_POINTER_DOWN = 5; // 0x5
+ field @Deprecated public static final int ACTION_POINTER_INDEX_MASK = 65280; // 0xff00
+ field @Deprecated public static final int ACTION_POINTER_INDEX_SHIFT = 8; // 0x8
+ field @Deprecated public static final int ACTION_POINTER_UP = 6; // 0x6
+ field @Deprecated public static final int ACTION_SCROLL = 8; // 0x8
+ field @Deprecated public static final int AXIS_BRAKE = 23; // 0x17
+ field @Deprecated public static final int AXIS_DISTANCE = 24; // 0x18
+ field @Deprecated public static final int AXIS_GAS = 22; // 0x16
+ field @Deprecated public static final int AXIS_GENERIC_1 = 32; // 0x20
+ field @Deprecated public static final int AXIS_GENERIC_10 = 41; // 0x29
+ field @Deprecated public static final int AXIS_GENERIC_11 = 42; // 0x2a
+ field @Deprecated public static final int AXIS_GENERIC_12 = 43; // 0x2b
+ field @Deprecated public static final int AXIS_GENERIC_13 = 44; // 0x2c
+ field @Deprecated public static final int AXIS_GENERIC_14 = 45; // 0x2d
+ field @Deprecated public static final int AXIS_GENERIC_15 = 46; // 0x2e
+ field @Deprecated public static final int AXIS_GENERIC_16 = 47; // 0x2f
+ field @Deprecated public static final int AXIS_GENERIC_2 = 33; // 0x21
+ field @Deprecated public static final int AXIS_GENERIC_3 = 34; // 0x22
+ field @Deprecated public static final int AXIS_GENERIC_4 = 35; // 0x23
+ field @Deprecated public static final int AXIS_GENERIC_5 = 36; // 0x24
+ field @Deprecated public static final int AXIS_GENERIC_6 = 37; // 0x25
+ field @Deprecated public static final int AXIS_GENERIC_7 = 38; // 0x26
+ field @Deprecated public static final int AXIS_GENERIC_8 = 39; // 0x27
+ field @Deprecated public static final int AXIS_GENERIC_9 = 40; // 0x28
+ field @Deprecated public static final int AXIS_HAT_X = 15; // 0xf
+ field @Deprecated public static final int AXIS_HAT_Y = 16; // 0x10
+ field @Deprecated public static final int AXIS_HSCROLL = 10; // 0xa
+ field @Deprecated public static final int AXIS_LTRIGGER = 17; // 0x11
+ field @Deprecated public static final int AXIS_ORIENTATION = 8; // 0x8
+ field @Deprecated public static final int AXIS_PRESSURE = 2; // 0x2
+ field public static final int AXIS_RELATIVE_X = 27; // 0x1b
+ field public static final int AXIS_RELATIVE_Y = 28; // 0x1c
+ field @Deprecated public static final int AXIS_RTRIGGER = 18; // 0x12
+ field @Deprecated public static final int AXIS_RUDDER = 20; // 0x14
+ field @Deprecated public static final int AXIS_RX = 12; // 0xc
+ field @Deprecated public static final int AXIS_RY = 13; // 0xd
+ field @Deprecated public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
+ field @Deprecated public static final int AXIS_SIZE = 3; // 0x3
+ field @Deprecated public static final int AXIS_THROTTLE = 19; // 0x13
+ field @Deprecated public static final int AXIS_TILT = 25; // 0x19
+ field @Deprecated public static final int AXIS_TOOL_MAJOR = 6; // 0x6
+ field @Deprecated public static final int AXIS_TOOL_MINOR = 7; // 0x7
+ field @Deprecated public static final int AXIS_TOUCH_MAJOR = 4; // 0x4
+ field @Deprecated public static final int AXIS_TOUCH_MINOR = 5; // 0x5
+ field @Deprecated public static final int AXIS_VSCROLL = 9; // 0x9
+ field @Deprecated public static final int AXIS_WHEEL = 21; // 0x15
+ field @Deprecated public static final int AXIS_X = 0; // 0x0
+ field @Deprecated public static final int AXIS_Y = 1; // 0x1
+ field @Deprecated public static final int AXIS_Z = 11; // 0xb
+ field @Deprecated public static final int BUTTON_PRIMARY = 1; // 0x1
+ }
+
+ public interface NestedScrollingChild {
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean isNestedScrollingEnabled();
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(int);
+ method public void stopNestedScroll();
+ }
+
+ public interface NestedScrollingChild2 extends androidx.core.view.NestedScrollingChild {
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll(int);
+ }
+
+ public interface NestedScrollingChild3 extends androidx.core.view.NestedScrollingChild2 {
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]);
+ }
+
+ public class NestedScrollingChildHelper {
+ ctor public NestedScrollingChildHelper(android.view.View);
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean isNestedScrollingEnabled();
+ method public void onDetachedFromWindow();
+ method public void onStopNestedScroll(android.view.View);
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll();
+ method public void stopNestedScroll(int);
+ }
+
+ public interface NestedScrollingParent {
+ method public int getNestedScrollAxes();
+ method public boolean onNestedFling(android.view.View, float, float, boolean);
+ method public boolean onNestedPreFling(android.view.View, float, float);
+ method public void onNestedPreScroll(android.view.View, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
+ method public void onStopNestedScroll(android.view.View);
+ }
+
+ public interface NestedScrollingParent2 extends androidx.core.view.NestedScrollingParent {
+ method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View, int);
+ }
+
+ public interface NestedScrollingParent3 extends androidx.core.view.NestedScrollingParent2 {
+ method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]);
+ }
+
+ public class NestedScrollingParentHelper {
+ ctor public NestedScrollingParentHelper(android.view.ViewGroup);
+ method public int getNestedScrollAxes();
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View);
+ method public void onStopNestedScroll(android.view.View, int);
+ }
+
+ public interface OnApplyWindowInsetsListener {
+ method public androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ }
+
+ public interface OnReceiveContentListener {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ }
+
+ public interface OnReceiveContentViewBehavior {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(androidx.core.view.ContentInfoCompat);
+ }
+
+ public final class OneShotPreDrawListener implements android.view.View.OnAttachStateChangeListener android.view.ViewTreeObserver.OnPreDrawListener {
+ method public static androidx.core.view.OneShotPreDrawListener add(android.view.View, Runnable);
+ method public boolean onPreDraw();
+ method public void onViewAttachedToWindow(android.view.View);
+ method public void onViewDetachedFromWindow(android.view.View);
+ method public void removeListener();
+ }
+
+ public final class PointerIconCompat {
+ method public static androidx.core.view.PointerIconCompat create(android.graphics.Bitmap, float, float);
+ method public static androidx.core.view.PointerIconCompat getSystemIcon(android.content.Context, int);
+ method public static androidx.core.view.PointerIconCompat load(android.content.res.Resources, int);
+ field public static final int TYPE_ALIAS = 1010; // 0x3f2
+ field public static final int TYPE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int TYPE_ARROW = 1000; // 0x3e8
+ field public static final int TYPE_CELL = 1006; // 0x3ee
+ field public static final int TYPE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int TYPE_COPY = 1011; // 0x3f3
+ field public static final int TYPE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int TYPE_DEFAULT = 1000; // 0x3e8
+ field public static final int TYPE_GRAB = 1020; // 0x3fc
+ field public static final int TYPE_GRABBING = 1021; // 0x3fd
+ field public static final int TYPE_HAND = 1002; // 0x3ea
+ field public static final int TYPE_HELP = 1003; // 0x3eb
+ field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int TYPE_NO_DROP = 1012; // 0x3f4
+ field public static final int TYPE_NULL = 0; // 0x0
+ field public static final int TYPE_TEXT = 1008; // 0x3f0
+ field public static final int TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int TYPE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int TYPE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int TYPE_WAIT = 1004; // 0x3ec
+ field public static final int TYPE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int TYPE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
+ public final class ScaleGestureDetectorCompat {
+ method @Deprecated public static boolean isQuickScaleEnabled(Object!);
+ method public static boolean isQuickScaleEnabled(android.view.ScaleGestureDetector);
+ method @Deprecated public static void setQuickScaleEnabled(Object!, boolean);
+ method public static void setQuickScaleEnabled(android.view.ScaleGestureDetector, boolean);
+ }
+
+ public interface ScrollingView {
+ method public int computeHorizontalScrollExtent();
+ method public int computeHorizontalScrollOffset();
+ method public int computeHorizontalScrollRange();
+ method public int computeVerticalScrollExtent();
+ method public int computeVerticalScrollOffset();
+ method public int computeVerticalScrollRange();
+ }
+
+ public interface TintableBackgroundView {
+ method public android.content.res.ColorStateList? getSupportBackgroundTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
+ method public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
+ method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ @Deprecated public final class VelocityTrackerCompat {
+ method @Deprecated public static float getXVelocity(android.view.VelocityTracker!, int);
+ method @Deprecated public static float getYVelocity(android.view.VelocityTracker!, int);
+ }
+
+ public class ViewCompat {
+ ctor @Deprecated protected ViewCompat();
+ method public static int addAccessibilityAction(android.view.View, CharSequence, androidx.core.view.accessibility.AccessibilityViewCommand);
+ method public static void addKeyboardNavigationClusters(android.view.View, java.util.Collection<android.view.View!>, int);
+ method public static void addOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static androidx.core.view.ViewPropertyAnimatorCompat animate(android.view.View);
+ method @Deprecated public static boolean canScrollHorizontally(android.view.View!, int);
+ method @Deprecated public static boolean canScrollVertically(android.view.View!, int);
+ method public static void cancelDragAndDrop(android.view.View);
+ method @Deprecated public static int combineMeasuredStates(int, int);
+ method public static androidx.core.view.WindowInsetsCompat computeSystemWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat, android.graphics.Rect);
+ method public static androidx.core.view.WindowInsetsCompat dispatchApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method public static void dispatchFinishTemporaryDetach(android.view.View);
+ method public static boolean dispatchNestedFling(android.view.View, float, float, boolean);
+ method public static boolean dispatchNestedPreFling(android.view.View, float, float);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?, int);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?);
+ method public static void dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, int, int[]);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, int);
+ method public static void dispatchStartTemporaryDetach(android.view.View);
+ method public static void enableAccessibleClickableSpanSupport(android.view.View);
+ method public static int generateViewId();
+ method public static androidx.core.view.AccessibilityDelegateCompat? getAccessibilityDelegate(android.view.View);
+ method public static int getAccessibilityLiveRegion(android.view.View);
+ method public static androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method @UiThread public static CharSequence? getAccessibilityPaneTitle(android.view.View);
+ method @Deprecated public static float getAlpha(android.view.View!);
+ method public static android.content.res.ColorStateList? getBackgroundTintList(android.view.View);
+ method public static android.graphics.PorterDuff.Mode? getBackgroundTintMode(android.view.View);
+ method public static android.graphics.Rect? getClipBounds(android.view.View);
+ method public static android.view.Display? getDisplay(android.view.View);
+ method public static float getElevation(android.view.View);
+ method public static boolean getFitsSystemWindows(android.view.View);
+ method public static int getImportantForAccessibility(android.view.View);
+ method public static int getImportantForAutofill(android.view.View);
+ method public static int getLabelFor(android.view.View);
+ method @Deprecated public static int getLayerType(android.view.View!);
+ method public static int getLayoutDirection(android.view.View);
+ method @Deprecated public static android.graphics.Matrix? getMatrix(android.view.View!);
+ method @Deprecated public static int getMeasuredHeightAndState(android.view.View!);
+ method @Deprecated public static int getMeasuredState(android.view.View!);
+ method @Deprecated public static int getMeasuredWidthAndState(android.view.View!);
+ method public static int getMinimumHeight(android.view.View);
+ method public static int getMinimumWidth(android.view.View);
+ method public static int getNextClusterForwardId(android.view.View);
+ method public static String![]? getOnReceiveContentMimeTypes(android.view.View);
+ method @Deprecated public static int getOverScrollMode(android.view.View!);
+ method @Px public static int getPaddingEnd(android.view.View);
+ method @Px public static int getPaddingStart(android.view.View);
+ method public static android.view.ViewParent? getParentForAccessibility(android.view.View);
+ method @Deprecated public static float getPivotX(android.view.View!);
+ method @Deprecated public static float getPivotY(android.view.View!);
+ method public static androidx.core.view.WindowInsetsCompat? getRootWindowInsets(android.view.View);
+ method @Deprecated public static float getRotation(android.view.View!);
+ method @Deprecated public static float getRotationX(android.view.View!);
+ method @Deprecated public static float getRotationY(android.view.View!);
+ method @Deprecated public static float getScaleX(android.view.View!);
+ method @Deprecated public static float getScaleY(android.view.View!);
+ method public static int getScrollIndicators(android.view.View);
+ method @UiThread public static CharSequence? getStateDescription(android.view.View);
+ method public static java.util.List<android.graphics.Rect!> getSystemGestureExclusionRects(android.view.View);
+ method public static String? getTransitionName(android.view.View);
+ method @Deprecated public static float getTranslationX(android.view.View!);
+ method @Deprecated public static float getTranslationY(android.view.View!);
+ method public static float getTranslationZ(android.view.View);
+ method @Deprecated public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
+ method @Deprecated public static int getWindowSystemUiVisibility(android.view.View);
+ method @Deprecated public static float getX(android.view.View!);
+ method @Deprecated public static float getY(android.view.View!);
+ method public static float getZ(android.view.View);
+ method public static boolean hasAccessibilityDelegate(android.view.View);
+ method public static boolean hasExplicitFocusable(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View, int);
+ method public static boolean hasOnClickListeners(android.view.View);
+ method public static boolean hasOverlappingRendering(android.view.View);
+ method public static boolean hasTransientState(android.view.View);
+ method @UiThread public static boolean isAccessibilityHeading(android.view.View);
+ method public static boolean isAttachedToWindow(android.view.View);
+ method public static boolean isFocusedByDefault(android.view.View);
+ method public static boolean isImportantForAccessibility(android.view.View);
+ method public static boolean isImportantForAutofill(android.view.View);
+ method public static boolean isInLayout(android.view.View);
+ method public static boolean isKeyboardNavigationCluster(android.view.View);
+ method public static boolean isLaidOut(android.view.View);
+ method public static boolean isLayoutDirectionResolved(android.view.View);
+ method public static boolean isNestedScrollingEnabled(android.view.View);
+ method @Deprecated public static boolean isOpaque(android.view.View!);
+ method public static boolean isPaddingRelative(android.view.View);
+ method @UiThread public static boolean isScreenReaderFocusable(android.view.View);
+ method @Deprecated public static void jumpDrawablesToCurrentState(android.view.View!);
+ method public static android.view.View? keyboardNavigationClusterSearch(android.view.View, android.view.View?, int);
+ method public static void offsetLeftAndRight(android.view.View, int);
+ method public static void offsetTopAndBottom(android.view.View, int);
+ method public static androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method @Deprecated public static void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method @Deprecated public static void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public static androidx.core.view.ContentInfoCompat? performReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ method public static void postInvalidateOnAnimation(android.view.View);
+ method public static void postInvalidateOnAnimation(android.view.View, int, int, int, int);
+ method public static void postOnAnimation(android.view.View, Runnable);
+ method public static void postOnAnimationDelayed(android.view.View, Runnable, long);
+ method public static void removeAccessibilityAction(android.view.View, int);
+ method public static void removeOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static void replaceAccessibilityAction(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat, CharSequence?, androidx.core.view.accessibility.AccessibilityViewCommand?);
+ method public static void requestApplyInsets(android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.View, @IdRes int);
+ method @Deprecated public static int resolveSizeAndState(int, int, int);
+ method public static boolean restoreDefaultFocus(android.view.View);
+ method public static void saveAttributeDataForStyleable(android.view.View, android.content.Context, int[], android.util.AttributeSet?, android.content.res.TypedArray, int, int);
+ method public static void setAccessibilityDelegate(android.view.View, androidx.core.view.AccessibilityDelegateCompat?);
+ method @UiThread public static void setAccessibilityHeading(android.view.View, boolean);
+ method public static void setAccessibilityLiveRegion(android.view.View, int);
+ method @UiThread public static void setAccessibilityPaneTitle(android.view.View, CharSequence?);
+ method @Deprecated public static void setActivated(android.view.View!, boolean);
+ method @Deprecated public static void setAlpha(android.view.View!, @FloatRange(from=0.0, to=1.0) float);
+ method public static void setAutofillHints(android.view.View, java.lang.String!...);
+ method public static void setBackground(android.view.View, android.graphics.drawable.Drawable?);
+ method public static void setBackgroundTintList(android.view.View, android.content.res.ColorStateList?);
+ method public static void setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode?);
+ method @Deprecated public static void setChildrenDrawingOrderEnabled(android.view.ViewGroup!, boolean);
+ method public static void setClipBounds(android.view.View, android.graphics.Rect?);
+ method public static void setElevation(android.view.View, float);
+ method @Deprecated public static void setFitsSystemWindows(android.view.View!, boolean);
+ method public static void setFocusedByDefault(android.view.View, boolean);
+ method public static void setHasTransientState(android.view.View, boolean);
+ method @UiThread public static void setImportantForAccessibility(android.view.View, int);
+ method public static void setImportantForAutofill(android.view.View, int);
+ method public static void setKeyboardNavigationCluster(android.view.View, boolean);
+ method public static void setLabelFor(android.view.View, @IdRes int);
+ method public static void setLayerPaint(android.view.View, android.graphics.Paint?);
+ method @Deprecated public static void setLayerType(android.view.View!, int, android.graphics.Paint!);
+ method public static void setLayoutDirection(android.view.View, int);
+ method public static void setNestedScrollingEnabled(android.view.View, boolean);
+ method public static void setNextClusterForwardId(android.view.View, int);
+ method public static void setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener?);
+ method public static void setOnReceiveContentListener(android.view.View, String![]?, androidx.core.view.OnReceiveContentListener?);
+ method @Deprecated public static void setOverScrollMode(android.view.View!, int);
+ method public static void setPaddingRelative(android.view.View, @Px int, @Px int, @Px int, @Px int);
+ method @Deprecated public static void setPivotX(android.view.View!, float);
+ method @Deprecated public static void setPivotY(android.view.View!, float);
+ method public static void setPointerIcon(android.view.View, androidx.core.view.PointerIconCompat?);
+ method @Deprecated public static void setRotation(android.view.View!, float);
+ method @Deprecated public static void setRotationX(android.view.View!, float);
+ method @Deprecated public static void setRotationY(android.view.View!, float);
+ method @Deprecated public static void setSaveFromParentEnabled(android.view.View!, boolean);
+ method @Deprecated public static void setScaleX(android.view.View!, float);
+ method @Deprecated public static void setScaleY(android.view.View!, float);
+ method @UiThread public static void setScreenReaderFocusable(android.view.View, boolean);
+ method public static void setScrollIndicators(android.view.View, int);
+ method public static void setScrollIndicators(android.view.View, int, int);
+ method @UiThread public static void setStateDescription(android.view.View, CharSequence?);
+ method public static void setSystemGestureExclusionRects(android.view.View, java.util.List<android.graphics.Rect!>);
+ method public static void setTooltipText(android.view.View, CharSequence?);
+ method public static void setTransitionName(android.view.View, String?);
+ method @Deprecated public static void setTranslationX(android.view.View!, float);
+ method @Deprecated public static void setTranslationY(android.view.View!, float);
+ method public static void setTranslationZ(android.view.View, float);
+ method public static void setWindowInsetsAnimationCallback(android.view.View, androidx.core.view.WindowInsetsAnimationCompat.Callback?);
+ method @Deprecated public static void setX(android.view.View!, float);
+ method @Deprecated public static void setY(android.view.View!, float);
+ method public static void setZ(android.view.View, float);
+ method public static boolean startDragAndDrop(android.view.View, android.content.ClipData?, android.view.View.DragShadowBuilder, Object?, int);
+ method public static boolean startNestedScroll(android.view.View, int);
+ method public static boolean startNestedScroll(android.view.View, int, int);
+ method public static void stopNestedScroll(android.view.View);
+ method public static void stopNestedScroll(android.view.View, int);
+ method public static void updateDragShadow(android.view.View, android.view.View.DragShadowBuilder);
+ field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
+ field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
+ field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field @Deprecated public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
+ field @Deprecated public static final int LAYER_TYPE_NONE = 0; // 0x0
+ field @Deprecated public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
+ field public static final int LAYOUT_DIRECTION_INHERIT = 2; // 0x2
+ field public static final int LAYOUT_DIRECTION_LOCALE = 3; // 0x3
+ field public static final int LAYOUT_DIRECTION_LTR = 0; // 0x0
+ field public static final int LAYOUT_DIRECTION_RTL = 1; // 0x1
+ field @Deprecated public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; // 0x10
+ field @Deprecated public static final int MEASURED_SIZE_MASK = 16777215; // 0xffffff
+ field @Deprecated public static final int MEASURED_STATE_MASK = -16777216; // 0xff000000
+ field @Deprecated public static final int MEASURED_STATE_TOO_SMALL = 16777216; // 0x1000000
+ field @Deprecated public static final int OVER_SCROLL_ALWAYS = 0; // 0x0
+ field @Deprecated public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; // 0x1
+ field @Deprecated public static final int OVER_SCROLL_NEVER = 2; // 0x2
+ field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
+ field public static final int SCROLL_AXIS_NONE = 0; // 0x0
+ field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+ field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+ field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+ field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+ field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
+ field public static final int TYPE_NON_TOUCH = 1; // 0x1
+ field public static final int TYPE_TOUCH = 0; // 0x0
+ }
+
+ public static interface ViewCompat.OnUnhandledKeyEventListenerCompat {
+ method public boolean onUnhandledKeyEvent(android.view.View, android.view.KeyEvent);
+ }
+
+ public final class ViewConfigurationCompat {
+ method public static float getScaledHorizontalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method public static int getScaledHoverSlop(android.view.ViewConfiguration);
+ method @Deprecated public static int getScaledPagingTouchSlop(android.view.ViewConfiguration!);
+ method public static float getScaledVerticalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method @Deprecated public static boolean hasPermanentMenuKey(android.view.ViewConfiguration!);
+ method public static boolean shouldShowMenuShortcutsWhenKeyboardPresent(android.view.ViewConfiguration, android.content.Context);
+ }
+
+ public final class ViewGroupCompat {
+ method public static int getLayoutMode(android.view.ViewGroup);
+ method public static int getNestedScrollAxes(android.view.ViewGroup);
+ method public static boolean isTransitionGroup(android.view.ViewGroup);
+ method @Deprecated public static boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void setLayoutMode(android.view.ViewGroup, int);
+ method @Deprecated public static void setMotionEventSplittingEnabled(android.view.ViewGroup!, boolean);
+ method public static void setTransitionGroup(android.view.ViewGroup, boolean);
+ field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
+ field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
+ }
+
+ public final class ViewParentCompat {
+ method public static void notifySubtreeAccessibilityStateChanged(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onNestedFling(android.view.ViewParent, android.view.View, float, float, boolean);
+ method public static boolean onNestedPreFling(android.view.ViewParent, android.view.View, float, float);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[]);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[], int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int, int[]);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View, int);
+ method @Deprecated public static boolean requestSendAccessibilityEvent(android.view.ViewParent!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ }
+
+ public final class ViewPropertyAnimatorCompat {
+ method public androidx.core.view.ViewPropertyAnimatorCompat alpha(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat alphaBy(float);
+ method public void cancel();
+ method public long getDuration();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method public long getStartDelay();
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotation(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setDuration(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setInterpolator(android.view.animation.Interpolator?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setListener(androidx.core.view.ViewPropertyAnimatorListener?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setStartDelay(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setUpdateListener(androidx.core.view.ViewPropertyAnimatorUpdateListener?);
+ method public void start();
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZ(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withEndAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withLayer();
+ method public androidx.core.view.ViewPropertyAnimatorCompat withStartAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat x(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat xBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat y(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat yBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat z(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat zBy(float);
+ }
+
+ public interface ViewPropertyAnimatorListener {
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public class ViewPropertyAnimatorListenerAdapter implements androidx.core.view.ViewPropertyAnimatorListener {
+ ctor public ViewPropertyAnimatorListenerAdapter();
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public interface ViewPropertyAnimatorUpdateListener {
+ method public void onAnimationUpdate(android.view.View);
+ }
+
+ public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat getInsetsController(android.view.Window, android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
+ method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
+ field public static final int FEATURE_ACTION_BAR = 8; // 0x8
+ field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9
+ field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
+ }
+
+ public final class WindowInsetsAnimationCompat {
+ ctor public WindowInsetsAnimationCompat(int, android.view.animation.Interpolator?, long);
+ method @FloatRange(from=0.0f, to=1.0f) public float getAlpha();
+ method public long getDurationMillis();
+ method @FloatRange(from=0.0f, to=1.0f) public float getFraction();
+ method public float getInterpolatedFraction();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method public int getTypeMask();
+ method public void setAlpha(@FloatRange(from=0.0f, to=1.0f) float);
+ method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public static final class WindowInsetsAnimationCompat.BoundsCompat {
+ ctor public WindowInsetsAnimationCompat.BoundsCompat(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public androidx.core.graphics.Insets getLowerBound();
+ method public androidx.core.graphics.Insets getUpperBound();
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat inset(androidx.core.graphics.Insets);
+ method @RequiresApi(30) public android.view.WindowInsetsAnimation.Bounds toBounds();
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat toBoundsCompat(android.view.WindowInsetsAnimation.Bounds);
+ }
+
+ public abstract static class WindowInsetsAnimationCompat.Callback {
+ ctor public WindowInsetsAnimationCompat.Callback(int);
+ method public final int getDispatchMode();
+ method public void onEnd(androidx.core.view.WindowInsetsAnimationCompat);
+ method public void onPrepare(androidx.core.view.WindowInsetsAnimationCompat);
+ method public abstract androidx.core.view.WindowInsetsCompat onProgress(androidx.core.view.WindowInsetsCompat, java.util.List<androidx.core.view.WindowInsetsAnimationCompat!>);
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat onStart(androidx.core.view.WindowInsetsAnimationCompat, androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat);
+ field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
+ field public static final int DISPATCH_MODE_STOP = 0; // 0x0
+ }
+
+ public interface WindowInsetsAnimationControlListenerCompat {
+ method public void onCancelled(androidx.core.view.WindowInsetsAnimationControllerCompat?);
+ method public void onFinished(androidx.core.view.WindowInsetsAnimationControllerCompat);
+ method public void onReady(androidx.core.view.WindowInsetsAnimationControllerCompat, int);
+ }
+
+ public final class WindowInsetsAnimationControllerCompat {
+ method public void finish(boolean);
+ method public float getCurrentAlpha();
+ method @FloatRange(from=0.0f, to=1.0f) public float getCurrentFraction();
+ method public androidx.core.graphics.Insets getCurrentInsets();
+ method public androidx.core.graphics.Insets getHiddenStateInsets();
+ method public androidx.core.graphics.Insets getShownStateInsets();
+ method public int getTypes();
+ method public boolean isCancelled();
+ method public boolean isFinished();
+ method public boolean isReady();
+ method public void setInsetsAndAlpha(androidx.core.graphics.Insets?, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public class WindowInsetsCompat {
+ ctor public WindowInsetsCompat(androidx.core.view.WindowInsetsCompat?);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeDisplayCutout();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeStableInsets();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeSystemWindowInsets();
+ method public androidx.core.view.DisplayCutoutCompat? getDisplayCutout();
+ method public androidx.core.graphics.Insets getInsets(int);
+ method public androidx.core.graphics.Insets getInsetsIgnoringVisibility(int);
+ method @Deprecated public androidx.core.graphics.Insets getMandatorySystemGestureInsets();
+ method @Deprecated public int getStableInsetBottom();
+ method @Deprecated public int getStableInsetLeft();
+ method @Deprecated public int getStableInsetRight();
+ method @Deprecated public int getStableInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getStableInsets();
+ method @Deprecated public androidx.core.graphics.Insets getSystemGestureInsets();
+ method @Deprecated public int getSystemWindowInsetBottom();
+ method @Deprecated public int getSystemWindowInsetLeft();
+ method @Deprecated public int getSystemWindowInsetRight();
+ method @Deprecated public int getSystemWindowInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getSystemWindowInsets();
+ method @Deprecated public androidx.core.graphics.Insets getTappableElementInsets();
+ method public boolean hasInsets();
+ method @Deprecated public boolean hasStableInsets();
+ method @Deprecated public boolean hasSystemWindowInsets();
+ method public androidx.core.view.WindowInsetsCompat inset(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat inset(@IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+ method public boolean isConsumed();
+ method public boolean isRound();
+ method public boolean isVisible(int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(int, int, int, int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
+ method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets, android.view.View?);
+ field public static final androidx.core.view.WindowInsetsCompat CONSUMED;
+ }
+
+ public static final class WindowInsetsCompat.Builder {
+ ctor public WindowInsetsCompat.Builder();
+ ctor public WindowInsetsCompat.Builder(androidx.core.view.WindowInsetsCompat);
+ method public androidx.core.view.WindowInsetsCompat build();
+ method public androidx.core.view.WindowInsetsCompat.Builder setDisplayCutout(androidx.core.view.DisplayCutoutCompat?);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsets(int, androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsetsIgnoringVisibility(int, androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setMandatorySystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setStableInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemWindowInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setTappableElementInsets(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setVisible(int, boolean);
+ }
+
+ public static final class WindowInsetsCompat.Type {
+ method public static int captionBar();
+ method public static int displayCutout();
+ method public static int ime();
+ method public static int mandatorySystemGestures();
+ method public static int navigationBars();
+ method public static int statusBars();
+ method public static int systemBars();
+ method public static int systemGestures();
+ method public static int tappableElement();
+ }
+
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public void addOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void controlWindowInsetsAnimation(int, long, android.view.animation.Interpolator?, android.os.CancellationSignal?, androidx.core.view.WindowInsetsAnimationControlListenerCompat);
+ method public int getSystemBarsBehavior();
+ method public void hide(int);
+ method public boolean isAppearanceLightNavigationBars();
+ method public boolean isAppearanceLightStatusBars();
+ method public void removeOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void setAppearanceLightNavigationBars(boolean);
+ method public void setAppearanceLightStatusBars(boolean);
+ method public void setSystemBarsBehavior(int);
+ method public void show(int);
+ method @Deprecated @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_DEFAULT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
+ public static interface WindowInsetsControllerCompat.OnControllableInsetsChangedListener {
+ method public void onControllableInsetsChanged(androidx.core.view.WindowInsetsControllerCompat, int);
+ }
+
+}
+
+package androidx.core.view.accessibility {
+
+ public final class AccessibilityClickableSpanCompat extends android.text.style.ClickableSpan {
+ method public void onClick(android.view.View);
+ }
+
+ public final class AccessibilityEventCompat {
+ method @Deprecated public static void appendRecord(android.view.accessibility.AccessibilityEvent!, androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! asRecord(android.view.accessibility.AccessibilityEvent!);
+ method public static int getAction(android.view.accessibility.AccessibilityEvent);
+ method public static int getContentChangeTypes(android.view.accessibility.AccessibilityEvent);
+ method public static int getMovementGranularity(android.view.accessibility.AccessibilityEvent);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! getRecord(android.view.accessibility.AccessibilityEvent!, int);
+ method @Deprecated public static int getRecordCount(android.view.accessibility.AccessibilityEvent!);
+ method public static void setAction(android.view.accessibility.AccessibilityEvent, int);
+ method public static void setContentChangeTypes(android.view.accessibility.AccessibilityEvent, int);
+ method public static void setMovementGranularity(android.view.accessibility.AccessibilityEvent, int);
+ field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 512; // 0x200
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 256; // 0x100
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 128; // 0x80
+ field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10
+ field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20
+ field public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 8; // 0x8
+ field public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 64; // 0x40
+ field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
+ field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
+ field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
+ field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+ field public static final int TYPE_ASSIST_READING_CONTEXT = 16777216; // 0x1000000
+ field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
+ field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
+ field public static final int TYPE_TOUCH_INTERACTION_END = 2097152; // 0x200000
+ field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
+ field public static final int TYPE_VIEW_CONTEXT_CLICKED = 8388608; // 0x800000
+ field @Deprecated public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
+ field @Deprecated public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
+ field @Deprecated public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
+ field @Deprecated public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
+ field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
+ field public static final int TYPE_WINDOWS_CHANGED = 4194304; // 0x400000
+ field @Deprecated public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
+ }
+
+ public final class AccessibilityManagerCompat {
+ method @Deprecated public static boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getEnabledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!, int);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getInstalledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean isTouchExplorationEnabled(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ }
+
+ @Deprecated public static interface AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ method @Deprecated public void onAccessibilityStateChanged(boolean);
+ }
+
+ @Deprecated public abstract static class AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat implements androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ ctor @Deprecated public AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat();
+ }
+
+ public static interface AccessibilityManagerCompat.TouchExplorationStateChangeListener {
+ method public void onTouchExplorationStateChanged(boolean);
+ }
+
+ public class AccessibilityNodeInfoCompat {
+ ctor @Deprecated public AccessibilityNodeInfoCompat(Object!);
+ method public void addAction(int);
+ method public void addAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public void addChild(android.view.View!);
+ method public void addChild(android.view.View!, int);
+ method public boolean canOpenPopup();
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByText(String!);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByViewId(String!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! findFocus(int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! focusSearch(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!>! getActionList();
+ method @Deprecated public int getActions();
+ method public java.util.List<java.lang.String!> getAvailableExtraData();
+ method @Deprecated public void getBoundsInParent(android.graphics.Rect!);
+ method public void getBoundsInScreen(android.graphics.Rect!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getChild(int);
+ method public int getChildCount();
+ method public CharSequence! getClassName();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! getCollectionInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! getCollectionItemInfo();
+ method public CharSequence! getContentDescription();
+ method public int getDrawingOrder();
+ method public CharSequence! getError();
+ method public android.view.accessibility.AccessibilityNodeInfo.ExtraRenderingInfo? getExtraRenderingInfo();
+ method public android.os.Bundle! getExtras();
+ method public CharSequence? getHintText();
+ method @Deprecated public Object! getInfo();
+ method public int getInputType();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabelFor();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
+ method public int getLiveRegion();
+ method public int getMaxTextLength();
+ method public long getMinDurationBetweenContentChangesMillis();
+ method public int getMovementGranularities();
+ method public CharSequence! getPackageName();
+ method public CharSequence? getPaneTitle();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getParent();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! getRangeInfo();
+ method public CharSequence? getRoleDescription();
+ method public CharSequence? getStateDescription();
+ method public CharSequence! getText();
+ method public int getTextSelectionEnd();
+ method public int getTextSelectionStart();
+ method public CharSequence? getTooltipText();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat? getTouchDelegateInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalAfter();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalBefore();
+ method public String? getUniqueId();
+ method public String! getViewIdResourceName();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat! getWindow();
+ method public int getWindowId();
+ method public boolean hasRequestInitialAccessibilityFocus();
+ method public boolean isAccessibilityFocused();
+ method public boolean isCheckable();
+ method public boolean isChecked();
+ method public boolean isClickable();
+ method public boolean isContentInvalid();
+ method public boolean isContextClickable();
+ method public boolean isDismissable();
+ method public boolean isEditable();
+ method public boolean isEnabled();
+ method public boolean isFocusable();
+ method public boolean isFocused();
+ method public boolean isHeading();
+ method public boolean isImportantForAccessibility();
+ method public boolean isLongClickable();
+ method public boolean isMultiLine();
+ method public boolean isPassword();
+ method public boolean isScreenReaderFocusable();
+ method public boolean isScrollable();
+ method public boolean isSelected();
+ method public boolean isShowingHintText();
+ method public boolean isTextEntryKey();
+ method public boolean isTextSelectable();
+ method public boolean isVisibleToUser();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
+ method public boolean performAction(int);
+ method public boolean performAction(int, android.os.Bundle!);
+ method @Deprecated public void recycle();
+ method public boolean refresh();
+ method public boolean removeAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public boolean removeChild(android.view.View!);
+ method public boolean removeChild(android.view.View!, int);
+ method public void setAccessibilityFocused(boolean);
+ method public void setAvailableExtraData(java.util.List<java.lang.String!>);
+ method @Deprecated public void setBoundsInParent(android.graphics.Rect!);
+ method public void setBoundsInScreen(android.graphics.Rect!);
+ method public void setCanOpenPopup(boolean);
+ method public void setCheckable(boolean);
+ method public void setChecked(boolean);
+ method public void setClassName(CharSequence!);
+ method public void setClickable(boolean);
+ method public void setCollectionInfo(Object!);
+ method public void setCollectionItemInfo(Object!);
+ method public void setContentDescription(CharSequence!);
+ method public void setContentInvalid(boolean);
+ method public void setContextClickable(boolean);
+ method public void setDismissable(boolean);
+ method public void setDrawingOrder(int);
+ method public void setEditable(boolean);
+ method public void setEnabled(boolean);
+ method public void setError(CharSequence!);
+ method public void setFocusable(boolean);
+ method public void setFocused(boolean);
+ method public void setHeading(boolean);
+ method public void setHintText(CharSequence?);
+ method public void setImportantForAccessibility(boolean);
+ method public void setInputType(int);
+ method public void setLabelFor(android.view.View!);
+ method public void setLabelFor(android.view.View!, int);
+ method public void setLabeledBy(android.view.View!);
+ method public void setLabeledBy(android.view.View!, int);
+ method public void setLiveRegion(int);
+ method public void setLongClickable(boolean);
+ method public void setMaxTextLength(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
+ method public void setMovementGranularities(int);
+ method public void setMultiLine(boolean);
+ method public void setPackageName(CharSequence!);
+ method public void setPaneTitle(CharSequence?);
+ method public void setParent(android.view.View!);
+ method public void setParent(android.view.View!, int);
+ method public void setPassword(boolean);
+ method public void setRangeInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat!);
+ method public void setRequestInitialAccessibilityFocus(boolean);
+ method public void setRoleDescription(CharSequence?);
+ method public void setScreenReaderFocusable(boolean);
+ method public void setScrollable(boolean);
+ method public void setSelected(boolean);
+ method public void setShowingHintText(boolean);
+ method public void setSource(android.view.View!);
+ method public void setSource(android.view.View!, int);
+ method public void setStateDescription(CharSequence?);
+ method public void setText(CharSequence!);
+ method public void setTextEntryKey(boolean);
+ method public void setTextSelectable(boolean);
+ method public void setTextSelection(int, int);
+ method public void setTooltipText(CharSequence?);
+ method public void setTouchDelegateInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat);
+ method public void setTraversalAfter(android.view.View!);
+ method public void setTraversalAfter(android.view.View!, int);
+ method public void setTraversalBefore(android.view.View!);
+ method public void setTraversalBefore(android.view.View!, int);
+ method public void setUniqueId(String?);
+ method public void setViewIdResourceName(String!);
+ method public void setVisibleToUser(boolean);
+ method public android.view.accessibility.AccessibilityNodeInfo! unwrap();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! wrap(android.view.accessibility.AccessibilityNodeInfo);
+ field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+ field public static final String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
+ field public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
+ field public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
+ field public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_X = "ACTION_ARGUMENT_MOVE_WINDOW_X";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y = "ACTION_ARGUMENT_MOVE_WINDOW_Y";
+ field public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT = "android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT";
+ field public static final String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
+ field public static final String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
+ field public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
+ field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
+ field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
+ field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
+ field public static final int ACTION_CLICK = 16; // 0x10
+ field public static final int ACTION_COLLAPSE = 524288; // 0x80000
+ field public static final int ACTION_COPY = 16384; // 0x4000
+ field public static final int ACTION_CUT = 65536; // 0x10000
+ field public static final int ACTION_DISMISS = 1048576; // 0x100000
+ field public static final int ACTION_EXPAND = 262144; // 0x40000
+ field public static final int ACTION_FOCUS = 1; // 0x1
+ field public static final int ACTION_LONG_CLICK = 32; // 0x20
+ field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
+ field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
+ field public static final int ACTION_PASTE = 32768; // 0x8000
+ field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
+ field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
+ field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
+ field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
+ field public static final int ACTION_SELECT = 4; // 0x4
+ field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
+ field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+ field public static final int EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH = 20000; // 0x4e20
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
+ field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
+ field public static final int FOCUS_INPUT = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_LINE = 4; // 0x4
+ field public static final int MOVEMENT_GRANULARITY_PAGE = 16; // 0x10
+ field public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 8; // 0x8
+ field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
+ }
+
+ public static class AccessibilityNodeInfoCompat.AccessibilityActionCompat {
+ ctor public AccessibilityNodeInfoCompat.AccessibilityActionCompat(int, CharSequence!);
+ method public int getId();
+ method public CharSequence! getLabel();
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COLLAPSE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CONTEXT_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COPY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CUT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_DISMISS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_CANCEL;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_DROP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_START;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_EXPAND;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_HIDE_TOOLTIP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_IME_ENTER;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_LONG_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_MOVE_WINDOW;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PASTE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PRESS_AND_HOLD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_BACKWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_FORWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_TO_POSITION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SELECT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_PROGRESS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_TEXT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_ON_SCREEN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_SHOW_TEXT_SUGGESTIONS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_TOOLTIP;
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionInfoCompat {
+ method public int getColumnCount();
+ method public int getRowCount();
+ method public int getSelectionMode();
+ method public boolean isHierarchical();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean);
+ field public static final int SELECTION_MODE_MULTIPLE = 2; // 0x2
+ field public static final int SELECTION_MODE_NONE = 0; // 0x0
+ field public static final int SELECTION_MODE_SINGLE = 1; // 0x1
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionItemInfoCompat {
+ method public int getColumnIndex();
+ method public int getColumnSpan();
+ method public int getRowIndex();
+ method public int getRowSpan();
+ method @Deprecated public boolean isHeading();
+ method public boolean isSelected();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean, boolean);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean);
+ }
+
+ public static class AccessibilityNodeInfoCompat.RangeInfoCompat {
+ method public float getCurrent();
+ method public float getMax();
+ method public float getMin();
+ method public int getType();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! obtain(int, float, float, float);
+ field public static final int RANGE_TYPE_FLOAT = 1; // 0x1
+ field public static final int RANGE_TYPE_INT = 0; // 0x0
+ field public static final int RANGE_TYPE_PERCENT = 2; // 0x2
+ }
+
+ public static final class AccessibilityNodeInfoCompat.TouchDelegateInfoCompat {
+ ctor public AccessibilityNodeInfoCompat.TouchDelegateInfoCompat(java.util.Map<android.graphics.Region!,android.view.View!>);
+ method public android.graphics.Region? getRegionAt(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getRegionCount();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getTargetForRegion(android.graphics.Region);
+ }
+
+ public class AccessibilityNodeProviderCompat {
+ ctor public AccessibilityNodeProviderCompat();
+ ctor public AccessibilityNodeProviderCompat(Object?);
+ method public void addExtraDataToAccessibilityNodeInfo(int, androidx.core.view.accessibility.AccessibilityNodeInfoCompat, String, android.os.Bundle?);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? createAccessibilityNodeInfo(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>? findAccessibilityNodeInfosByText(String, int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? findFocus(int);
+ method public Object? getProvider();
+ method public boolean performAction(int, int, android.os.Bundle?);
+ field public static final int HOST_VIEW_ID = -1; // 0xffffffff
+ }
+
+ public class AccessibilityRecordCompat {
+ ctor @Deprecated public AccessibilityRecordCompat(Object!);
+ method @Deprecated public boolean equals(Object?);
+ method @Deprecated public int getAddedCount();
+ method @Deprecated public CharSequence! getBeforeText();
+ method @Deprecated public CharSequence! getClassName();
+ method @Deprecated public CharSequence! getContentDescription();
+ method @Deprecated public int getCurrentItemIndex();
+ method @Deprecated public int getFromIndex();
+ method @Deprecated public Object! getImpl();
+ method @Deprecated public int getItemCount();
+ method @Deprecated public int getMaxScrollX();
+ method public static int getMaxScrollX(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public int getMaxScrollY();
+ method public static int getMaxScrollY(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public android.os.Parcelable! getParcelableData();
+ method @Deprecated public int getRemovedCount();
+ method @Deprecated public int getScrollX();
+ method @Deprecated public int getScrollY();
+ method @Deprecated public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getSource();
+ method @Deprecated public java.util.List<java.lang.CharSequence!>! getText();
+ method @Deprecated public int getToIndex();
+ method @Deprecated public int getWindowId();
+ method @Deprecated public int hashCode();
+ method @Deprecated public boolean isChecked();
+ method @Deprecated public boolean isEnabled();
+ method @Deprecated public boolean isFullScreen();
+ method @Deprecated public boolean isPassword();
+ method @Deprecated public boolean isScrollable();
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain(androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain();
+ method @Deprecated public void recycle();
+ method @Deprecated public void setAddedCount(int);
+ method @Deprecated public void setBeforeText(CharSequence!);
+ method @Deprecated public void setChecked(boolean);
+ method @Deprecated public void setClassName(CharSequence!);
+ method @Deprecated public void setContentDescription(CharSequence!);
+ method @Deprecated public void setCurrentItemIndex(int);
+ method @Deprecated public void setEnabled(boolean);
+ method @Deprecated public void setFromIndex(int);
+ method @Deprecated public void setFullScreen(boolean);
+ method @Deprecated public void setItemCount(int);
+ method @Deprecated public void setMaxScrollX(int);
+ method public static void setMaxScrollX(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setMaxScrollY(int);
+ method public static void setMaxScrollY(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setParcelableData(android.os.Parcelable!);
+ method @Deprecated public void setPassword(boolean);
+ method @Deprecated public void setRemovedCount(int);
+ method @Deprecated public void setScrollX(int);
+ method @Deprecated public void setScrollY(int);
+ method @Deprecated public void setScrollable(boolean);
+ method @Deprecated public void setSource(android.view.View!);
+ method @Deprecated public void setSource(android.view.View!, int);
+ method public static void setSource(android.view.accessibility.AccessibilityRecord, android.view.View?, int);
+ method @Deprecated public void setToIndex(int);
+ }
+
+ public interface AccessibilityViewCommand {
+ method public boolean perform(android.view.View, androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments?);
+ }
+
+ public abstract static class AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.CommandArguments();
+ }
+
+ public static final class AccessibilityViewCommand.MoveAtGranularityArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveAtGranularityArguments();
+ method public boolean getExtendSelection();
+ method public int getGranularity();
+ }
+
+ public static final class AccessibilityViewCommand.MoveHtmlArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveHtmlArguments();
+ method public String? getHTMLElement();
+ }
+
+ public static final class AccessibilityViewCommand.MoveWindowArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveWindowArguments();
+ method public int getX();
+ method public int getY();
+ }
+
+ public static final class AccessibilityViewCommand.ScrollToPositionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.ScrollToPositionArguments();
+ method public int getColumn();
+ method public int getRow();
+ }
+
+ public static final class AccessibilityViewCommand.SetProgressArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetProgressArguments();
+ method public float getProgress();
+ }
+
+ public static final class AccessibilityViewCommand.SetSelectionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetSelectionArguments();
+ method public int getEnd();
+ method public int getStart();
+ }
+
+ public static final class AccessibilityViewCommand.SetTextArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetTextArguments();
+ method public CharSequence? getText();
+ }
+
+ public class AccessibilityWindowInfoCompat {
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getAnchor();
+ method public void getBoundsInScreen(android.graphics.Rect);
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getChild(int);
+ method public int getChildCount();
+ method public int getDisplayId();
+ method public int getId();
+ method public int getLayer();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getParent();
+ method public void getRegionInScreen(android.graphics.Region);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getRoot();
+ method public CharSequence? getTitle();
+ method public int getType();
+ method public boolean isAccessibilityFocused();
+ method public boolean isActive();
+ method public boolean isFocused();
+ method public boolean isInPictureInPictureMode();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain(androidx.core.view.accessibility.AccessibilityWindowInfoCompat?);
+ method @Deprecated public void recycle();
+ method public android.view.accessibility.AccessibilityWindowInfo? unwrap();
+ field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
+ field public static final int TYPE_APPLICATION = 1; // 0x1
+ field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
+ field public static final int TYPE_SYSTEM = 3; // 0x3
+ }
+
+}
+
+package androidx.core.view.animation {
+
+ public final class PathInterpolatorCompat {
+ method public static android.view.animation.Interpolator create(android.graphics.Path);
+ method public static android.view.animation.Interpolator create(float, float);
+ method public static android.view.animation.Interpolator create(float, float, float, float);
+ }
+
+}
+
+package androidx.core.view.inputmethod {
+
+ public final class EditorInfoCompat {
+ ctor @Deprecated public EditorInfoCompat();
+ method public static String![] getContentMimeTypes(android.view.inputmethod.EditorInfo);
+ method public static CharSequence? getInitialSelectedText(android.view.inputmethod.EditorInfo, int);
+ method public static CharSequence? getInitialTextAfterCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static CharSequence? getInitialTextBeforeCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static void setContentMimeTypes(android.view.inputmethod.EditorInfo, String![]?);
+ method public static void setInitialSurroundingSubText(android.view.inputmethod.EditorInfo, CharSequence, int);
+ method public static void setInitialSurroundingText(android.view.inputmethod.EditorInfo, CharSequence);
+ field public static final int IME_FLAG_FORCE_ASCII = -2147483648; // 0x80000000
+ field public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 16777216; // 0x1000000
+ }
+
+ public final class InputConnectionCompat {
+ ctor @Deprecated public InputConnectionCompat();
+ method public static boolean commitContent(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ method @Deprecated public static android.view.inputmethod.InputConnection createWrapper(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener);
+ method public static android.view.inputmethod.InputConnection createWrapper(android.view.View, android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
+ }
+
+ public static interface InputConnectionCompat.OnCommitContentListener {
+ method public boolean onCommitContent(androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ }
+
+ public final class InputContentInfoCompat {
+ ctor public InputContentInfoCompat(android.net.Uri, android.content.ClipDescription, android.net.Uri?);
+ method public android.net.Uri getContentUri();
+ method public android.content.ClipDescription getDescription();
+ method public android.net.Uri? getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
+ method public Object? unwrap();
+ method public static androidx.core.view.inputmethod.InputContentInfoCompat? wrap(Object?);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public abstract class AutoScrollHelper implements android.view.View.OnTouchListener {
+ ctor public AutoScrollHelper(android.view.View);
+ method public abstract boolean canTargetScrollHorizontally(int);
+ method public abstract boolean canTargetScrollVertically(int);
+ method public boolean isEnabled();
+ method public boolean isExclusive();
+ method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+ method public abstract void scrollTargetBy(int, int);
+ method public androidx.core.widget.AutoScrollHelper setActivationDelay(int);
+ method public androidx.core.widget.AutoScrollHelper setEdgeType(int);
+ method public androidx.core.widget.AutoScrollHelper! setEnabled(boolean);
+ method public androidx.core.widget.AutoScrollHelper! setExclusive(boolean);
+ method public androidx.core.widget.AutoScrollHelper setMaximumEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMaximumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMinimumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRampDownDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRampUpDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRelativeEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRelativeVelocity(float, float);
+ field public static final int EDGE_TYPE_INSIDE = 0; // 0x0
+ field public static final int EDGE_TYPE_INSIDE_EXTEND = 1; // 0x1
+ field public static final int EDGE_TYPE_OUTSIDE = 2; // 0x2
+ field public static final float NO_MAX = 3.4028235E38f;
+ field public static final float NO_MIN = 0.0f;
+ field public static final float RELATIVE_UNSPECIFIED = 0.0f;
+ }
+
+ public final class CheckedTextViewCompat {
+ method public static android.graphics.drawable.Drawable? getCheckMarkDrawable(android.widget.CheckedTextView);
+ method public static android.content.res.ColorStateList? getCheckMarkTintList(android.widget.CheckedTextView);
+ method public static android.graphics.PorterDuff.Mode? getCheckMarkTintMode(android.widget.CheckedTextView);
+ method public static void setCheckMarkTintList(android.widget.CheckedTextView, android.content.res.ColorStateList?);
+ method public static void setCheckMarkTintMode(android.widget.CheckedTextView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class CompoundButtonCompat {
+ method public static android.graphics.drawable.Drawable? getButtonDrawable(android.widget.CompoundButton);
+ method public static android.content.res.ColorStateList? getButtonTintList(android.widget.CompoundButton);
+ method public static android.graphics.PorterDuff.Mode? getButtonTintMode(android.widget.CompoundButton);
+ method public static void setButtonTintList(android.widget.CompoundButton, android.content.res.ColorStateList?);
+ method public static void setButtonTintMode(android.widget.CompoundButton, android.graphics.PorterDuff.Mode?);
+ }
+
+ public class ContentLoadingProgressBar extends android.widget.ProgressBar {
+ ctor public ContentLoadingProgressBar(android.content.Context);
+ ctor public ContentLoadingProgressBar(android.content.Context, android.util.AttributeSet?);
+ method public void hide();
+ method public void onAttachedToWindow();
+ method public void onDetachedFromWindow();
+ method public void show();
+ }
+
+ public final class EdgeEffectCompat {
+ ctor @Deprecated public EdgeEffectCompat(android.content.Context!);
+ method public static android.widget.EdgeEffect create(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public boolean draw(android.graphics.Canvas!);
+ method @Deprecated public void finish();
+ method public static float getDistance(android.widget.EdgeEffect);
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean onAbsorb(int);
+ method @Deprecated public boolean onPull(float);
+ method @Deprecated public boolean onPull(float, float);
+ method public static void onPull(android.widget.EdgeEffect, float, float);
+ method public static float onPullDistance(android.widget.EdgeEffect, float, float);
+ method @Deprecated public boolean onRelease();
+ method @Deprecated public void setSize(int, int);
+ }
+
+ public class ImageViewCompat {
+ method public static android.content.res.ColorStateList? getImageTintList(android.widget.ImageView);
+ method public static android.graphics.PorterDuff.Mode? getImageTintMode(android.widget.ImageView);
+ method public static void setImageTintList(android.widget.ImageView, android.content.res.ColorStateList?);
+ method public static void setImageTintMode(android.widget.ImageView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class ListPopupWindowCompat {
+ method @Deprecated public static android.view.View.OnTouchListener! createDragToOpenListener(Object!, android.view.View!);
+ method public static android.view.View.OnTouchListener? createDragToOpenListener(android.widget.ListPopupWindow, android.view.View);
+ }
+
+ public class ListViewAutoScrollHelper extends androidx.core.widget.AutoScrollHelper {
+ ctor public ListViewAutoScrollHelper(android.widget.ListView);
+ method public boolean canTargetScrollHorizontally(int);
+ method public boolean canTargetScrollVertically(int);
+ method public void scrollTargetBy(int, int);
+ }
+
+ public final class ListViewCompat {
+ method public static boolean canScrollList(android.widget.ListView, int);
+ method public static void scrollListBy(android.widget.ListView, int);
+ }
+
+ public class NestedScrollView extends android.widget.FrameLayout implements androidx.core.view.NestedScrollingChild3 androidx.core.view.NestedScrollingParent3 androidx.core.view.ScrollingView {
+ ctor public NestedScrollView(android.content.Context);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?, int);
+ method public boolean arrowScroll(int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollRange();
+ method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollRange();
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public boolean executeKeyEvent(android.view.KeyEvent);
+ method public void fling(int);
+ method public boolean fullScroll(int);
+ method public int getMaxScrollAmount();
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean isFillViewport();
+ method public boolean isSmoothScrollingEnabled();
+ method public void onAttachedToWindow();
+ method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View, int);
+ method public boolean pageScroll(int);
+ method public void setFillViewport(boolean);
+ method public void setOnScrollChangeListener(androidx.core.widget.NestedScrollView.OnScrollChangeListener?);
+ method public void setSmoothScrollingEnabled(boolean);
+ method public final void smoothScrollBy(int, int);
+ method public final void smoothScrollBy(int, int, int);
+ method public final void smoothScrollTo(int, int);
+ method public final void smoothScrollTo(int, int, int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll(int);
+ }
+
+ public static interface NestedScrollView.OnScrollChangeListener {
+ method public void onScrollChange(androidx.core.widget.NestedScrollView, int, int, int, int);
+ }
+
+ public final class PopupMenuCompat {
+ method public static android.view.View.OnTouchListener? getDragToOpenListener(Object);
+ }
+
+ public final class PopupWindowCompat {
+ method public static boolean getOverlapAnchor(android.widget.PopupWindow);
+ method public static int getWindowLayoutType(android.widget.PopupWindow);
+ method public static void setOverlapAnchor(android.widget.PopupWindow, boolean);
+ method public static void setWindowLayoutType(android.widget.PopupWindow, int);
+ method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
+ }
+
+ @Deprecated public final class ScrollerCompat {
+ method @Deprecated public void abortAnimation();
+ method @Deprecated public boolean computeScrollOffset();
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!);
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!, android.view.animation.Interpolator!);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int, int, int);
+ method @Deprecated public float getCurrVelocity();
+ method @Deprecated public int getCurrX();
+ method @Deprecated public int getCurrY();
+ method @Deprecated public int getFinalX();
+ method @Deprecated public int getFinalY();
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean isOverScrolled();
+ method @Deprecated public void notifyHorizontalEdgeReached(int, int, int);
+ method @Deprecated public void notifyVerticalEdgeReached(int, int, int);
+ method @Deprecated public boolean springBack(int, int, int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int, int);
+ }
+
+ public final class TextViewCompat {
+ method public static int getAutoSizeMaxTextSize(android.widget.TextView);
+ method public static int getAutoSizeMinTextSize(android.widget.TextView);
+ method public static int getAutoSizeStepGranularity(android.widget.TextView);
+ method public static int[] getAutoSizeTextAvailableSizes(android.widget.TextView);
+ method public static int getAutoSizeTextType(android.widget.TextView);
+ method public static android.content.res.ColorStateList? getCompoundDrawableTintList(android.widget.TextView);
+ method public static android.graphics.PorterDuff.Mode? getCompoundDrawableTintMode(android.widget.TextView);
+ method public static android.graphics.drawable.Drawable![] getCompoundDrawablesRelative(android.widget.TextView);
+ method public static int getFirstBaselineToTopHeight(android.widget.TextView);
+ method public static int getLastBaselineToBottomHeight(android.widget.TextView);
+ method public static int getMaxLines(android.widget.TextView);
+ method public static int getMinLines(android.widget.TextView);
+ method public static androidx.core.text.PrecomputedTextCompat.Params getTextMetricsParams(android.widget.TextView);
+ method public static void setAutoSizeTextTypeUniformWithConfiguration(android.widget.TextView, int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeUniformWithPresetSizes(android.widget.TextView, int[], int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeWithDefaults(android.widget.TextView, int);
+ method public static void setCompoundDrawableTintList(android.widget.TextView, android.content.res.ColorStateList?);
+ method public static void setCompoundDrawableTintMode(android.widget.TextView, android.graphics.PorterDuff.Mode?);
+ method public static void setCompoundDrawablesRelative(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, @DrawableRes int, @DrawableRes int, @DrawableRes int, @DrawableRes int);
+ method public static void setCustomSelectionActionModeCallback(android.widget.TextView, android.view.ActionMode.Callback);
+ method public static void setFirstBaselineToTopHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLastBaselineToBottomHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLineHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setPrecomputedText(android.widget.TextView, androidx.core.text.PrecomputedTextCompat);
+ method public static void setTextAppearance(android.widget.TextView, @StyleRes int);
+ method public static void setTextMetricsParams(android.widget.TextView, androidx.core.text.PrecomputedTextCompat.Params);
+ field public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0; // 0x0
+ field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
+ }
+
+ public interface TintableCompoundButton {
+ method public android.content.res.ColorStateList? getSupportButtonTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
+ method public void setSupportButtonTintList(android.content.res.ColorStateList?);
+ method public void setSupportButtonTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ public interface TintableCompoundDrawablesView {
+ method public android.content.res.ColorStateList? getSupportCompoundDrawablesTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportCompoundDrawablesTintMode();
+ method public void setSupportCompoundDrawablesTintList(android.content.res.ColorStateList?);
+ method public void setSupportCompoundDrawablesTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+}
+
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 5033a53..f8aa350 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -3253,7 +3253,7 @@
method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
method public int getLiveRegion();
method public int getMaxTextLength();
- method public int getMinMillisBetweenContentChanges();
+ method public long getMinDurationBetweenContentChangesMillis();
method public int getMovementGranularities();
method public CharSequence! getPackageName();
method public CharSequence? getPaneTitle();
@@ -3339,7 +3339,7 @@
method public void setLiveRegion(int);
method public void setLongClickable(boolean);
method public void setMaxTextLength(int);
- method public void setMinMillisBetweenContentChanges(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
method public void setMovementGranularities(int);
method public void setMultiLine(boolean);
method public void setPackageName(CharSequence!);
diff --git a/core/core/api/public_plus_experimental_1.10.0-beta01.txt b/core/core/api/public_plus_experimental_1.10.0-beta01.txt
new file mode 100644
index 0000000..a1e0e3c
--- /dev/null
+++ b/core/core/api/public_plus_experimental_1.10.0-beta01.txt
@@ -0,0 +1,3935 @@
+// Signature format: 4.0
+package androidx.core.accessibilityservice {
+
+ public final class AccessibilityServiceInfoCompat {
+ method public static String capabilityToString(int);
+ method public static String feedbackTypeToString(int);
+ method public static String? flagToString(int);
+ method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
+ method public static String? loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
+ field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
+ field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
+ field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
+ field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
+ field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
+ field public static final int FEEDBACK_BRAILLE = 32; // 0x20
+ field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
+ field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
+ field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
+ field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
+ }
+
+}
+
+package androidx.core.app {
+
+ public class ActivityCompat extends androidx.core.content.ContextCompat {
+ ctor protected ActivityCompat();
+ method public static void finishAffinity(android.app.Activity);
+ method public static void finishAfterTransition(android.app.Activity);
+ method public static android.net.Uri? getReferrer(android.app.Activity);
+ method @Deprecated public static boolean invalidateOptionsMenu(android.app.Activity!);
+ method public static boolean isLaunchedFromBubble(android.app.Activity);
+ method public static void postponeEnterTransition(android.app.Activity);
+ method public static void recreate(android.app.Activity);
+ method public static androidx.core.view.DragAndDropPermissionsCompat? requestDragAndDropPermissions(android.app.Activity, android.view.DragEvent);
+ method public static void requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ method public static <T extends android.view.View> T requireViewById(android.app.Activity, @IdRes int);
+ method public static void setEnterSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setExitSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setLocusContext(android.app.Activity, androidx.core.content.LocusIdCompat?, android.os.Bundle?);
+ method public static void setPermissionCompatDelegate(androidx.core.app.ActivityCompat.PermissionCompatDelegate?);
+ method public static boolean shouldShowRequestPermissionRationale(android.app.Activity, String);
+ method public static void startActivityForResult(android.app.Activity, android.content.Intent, int, android.os.Bundle?);
+ method public static void startIntentSenderForResult(android.app.Activity, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public static void startPostponedEnterTransition(android.app.Activity);
+ }
+
+ public static interface ActivityCompat.OnRequestPermissionsResultCallback {
+ method public void onRequestPermissionsResult(int, String![], int[]);
+ }
+
+ public static interface ActivityCompat.PermissionCompatDelegate {
+ method public boolean onActivityResult(android.app.Activity, @IntRange(from=0) int, int, android.content.Intent?);
+ method public boolean requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ }
+
+ public final class ActivityManagerCompat {
+ method public static boolean isLowRamDevice(android.app.ActivityManager);
+ }
+
+ public class ActivityOptionsCompat {
+ ctor protected ActivityOptionsCompat();
+ method public android.graphics.Rect? getLaunchBounds();
+ method public static androidx.core.app.ActivityOptionsCompat makeBasic();
+ method public static androidx.core.app.ActivityOptionsCompat makeClipRevealAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeCustomAnimation(android.content.Context, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeScaleUpAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, android.view.View, String);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, androidx.core.util.Pair<android.view.View!,java.lang.String!>!...);
+ method public static androidx.core.app.ActivityOptionsCompat makeTaskLaunchBehind();
+ method public static androidx.core.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+ method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public androidx.core.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect?);
+ method public android.os.Bundle? toBundle();
+ method public void update(androidx.core.app.ActivityOptionsCompat);
+ field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
+ field public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
+ }
+
+ public final class AlarmManagerCompat {
+ method public static void setAlarmClock(android.app.AlarmManager, long, android.app.PendingIntent, android.app.PendingIntent);
+ method public static void setAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExact(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExactAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ }
+
+ @RequiresApi(28) public class AppComponentFactory extends android.app.AppComponentFactory {
+ ctor public AppComponentFactory();
+ method public final android.app.Activity instantiateActivity(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Activity instantiateActivityCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Application instantiateApplication(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Application instantiateApplicationCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.ContentProvider instantiateProvider(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.ContentProvider instantiateProviderCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.BroadcastReceiver instantiateReceiver(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.BroadcastReceiver instantiateReceiverCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Service instantiateService(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Service instantiateServiceCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ }
+
+ public class AppLaunchChecker {
+ ctor @Deprecated public AppLaunchChecker();
+ method public static boolean hasStartedFromLauncher(android.content.Context);
+ method public static void onActivityCreate(android.app.Activity);
+ }
+
+ public final class AppOpsManagerCompat {
+ method public static int checkOrNoteProxyOp(android.content.Context, int, String, String);
+ method public static int noteOp(android.content.Context, String, int, String);
+ method public static int noteOpNoThrow(android.content.Context, String, int, String);
+ method public static int noteProxyOp(android.content.Context, String, String);
+ method public static int noteProxyOpNoThrow(android.content.Context, String, String);
+ method public static String? permissionToOp(String);
+ field public static final int MODE_ALLOWED = 0; // 0x0
+ field public static final int MODE_DEFAULT = 3; // 0x3
+ field public static final int MODE_ERRORED = 2; // 0x2
+ field public static final int MODE_IGNORED = 1; // 0x1
+ }
+
+ public final class BundleCompat {
+ method public static android.os.IBinder? getBinder(android.os.Bundle, String?);
+ method public static void putBinder(android.os.Bundle, String?, android.os.IBinder?);
+ }
+
+ public class DialogCompat {
+ method public static android.view.View requireViewById(android.app.Dialog, int);
+ }
+
+ public class FrameMetricsAggregator {
+ ctor public FrameMetricsAggregator();
+ ctor public FrameMetricsAggregator(int);
+ method public void add(android.app.Activity);
+ method public android.util.SparseIntArray![]? getMetrics();
+ method public android.util.SparseIntArray![]? remove(android.app.Activity);
+ method public android.util.SparseIntArray![]? reset();
+ method public android.util.SparseIntArray![]? stop();
+ field public static final int ANIMATION_DURATION = 256; // 0x100
+ field public static final int ANIMATION_INDEX = 8; // 0x8
+ field public static final int COMMAND_DURATION = 32; // 0x20
+ field public static final int COMMAND_INDEX = 5; // 0x5
+ field public static final int DELAY_DURATION = 128; // 0x80
+ field public static final int DELAY_INDEX = 7; // 0x7
+ field public static final int DRAW_DURATION = 8; // 0x8
+ field public static final int DRAW_INDEX = 3; // 0x3
+ field public static final int EVERY_DURATION = 511; // 0x1ff
+ field public static final int INPUT_DURATION = 2; // 0x2
+ field public static final int INPUT_INDEX = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 4; // 0x4
+ field public static final int LAYOUT_MEASURE_INDEX = 2; // 0x2
+ field public static final int SWAP_DURATION = 64; // 0x40
+ field public static final int SWAP_INDEX = 6; // 0x6
+ field public static final int SYNC_DURATION = 16; // 0x10
+ field public static final int SYNC_INDEX = 4; // 0x4
+ field public static final int TOTAL_DURATION = 1; // 0x1
+ field public static final int TOTAL_INDEX = 0; // 0x0
+ }
+
+ @Deprecated public abstract class JobIntentService extends android.app.Service {
+ ctor @Deprecated public JobIntentService();
+ method @Deprecated public static void enqueueWork(android.content.Context, Class<?>, int, android.content.Intent);
+ method @Deprecated public static void enqueueWork(android.content.Context, android.content.ComponentName, int, android.content.Intent);
+ method @Deprecated public boolean isStopped();
+ method @Deprecated public android.os.IBinder! onBind(android.content.Intent);
+ method @Deprecated protected abstract void onHandleWork(android.content.Intent);
+ method @Deprecated public boolean onStopCurrentWork();
+ method @Deprecated public void setInterruptIfStopped(boolean);
+ }
+
+ public final class LocaleManagerCompat {
+ method @AnyThread public static androidx.core.os.LocaleListCompat getSystemLocales(android.content.Context);
+ }
+
+ public final class MultiWindowModeChangedInfo {
+ ctor public MultiWindowModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public MultiWindowModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInMultiWindowMode();
+ }
+
+ public final class NavUtils {
+ method public static android.content.Intent? getParentActivityIntent(android.app.Activity);
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, Class<?>) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static String? getParentActivityName(android.app.Activity);
+ method public static String? getParentActivityName(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void navigateUpFromSameTask(android.app.Activity);
+ method public static void navigateUpTo(android.app.Activity, android.content.Intent);
+ method public static boolean shouldUpRecreateTask(android.app.Activity, android.content.Intent);
+ field public static final String PARENT_ACTIVITY = "android.support.PARENT_ACTIVITY";
+ }
+
+ public class NotificationChannelCompat {
+ method public boolean canBubble();
+ method public boolean canBypassDnd();
+ method public boolean canShowBadge();
+ method public android.media.AudioAttributes? getAudioAttributes();
+ method public String? getConversationId();
+ method public String? getDescription();
+ method public String? getGroup();
+ method public String getId();
+ method public int getImportance();
+ method public int getLightColor();
+ method public int getLockscreenVisibility();
+ method public CharSequence? getName();
+ method public String? getParentChannelId();
+ method public android.net.Uri? getSound();
+ method public long[]? getVibrationPattern();
+ method public boolean isImportantConversation();
+ method public boolean shouldShowLights();
+ method public boolean shouldVibrate();
+ method public androidx.core.app.NotificationChannelCompat.Builder toBuilder();
+ field public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
+ }
+
+ public static class NotificationChannelCompat.Builder {
+ ctor public NotificationChannelCompat.Builder(String, int);
+ method public androidx.core.app.NotificationChannelCompat build();
+ method public androidx.core.app.NotificationChannelCompat.Builder setConversationId(String, String);
+ method public androidx.core.app.NotificationChannelCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setImportance(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightColor(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightsEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setName(CharSequence?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setShowBadge(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setSound(android.net.Uri?, android.media.AudioAttributes?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationPattern(long[]?);
+ }
+
+ public class NotificationChannelGroupCompat {
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getChannels();
+ method public String? getDescription();
+ method public String getId();
+ method public CharSequence? getName();
+ method public boolean isBlocked();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder toBuilder();
+ }
+
+ public static class NotificationChannelGroupCompat.Builder {
+ ctor public NotificationChannelGroupCompat.Builder(String);
+ method public androidx.core.app.NotificationChannelGroupCompat build();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setName(CharSequence?);
+ }
+
+ public class NotificationCompat {
+ ctor @Deprecated public NotificationCompat();
+ method public static androidx.core.app.NotificationCompat.Action? getAction(android.app.Notification, int);
+ method public static int getActionCount(android.app.Notification);
+ method public static boolean getAllowSystemGeneratedContextualActions(android.app.Notification);
+ method public static boolean getAutoCancel(android.app.Notification);
+ method public static int getBadgeIconType(android.app.Notification);
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? getBubbleMetadata(android.app.Notification);
+ method public static String? getCategory(android.app.Notification);
+ method public static String? getChannelId(android.app.Notification);
+ method public static int getColor(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentInfo(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentText(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentTitle(android.app.Notification);
+ method public static android.os.Bundle? getExtras(android.app.Notification);
+ method public static String? getGroup(android.app.Notification);
+ method public static int getGroupAlertBehavior(android.app.Notification);
+ method @RequiresApi(21) public static java.util.List<androidx.core.app.NotificationCompat.Action!> getInvisibleActions(android.app.Notification);
+ method public static boolean getLocalOnly(android.app.Notification);
+ method public static androidx.core.content.LocusIdCompat? getLocusId(android.app.Notification);
+ method public static boolean getOngoing(android.app.Notification);
+ method public static boolean getOnlyAlertOnce(android.app.Notification);
+ method public static java.util.List<androidx.core.app.Person!> getPeople(android.app.Notification);
+ method public static android.app.Notification? getPublicVersion(android.app.Notification);
+ method public static CharSequence? getSettingsText(android.app.Notification);
+ method public static String? getShortcutId(android.app.Notification);
+ method @RequiresApi(19) public static boolean getShowWhen(android.app.Notification);
+ method public static String? getSortKey(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getSubText(android.app.Notification);
+ method public static long getTimeoutAfter(android.app.Notification);
+ method @RequiresApi(19) public static boolean getUsesChronometer(android.app.Notification);
+ method public static int getVisibility(android.app.Notification);
+ method public static boolean isGroupSummary(android.app.Notification);
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
+ field public static final String CATEGORY_ALARM = "alarm";
+ field public static final String CATEGORY_CALL = "call";
+ field public static final String CATEGORY_EMAIL = "email";
+ field public static final String CATEGORY_ERROR = "err";
+ field public static final String CATEGORY_EVENT = "event";
+ field public static final String CATEGORY_LOCATION_SHARING = "location_sharing";
+ field public static final String CATEGORY_MESSAGE = "msg";
+ field public static final String CATEGORY_MISSED_CALL = "missed_call";
+ field public static final String CATEGORY_NAVIGATION = "navigation";
+ field public static final String CATEGORY_PROGRESS = "progress";
+ field public static final String CATEGORY_PROMO = "promo";
+ field public static final String CATEGORY_RECOMMENDATION = "recommendation";
+ field public static final String CATEGORY_REMINDER = "reminder";
+ field public static final String CATEGORY_SERVICE = "service";
+ field public static final String CATEGORY_SOCIAL = "social";
+ field public static final String CATEGORY_STATUS = "status";
+ field public static final String CATEGORY_STOPWATCH = "stopwatch";
+ field public static final String CATEGORY_SYSTEM = "sys";
+ field public static final String CATEGORY_TRANSPORT = "transport";
+ field public static final String CATEGORY_WORKOUT = "workout";
+ field @ColorInt public static final int COLOR_DEFAULT = 0; // 0x0
+ field public static final int DEFAULT_ALL = -1; // 0xffffffff
+ field public static final int DEFAULT_LIGHTS = 4; // 0x4
+ field public static final int DEFAULT_SOUND = 1; // 0x1
+ field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
+ field public static final String EXTRA_ANSWER_INTENT = "android.answerIntent";
+ field public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
+ field public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
+ field public static final String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final String EXTRA_CALL_IS_VIDEO = "android.callIsVideo";
+ field public static final String EXTRA_CALL_PERSON = "android.callPerson";
+ field public static final String EXTRA_CALL_PERSON_COMPAT = "android.callPersonCompat";
+ field public static final String EXTRA_CALL_TYPE = "android.callType";
+ field public static final String EXTRA_CHANNEL_GROUP_ID = "android.intent.extra.CHANNEL_GROUP_ID";
+ field public static final String EXTRA_CHANNEL_ID = "android.intent.extra.CHANNEL_ID";
+ field public static final String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+ field public static final String EXTRA_COLORIZED = "android.colorized";
+ field public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
+ field public static final String EXTRA_COMPAT_TEMPLATE = "androidx.core.app.extra.COMPAT_TEMPLATE";
+ field public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
+ field public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
+ field public static final String EXTRA_DECLINE_INTENT = "android.declineIntent";
+ field public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
+ field public static final String EXTRA_HIDDEN_CONVERSATION_TITLE = "android.hiddenConversationTitle";
+ field public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
+ field public static final String EXTRA_INFO_TEXT = "android.infoText";
+ field public static final String EXTRA_IS_GROUP_CONVERSATION = "android.isGroupConversation";
+ field public static final String EXTRA_LARGE_ICON = "android.largeIcon";
+ field public static final String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
+ field public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final String EXTRA_MESSAGES = "android.messages";
+ field public static final String EXTRA_MESSAGING_STYLE_USER = "android.messagingStyleUser";
+ field public static final String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
+ field public static final String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
+ field @Deprecated public static final String EXTRA_PEOPLE = "android.people";
+ field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
+ field public static final String EXTRA_PICTURE = "android.picture";
+ field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
+ field public static final String EXTRA_PICTURE_ICON = "android.pictureIcon";
+ field public static final String EXTRA_PROGRESS = "android.progress";
+ field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
+ field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
+ field public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+ field public static final String EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED = "android.showBigPictureWhenCollapsed";
+ field public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
+ field public static final String EXTRA_SHOW_WHEN = "android.showWhen";
+ field public static final String EXTRA_SMALL_ICON = "android.icon";
+ field public static final String EXTRA_SUB_TEXT = "android.subText";
+ field public static final String EXTRA_SUMMARY_TEXT = "android.summaryText";
+ field public static final String EXTRA_TEMPLATE = "android.template";
+ field public static final String EXTRA_TEXT = "android.text";
+ field public static final String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final String EXTRA_TITLE = "android.title";
+ field public static final String EXTRA_TITLE_BIG = "android.title.big";
+ field public static final String EXTRA_VERIFICATION_ICON = "android.verificationIcon";
+ field public static final String EXTRA_VERIFICATION_ICON_COMPAT = "android.verificationIconCompat";
+ field public static final String EXTRA_VERIFICATION_TEXT = "android.verificationText";
+ field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
+ field public static final int FLAG_BUBBLE = 4096; // 0x1000
+ field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+ field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
+ field @Deprecated public static final int FLAG_HIGH_PRIORITY = 128; // 0x80
+ field public static final int FLAG_INSISTENT = 4; // 0x4
+ field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
+ field public static final int FLAG_NO_CLEAR = 32; // 0x20
+ field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
+ field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
+ field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
+ field public static final int FOREGROUND_SERVICE_DEFAULT = 0; // 0x0
+ field public static final int FOREGROUND_SERVICE_DEFERRED = 2; // 0x2
+ field public static final int FOREGROUND_SERVICE_IMMEDIATE = 1; // 0x1
+ field public static final int GROUP_ALERT_ALL = 0; // 0x0
+ field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2
+ field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1
+ field public static final String GROUP_KEY_SILENT = "silent";
+ field public static final String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+ field public static final int PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int PRIORITY_HIGH = 1; // 0x1
+ field public static final int PRIORITY_LOW = -1; // 0xffffffff
+ field public static final int PRIORITY_MAX = 2; // 0x2
+ field public static final int PRIORITY_MIN = -2; // 0xfffffffe
+ field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+ field public static final int VISIBILITY_PRIVATE = 0; // 0x0
+ field public static final int VISIBILITY_PUBLIC = 1; // 0x1
+ field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
+ }
+
+ public static class NotificationCompat.Action {
+ ctor public NotificationCompat.Action(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ method public android.app.PendingIntent? getActionIntent();
+ method public boolean getAllowGeneratedReplies();
+ method public androidx.core.app.RemoteInput![]? getDataOnlyRemoteInputs();
+ method public android.os.Bundle getExtras();
+ method @Deprecated public int getIcon();
+ method public androidx.core.graphics.drawable.IconCompat? getIconCompat();
+ method public androidx.core.app.RemoteInput![]? getRemoteInputs();
+ method @androidx.core.app.NotificationCompat.Action.SemanticAction public int getSemanticAction();
+ method public boolean getShowsUserInterface();
+ method public CharSequence? getTitle();
+ method public boolean isAuthenticationRequired();
+ method public boolean isContextual();
+ field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
+ field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa
+ field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
+ field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
+ field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
+ field public static final int SEMANTIC_ACTION_MUTE = 6; // 0x6
+ field public static final int SEMANTIC_ACTION_NONE = 0; // 0x0
+ field public static final int SEMANTIC_ACTION_REPLY = 1; // 0x1
+ field public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9; // 0x9
+ field public static final int SEMANTIC_ACTION_THUMBS_UP = 8; // 0x8
+ field public static final int SEMANTIC_ACTION_UNMUTE = 7; // 0x7
+ field public android.app.PendingIntent? actionIntent;
+ field @Deprecated public int icon;
+ field public CharSequence! title;
+ }
+
+ public static final class NotificationCompat.Action.Builder {
+ ctor public NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.Builder addExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Action.Builder addRemoteInput(androidx.core.app.RemoteInput?);
+ method public androidx.core.app.NotificationCompat.Action build();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Extender);
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.NotificationCompat.Action.Builder setAllowGeneratedReplies(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setAuthenticationRequired(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setContextual(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setSemanticAction(@androidx.core.app.NotificationCompat.Action.SemanticAction int);
+ method public androidx.core.app.NotificationCompat.Action.Builder setShowsUserInterface(boolean);
+ }
+
+ public static interface NotificationCompat.Action.Extender {
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_NONE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_REPLY, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_UNREAD, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_DELETE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_UNMUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_UP, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_DOWN, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_CALL}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.Action.SemanticAction {
+ }
+
+ public static final class NotificationCompat.Action.WearableExtender implements androidx.core.app.NotificationCompat.Action.Extender {
+ ctor public NotificationCompat.Action.WearableExtender();
+ ctor public NotificationCompat.Action.WearableExtender(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ method @Deprecated public CharSequence? getCancelLabel();
+ method @Deprecated public CharSequence? getConfirmLabel();
+ method public boolean getHintDisplayActionInline();
+ method public boolean getHintLaunchesActivity();
+ method @Deprecated public CharSequence? getInProgressLabel();
+ method public boolean isAvailableOffline();
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setCancelLabel(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setConfirmLabel(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintDisplayActionInline(boolean);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setInProgressLabel(CharSequence?);
+ }
+
+ public static class NotificationCompat.BigPictureStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigPictureStyle();
+ ctor public NotificationCompat.BigPictureStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.Bitmap?);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.Bitmap?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setBigContentTitle(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle setContentDescription(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setSummaryText(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle showBigPictureWhenCollapsed(boolean);
+ }
+
+ public static class NotificationCompat.BigTextStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigTextStyle();
+ ctor public NotificationCompat.BigTextStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle bigText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setSummaryText(CharSequence?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata {
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? fromPlatform(android.app.Notification.BubbleMetadata?);
+ method public boolean getAutoExpandBubble();
+ method public android.app.PendingIntent? getDeleteIntent();
+ method @Dimension(unit=androidx.annotation.Dimension.DP) public int getDesiredHeight();
+ method @DimenRes public int getDesiredHeightResId();
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public android.app.PendingIntent? getIntent();
+ method public String? getShortcutId();
+ method public boolean isNotificationSuppressed();
+ method public static android.app.Notification.BubbleMetadata? toPlatform(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata.Builder {
+ ctor @Deprecated public NotificationCompat.BubbleMetadata.Builder();
+ ctor @RequiresApi(30) public NotificationCompat.BubbleMetadata.Builder(String);
+ ctor public NotificationCompat.BubbleMetadata.Builder(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata build();
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeight(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setSuppressNotification(boolean);
+ }
+
+ public static class NotificationCompat.Builder {
+ ctor @RequiresApi(19) public NotificationCompat.Builder(android.content.Context, android.app.Notification);
+ ctor public NotificationCompat.Builder(android.content.Context, String);
+ ctor @Deprecated public NotificationCompat.Builder(android.content.Context);
+ method public androidx.core.app.NotificationCompat.Builder addAction(int, CharSequence?, android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder addAction(androidx.core.app.NotificationCompat.Action?);
+ method public androidx.core.app.NotificationCompat.Builder addExtras(android.os.Bundle?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(int, CharSequence?, android.app.PendingIntent?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(androidx.core.app.NotificationCompat.Action?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder addPerson(String?);
+ method public androidx.core.app.NotificationCompat.Builder addPerson(androidx.core.app.Person?);
+ method public android.app.Notification build();
+ method public androidx.core.app.NotificationCompat.Builder clearActions();
+ method public androidx.core.app.NotificationCompat.Builder clearInvisibleActions();
+ method public androidx.core.app.NotificationCompat.Builder clearPeople();
+ method public android.widget.RemoteViews? createBigContentView();
+ method public android.widget.RemoteViews? createContentView();
+ method public android.widget.RemoteViews? createHeadsUpContentView();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Extender);
+ method public android.os.Bundle getExtras();
+ method @Deprecated public android.app.Notification getNotification();
+ method protected static CharSequence? limitCharSequenceLength(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setAllowSystemGeneratedContextualActions(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setAutoCancel(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setBadgeIconType(int);
+ method public androidx.core.app.NotificationCompat.Builder setBubbleMetadata(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ method public androidx.core.app.NotificationCompat.Builder setCategory(String?);
+ method public androidx.core.app.NotificationCompat.Builder setChannelId(String);
+ method @RequiresApi(24) public androidx.core.app.NotificationCompat.Builder setChronometerCountDown(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.Builder setColorized(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setContent(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setContentInfo(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setContentText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomBigContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomHeadsUpContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setDefaults(int);
+ method public androidx.core.app.NotificationCompat.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Builder setForegroundServiceBehavior(int);
+ method public androidx.core.app.NotificationCompat.Builder setFullScreenIntent(android.app.PendingIntent?, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationCompat.Builder setGroupAlertBehavior(int);
+ method public androidx.core.app.NotificationCompat.Builder setGroupSummary(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLargeIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.Builder setLights(@ColorInt int, int, int);
+ method public androidx.core.app.NotificationCompat.Builder setLocalOnly(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setNotificationSilent();
+ method public androidx.core.app.NotificationCompat.Builder setNumber(int);
+ method public androidx.core.app.NotificationCompat.Builder setOngoing(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setOnlyAlertOnce(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPriority(int);
+ method public androidx.core.app.NotificationCompat.Builder setProgress(int, int, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPublicVersion(android.app.Notification?);
+ method public androidx.core.app.NotificationCompat.Builder setRemoteInputHistory(CharSequence![]?);
+ method public androidx.core.app.NotificationCompat.Builder setSettingsText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutId(String?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutInfo(androidx.core.content.pm.ShortcutInfoCompat?);
+ method public androidx.core.app.NotificationCompat.Builder setShowWhen(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setSilent(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.Builder setSmallIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int, int);
+ method public androidx.core.app.NotificationCompat.Builder setSortKey(String?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?, int);
+ method public androidx.core.app.NotificationCompat.Builder setStyle(androidx.core.app.NotificationCompat.Style?);
+ method public androidx.core.app.NotificationCompat.Builder setSubText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?, android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setTimeoutAfter(long);
+ method public androidx.core.app.NotificationCompat.Builder setUsesChronometer(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setVibrate(long[]?);
+ method public androidx.core.app.NotificationCompat.Builder setVisibility(int);
+ method public androidx.core.app.NotificationCompat.Builder setWhen(long);
+ field @Deprecated public java.util.ArrayList<java.lang.String!>! mPeople;
+ }
+
+ public static class NotificationCompat.CallStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.CallStyle();
+ ctor public NotificationCompat.CallStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public static androidx.core.app.NotificationCompat.CallStyle forIncomingCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forOngoingCall(androidx.core.app.Person, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forScreeningCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method public androidx.core.app.NotificationCompat.CallStyle setAnswerButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setDeclineButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setIsVideo(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationText(CharSequence?);
+ field public static final int CALL_TYPE_INCOMING = 1; // 0x1
+ field public static final int CALL_TYPE_ONGOING = 2; // 0x2
+ field public static final int CALL_TYPE_SCREENING = 3; // 0x3
+ field public static final int CALL_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public static final class NotificationCompat.CarExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.CarExtender();
+ ctor public NotificationCompat.CarExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method @ColorInt public int getColor();
+ method public android.graphics.Bitmap? getLargeIcon();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation? getUnreadConversation();
+ method public androidx.core.app.NotificationCompat.CarExtender setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CarExtender setLargeIcon(android.graphics.Bitmap?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender setUnreadConversation(androidx.core.app.NotificationCompat.CarExtender.UnreadConversation?);
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation {
+ method @Deprecated public long getLatestTimestamp();
+ method @Deprecated public String![]? getMessages();
+ method @Deprecated public String? getParticipant();
+ method @Deprecated public String![]? getParticipants();
+ method @Deprecated public android.app.PendingIntent? getReadPendingIntent();
+ method @Deprecated public androidx.core.app.RemoteInput? getRemoteInput();
+ method @Deprecated public android.app.PendingIntent? getReplyPendingIntent();
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation.Builder {
+ ctor @Deprecated public NotificationCompat.CarExtender.UnreadConversation.Builder(String);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder addMessage(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation build();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setLatestTimestamp(long);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReadPendingIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReplyAction(android.app.PendingIntent?, androidx.core.app.RemoteInput?);
+ }
+
+ public static class NotificationCompat.DecoratedCustomViewStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.DecoratedCustomViewStyle();
+ }
+
+ public static interface NotificationCompat.Extender {
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ }
+
+ public static class NotificationCompat.InboxStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.InboxStyle();
+ ctor public NotificationCompat.InboxStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.InboxStyle addLine(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setSummaryText(CharSequence?);
+ }
+
+ public static class NotificationCompat.MessagingStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor @Deprecated public NotificationCompat.MessagingStyle(CharSequence);
+ ctor public NotificationCompat.MessagingStyle(androidx.core.app.Person);
+ method public void addCompatExtras(android.os.Bundle);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addHistoricMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method @Deprecated public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, androidx.core.app.Person?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method public static androidx.core.app.NotificationCompat.MessagingStyle? extractMessagingStyleFromNotification(android.app.Notification);
+ method public CharSequence? getConversationTitle();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getHistoricMessages();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getMessages();
+ method public androidx.core.app.Person getUser();
+ method @Deprecated public CharSequence? getUserDisplayName();
+ method public boolean isGroupConversation();
+ method public androidx.core.app.NotificationCompat.MessagingStyle setConversationTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle setGroupConversation(boolean);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class NotificationCompat.MessagingStyle.Message {
+ ctor public NotificationCompat.MessagingStyle.Message(CharSequence?, long, androidx.core.app.Person?);
+ ctor @Deprecated public NotificationCompat.MessagingStyle.Message(CharSequence?, long, CharSequence?);
+ method public String? getDataMimeType();
+ method public android.net.Uri? getDataUri();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.Person? getPerson();
+ method @Deprecated public CharSequence? getSender();
+ method public CharSequence? getText();
+ method public long getTimestamp();
+ method public androidx.core.app.NotificationCompat.MessagingStyle.Message setData(String?, android.net.Uri?);
+ }
+
+ public abstract static class NotificationCompat.Style {
+ ctor public NotificationCompat.Style();
+ method public android.app.Notification? build();
+ method public void setBuilder(androidx.core.app.NotificationCompat.Builder?);
+ }
+
+ public static final class NotificationCompat.WearableExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.WearableExtender();
+ ctor public NotificationCompat.WearableExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.WearableExtender addAction(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.WearableExtender addActions(java.util.List<androidx.core.app.NotificationCompat.Action!>);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPage(android.app.Notification);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPages(java.util.List<android.app.Notification!>);
+ method public androidx.core.app.NotificationCompat.WearableExtender clearActions();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender clearPages();
+ method public androidx.core.app.NotificationCompat.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method public java.util.List<androidx.core.app.NotificationCompat.Action!> getActions();
+ method @Deprecated public android.graphics.Bitmap? getBackground();
+ method public String? getBridgeTag();
+ method public int getContentAction();
+ method @Deprecated public int getContentIcon();
+ method @Deprecated public int getContentIconGravity();
+ method public boolean getContentIntentAvailableOffline();
+ method @Deprecated public int getCustomContentHeight();
+ method @Deprecated public int getCustomSizePreset();
+ method public String? getDismissalId();
+ method @Deprecated public android.app.PendingIntent? getDisplayIntent();
+ method @Deprecated public int getGravity();
+ method @Deprecated public boolean getHintAmbientBigPicture();
+ method @Deprecated public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
+ method @Deprecated public boolean getHintHideIcon();
+ method @Deprecated public int getHintScreenTimeout();
+ method @Deprecated public boolean getHintShowBackgroundOnly();
+ method @Deprecated public java.util.List<android.app.Notification!> getPages();
+ method public boolean getStartScrollBottom();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setBackground(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setBridgeTag(String?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentAction(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIcon(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIconGravity(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentIntentAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomContentHeight(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomSizePreset(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setDismissalId(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setDisplayIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setGravity(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAmbientBigPicture(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setHintContentIntentLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintHideIcon(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintScreenTimeout(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintShowBackgroundOnly(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setStartScrollBottom(boolean);
+ field @Deprecated public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff
+ field @Deprecated public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0
+ field @Deprecated public static final int SIZE_DEFAULT = 0; // 0x0
+ field @Deprecated public static final int SIZE_FULL_SCREEN = 5; // 0x5
+ field @Deprecated public static final int SIZE_LARGE = 4; // 0x4
+ field @Deprecated public static final int SIZE_MEDIUM = 3; // 0x3
+ field @Deprecated public static final int SIZE_SMALL = 2; // 0x2
+ field @Deprecated public static final int SIZE_XSMALL = 1; // 0x1
+ field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+ }
+
+ public final class NotificationCompatExtras {
+ field public static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras";
+ field public static final String EXTRA_GROUP_KEY = "android.support.groupKey";
+ field public static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary";
+ field public static final String EXTRA_LOCAL_ONLY = "android.support.localOnly";
+ field public static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs";
+ field public static final String EXTRA_SORT_KEY = "android.support.sortKey";
+ }
+
+ public abstract class NotificationCompatSideChannelService extends android.app.Service {
+ ctor public NotificationCompatSideChannelService();
+ method public abstract void cancel(String!, int, String!);
+ method public abstract void cancelAll(String!);
+ method public abstract void notify(String!, int, String!, android.app.Notification!);
+ method public android.os.IBinder! onBind(android.content.Intent!);
+ }
+
+ public final class NotificationManagerCompat {
+ method public boolean areNotificationsEnabled();
+ method public void cancel(int);
+ method public void cancel(String?, int);
+ method public void cancelAll();
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(androidx.core.app.NotificationChannelCompat);
+ method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+ method public void createNotificationChannelGroup(androidx.core.app.NotificationChannelGroupCompat);
+ method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup!>);
+ method public void createNotificationChannelGroupsCompat(java.util.List<androidx.core.app.NotificationChannelGroupCompat!>);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel!>);
+ method public void createNotificationChannelsCompat(java.util.List<androidx.core.app.NotificationChannelCompat!>);
+ method public void deleteNotificationChannel(String);
+ method public void deleteNotificationChannelGroup(String);
+ method public void deleteUnlistedNotificationChannels(java.util.Collection<java.lang.String!>);
+ method public static androidx.core.app.NotificationManagerCompat from(android.content.Context);
+ method public static java.util.Set<java.lang.String!> getEnabledListenerPackages(android.content.Context);
+ method public int getImportance();
+ method public android.app.NotificationChannel? getNotificationChannel(String);
+ method public android.app.NotificationChannel? getNotificationChannel(String, String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String, String);
+ method public android.app.NotificationChannelGroup? getNotificationChannelGroup(String);
+ method public androidx.core.app.NotificationChannelGroupCompat? getNotificationChannelGroupCompat(String);
+ method public java.util.List<android.app.NotificationChannelGroup!> getNotificationChannelGroups();
+ method public java.util.List<androidx.core.app.NotificationChannelGroupCompat!> getNotificationChannelGroupsCompat();
+ method public java.util.List<android.app.NotificationChannel!> getNotificationChannels();
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getNotificationChannelsCompat();
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(int, android.app.Notification);
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(String?, int, android.app.Notification);
+ field public static final String ACTION_BIND_SIDE_CHANNEL = "android.support.BIND_NOTIFICATION_SIDE_CHANNEL";
+ field public static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
+ field public static final int IMPORTANCE_NONE = 0; // 0x0
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
+ }
+
+ public interface OnMultiWindowModeChangedProvider {
+ method public void addOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ method public void removeOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ }
+
+ public interface OnNewIntentProvider {
+ method public void addOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ method public void removeOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ }
+
+ public interface OnPictureInPictureModeChangedProvider {
+ method public void addOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ method public void removeOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ }
+
+ public final class PendingIntentCompat {
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int, boolean);
+ method @RequiresApi(26) public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int, boolean);
+ }
+
+ public class Person {
+ method public static androidx.core.app.Person fromBundle(android.os.Bundle);
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public String? getKey();
+ method public CharSequence? getName();
+ method public String? getUri();
+ method public boolean isBot();
+ method public boolean isImportant();
+ method public androidx.core.app.Person.Builder toBuilder();
+ method public android.os.Bundle toBundle();
+ }
+
+ public static class Person.Builder {
+ ctor public Person.Builder();
+ method public androidx.core.app.Person build();
+ method public androidx.core.app.Person.Builder setBot(boolean);
+ method public androidx.core.app.Person.Builder setIcon(androidx.core.graphics.drawable.IconCompat?);
+ method public androidx.core.app.Person.Builder setImportant(boolean);
+ method public androidx.core.app.Person.Builder setKey(String?);
+ method public androidx.core.app.Person.Builder setName(CharSequence?);
+ method public androidx.core.app.Person.Builder setUri(String?);
+ }
+
+ public final class PictureInPictureModeChangedInfo {
+ ctor public PictureInPictureModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public PictureInPictureModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInPictureInPictureMode();
+ }
+
+ public final class RemoteActionCompat implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public RemoteActionCompat(androidx.core.graphics.drawable.IconCompat, CharSequence, CharSequence, android.app.PendingIntent);
+ ctor public RemoteActionCompat(androidx.core.app.RemoteActionCompat);
+ method @RequiresApi(26) public static androidx.core.app.RemoteActionCompat createFromRemoteAction(android.app.RemoteAction);
+ method public android.app.PendingIntent getActionIntent();
+ method public CharSequence getContentDescription();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
+ method public CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
+ method public void setShouldShowIcon(boolean);
+ method public boolean shouldShowIcon();
+ method @RequiresApi(26) public android.app.RemoteAction toRemoteAction();
+ }
+
+ public final class RemoteInput {
+ method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+ method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
+ method public boolean getAllowFreeFormInput();
+ method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+ method public CharSequence![]? getChoices();
+ method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
+ method public int getEditChoicesBeforeSending();
+ method public android.os.Bundle getExtras();
+ method public CharSequence? getLabel();
+ method public String getResultKey();
+ method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
+ method public static int getResultsSource(android.content.Intent);
+ method public boolean isDataOnly();
+ method public static void setResultsSource(android.content.Intent, int);
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_AUTO = 0; // 0x0
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_DISABLED = 1; // 0x1
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_ENABLED = 2; // 0x2
+ field public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+ field public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+ field public static final int SOURCE_CHOICE = 1; // 0x1
+ field public static final int SOURCE_FREE_FORM_INPUT = 0; // 0x0
+ }
+
+ public static final class RemoteInput.Builder {
+ ctor public RemoteInput.Builder(String);
+ method public androidx.core.app.RemoteInput.Builder addExtras(android.os.Bundle);
+ method public androidx.core.app.RemoteInput build();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.RemoteInput.Builder setAllowDataType(String, boolean);
+ method public androidx.core.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+ method public androidx.core.app.RemoteInput.Builder setChoices(CharSequence![]?);
+ method public androidx.core.app.RemoteInput.Builder setEditChoicesBeforeSending(int);
+ method public androidx.core.app.RemoteInput.Builder setLabel(CharSequence?);
+ }
+
+ public final class ServiceCompat {
+ method public static void stopForeground(android.app.Service, int);
+ field public static final int START_STICKY = 1; // 0x1
+ field public static final int STOP_FOREGROUND_DETACH = 2; // 0x2
+ field public static final int STOP_FOREGROUND_REMOVE = 1; // 0x1
+ }
+
+ public final class ShareCompat {
+ method @Deprecated public static void configureMenuItem(android.view.MenuItem, androidx.core.app.ShareCompat.IntentBuilder);
+ method @Deprecated public static void configureMenuItem(android.view.Menu, @IdRes int, androidx.core.app.ShareCompat.IntentBuilder);
+ method public static android.content.ComponentName? getCallingActivity(android.app.Activity);
+ method public static String? getCallingPackage(android.app.Activity);
+ field public static final String EXTRA_CALLING_ACTIVITY = "androidx.core.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_ACTIVITY_INTEROP = "android.support.v4.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_PACKAGE = "androidx.core.app.EXTRA_CALLING_PACKAGE";
+ field public static final String EXTRA_CALLING_PACKAGE_INTEROP = "android.support.v4.app.EXTRA_CALLING_PACKAGE";
+ }
+
+ public static class ShareCompat.IntentBuilder {
+ ctor public ShareCompat.IntentBuilder(android.content.Context);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addStream(android.net.Uri);
+ method public android.content.Intent createChooserIntent();
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentBuilder from(android.app.Activity);
+ method public android.content.Intent getIntent();
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(@StringRes int);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailBcc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailCc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailTo(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setHtmlText(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setStream(android.net.Uri?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setSubject(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setText(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setType(String?);
+ method public void startChooser();
+ }
+
+ public static class ShareCompat.IntentReader {
+ ctor public ShareCompat.IntentReader(android.app.Activity);
+ ctor public ShareCompat.IntentReader(android.content.Context, android.content.Intent);
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentReader from(android.app.Activity);
+ method public android.content.ComponentName? getCallingActivity();
+ method public android.graphics.drawable.Drawable? getCallingActivityIcon();
+ method public android.graphics.drawable.Drawable? getCallingApplicationIcon();
+ method public CharSequence? getCallingApplicationLabel();
+ method public String? getCallingPackage();
+ method public String![]? getEmailBcc();
+ method public String![]? getEmailCc();
+ method public String![]? getEmailTo();
+ method public String? getHtmlText();
+ method public android.net.Uri? getStream();
+ method public android.net.Uri? getStream(int);
+ method public int getStreamCount();
+ method public String? getSubject();
+ method public CharSequence? getText();
+ method public String? getType();
+ method public boolean isMultipleShare();
+ method public boolean isShareIntent();
+ method public boolean isSingleShare();
+ }
+
+ public abstract class SharedElementCallback {
+ ctor public SharedElementCallback();
+ method public android.os.Parcelable! onCaptureSharedElementSnapshot(android.view.View!, android.graphics.Matrix!, android.graphics.RectF!);
+ method public android.view.View! onCreateSnapshotView(android.content.Context!, android.os.Parcelable!);
+ method public void onMapSharedElements(java.util.List<java.lang.String!>!, java.util.Map<java.lang.String!,android.view.View!>!);
+ method public void onRejectSharedElements(java.util.List<android.view.View!>!);
+ method public void onSharedElementEnd(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementStart(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementsArrived(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, androidx.core.app.SharedElementCallback.OnSharedElementsReadyListener!);
+ }
+
+ public static interface SharedElementCallback.OnSharedElementsReadyListener {
+ method public void onSharedElementsReady();
+ }
+
+ public final class TaskStackBuilder implements java.lang.Iterable<android.content.Intent> {
+ method public androidx.core.app.TaskStackBuilder addNextIntent(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
+ method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
+ method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
+ method public android.content.Intent? editIntentAt(int);
+ method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
+ method @Deprecated public android.content.Intent! getIntent(int);
+ method public int getIntentCount();
+ method public android.content.Intent![] getIntents();
+ method public android.app.PendingIntent? getPendingIntent(int, int);
+ method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
+ method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
+ method public void startActivities();
+ method public void startActivities(android.os.Bundle?);
+ }
+
+ public static interface TaskStackBuilder.SupportParentable {
+ method public android.content.Intent? getSupportParentActivityIntent();
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentProviderCompat {
+ method public static android.content.Context requireContext(android.content.ContentProvider);
+ }
+
+ public final class ContentResolverCompat {
+ method public static android.database.Cursor? query(android.content.ContentResolver, android.net.Uri, String![]?, String?, String![]?, String?, androidx.core.os.CancellationSignal?);
+ }
+
+ public class ContextCompat {
+ ctor protected ContextCompat();
+ method public static int checkSelfPermission(android.content.Context, String);
+ method public static android.content.Context? createDeviceProtectedStorageContext(android.content.Context);
+ method public static String? getAttributionTag(android.content.Context);
+ method public static java.io.File getCodeCacheDir(android.content.Context);
+ method @ColorInt public static int getColor(android.content.Context, @ColorRes int);
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.Context, @ColorRes int);
+ method public static java.io.File? getDataDir(android.content.Context);
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.Context, @DrawableRes int);
+ method public static java.io.File![] getExternalCacheDirs(android.content.Context);
+ method public static java.io.File![] getExternalFilesDirs(android.content.Context, String?);
+ method public static java.util.concurrent.Executor getMainExecutor(android.content.Context);
+ method public static java.io.File? getNoBackupFilesDir(android.content.Context);
+ method public static java.io.File![] getObbDirs(android.content.Context);
+ method public static <T> T? getSystemService(android.content.Context, Class<T!>);
+ method public static String? getSystemServiceName(android.content.Context, Class<?>);
+ method public static boolean isDeviceProtectedStorage(android.content.Context);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![]);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
+ method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
+ method public static void startForegroundService(android.content.Context, android.content.Intent);
+ field public static final int RECEIVER_EXPORTED = 2; // 0x2
+ field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+ field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
+ }
+
+ public class FileProvider extends android.content.ContentProvider {
+ ctor public FileProvider();
+ ctor protected FileProvider(@XmlRes int);
+ method public int delete(android.net.Uri, String?, String![]?);
+ method public String? getType(android.net.Uri);
+ method public static android.net.Uri! getUriForFile(android.content.Context, String, java.io.File);
+ method public static android.net.Uri getUriForFile(android.content.Context, String, java.io.File, String);
+ method public android.net.Uri! insert(android.net.Uri, android.content.ContentValues);
+ method public boolean onCreate();
+ method public android.database.Cursor query(android.net.Uri, String![]?, String?, String![]?, String?);
+ method public int update(android.net.Uri, android.content.ContentValues, String?, String![]?);
+ }
+
+ public final class IntentCompat {
+ method public static android.content.Intent createManageUnusedAppRestrictionsIntent(android.content.Context, String);
+ method public static android.os.Parcelable![]? getParcelableArrayExtra(android.content.Intent, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayListExtra(android.content.Intent, String?, Class<? extends T>);
+ method public static <T> T? getParcelableExtra(android.content.Intent, String?, Class<T!>);
+ method public static android.content.Intent makeMainSelectorActivity(String, String);
+ field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
+ field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
+ field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
+ field public static final String EXTRA_TIME = "android.intent.extra.TIME";
+ }
+
+ public class IntentSanitizer {
+ method public android.content.Intent sanitize(android.content.Intent, androidx.core.util.Consumer<java.lang.String!>);
+ method public android.content.Intent sanitizeByFiltering(android.content.Intent);
+ method public android.content.Intent sanitizeByThrowing(android.content.Intent);
+ }
+
+ public static final class IntentSanitizer.Builder {
+ ctor public IntentSanitizer.Builder();
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowAnyComponent();
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipData(androidx.core.util.Predicate<android.content.ClipData!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataText();
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUri(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(android.content.ComponentName);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(androidx.core.util.Predicate<android.content.ComponentName!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponentWithPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowData(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowDataWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<?>);
+ method public <T> androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<T!>, androidx.core.util.Predicate<T!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, androidx.core.util.Predicate<java.lang.Object!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStream(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStreamUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowFlags(int);
+ method public androidx.core.content.IntentSanitizer.Builder allowHistoryStackFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowIdentifier();
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowReceiverFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowSelector();
+ method public androidx.core.content.IntentSanitizer.Builder allowSourceBounds();
+ method public androidx.core.content.IntentSanitizer.Builder allowType(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowType(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer build();
+ }
+
+ public final class LocusIdCompat {
+ ctor public LocusIdCompat(String);
+ method public String getId();
+ method @RequiresApi(29) public android.content.LocusId toLocusId();
+ method @RequiresApi(29) public static androidx.core.content.LocusIdCompat toLocusIdCompat(android.content.LocusId);
+ }
+
+ public final class MimeTypeFilter {
+ method public static boolean matches(String?, String);
+ method public static String? matches(String?, String![]);
+ method public static String? matches(String![]?, String);
+ method public static String![] matchesMany(String![]?, String);
+ }
+
+ public interface OnConfigurationChangedProvider {
+ method public void addOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ method public void removeOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ }
+
+ public interface OnTrimMemoryProvider {
+ method public void addOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ method public void removeOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ }
+
+ public final class PackageManagerCompat {
+ method public static com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> getUnusedAppRestrictionsStatus(android.content.Context);
+ field public static final String ACTION_PERMISSION_REVOCATION_SETTINGS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
+ }
+
+ public final class PermissionChecker {
+ method public static int checkCallingOrSelfPermission(android.content.Context, String);
+ method public static int checkCallingPermission(android.content.Context, String, String?);
+ method public static int checkPermission(android.content.Context, String, int, int, String?);
+ method public static int checkSelfPermission(android.content.Context, String);
+ field public static final int PERMISSION_DENIED = -1; // 0xffffffff
+ field public static final int PERMISSION_DENIED_APP_OP = -2; // 0xfffffffe
+ field public static final int PERMISSION_GRANTED = 0; // 0x0
+ }
+
+ @Deprecated public final class SharedPreferencesCompat {
+ }
+
+ @Deprecated public static final class SharedPreferencesCompat.EditorCompat {
+ method @Deprecated public void apply(android.content.SharedPreferences.Editor);
+ method @Deprecated public static androidx.core.content.SharedPreferencesCompat.EditorCompat! getInstance();
+ }
+
+ public class UnusedAppRestrictionsBackportCallback {
+ method public void onResult(boolean, boolean) throws android.os.RemoteException;
+ }
+
+ public abstract class UnusedAppRestrictionsBackportService extends android.app.Service {
+ ctor public UnusedAppRestrictionsBackportService();
+ method protected abstract void isPermissionRevocationEnabled(androidx.core.content.UnusedAppRestrictionsBackportCallback);
+ method public android.os.IBinder? onBind(android.content.Intent?);
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS_BACKPORT_CONNECTION = "android.support.unusedapprestrictions.action.CustomUnusedAppRestrictionsBackportService";
+ }
+
+ public final class UnusedAppRestrictionsConstants {
+ field public static final int API_30 = 4; // 0x4
+ field public static final int API_30_BACKPORT = 3; // 0x3
+ field public static final int API_31 = 5; // 0x5
+ field public static final int DISABLED = 2; // 0x2
+ field public static final int ERROR = 0; // 0x0
+ field public static final int FEATURE_NOT_AVAILABLE = 1; // 0x1
+ }
+
+ public class UriMatcherCompat {
+ method public static androidx.core.util.Predicate<android.net.Uri!> asPredicate(android.content.UriMatcher);
+ }
+
+}
+
+package androidx.core.content.pm {
+
+ @Deprecated public final class ActivityInfoCompat {
+ field @Deprecated public static final int CONFIG_UI_MODE = 512; // 0x200
+ }
+
+ public final class PackageInfoCompat {
+ method public static long getLongVersionCode(android.content.pm.PackageInfo);
+ method public static java.util.List<android.content.pm.Signature!> getSignatures(android.content.pm.PackageManager, String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static boolean hasSignatures(android.content.pm.PackageManager, String, @Size(min=1) java.util.Map<byte[]!,java.lang.Integer!>, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
+ }
+
+ public final class PermissionInfoCompat {
+ method public static int getProtection(android.content.pm.PermissionInfo);
+ method public static int getProtectionFlags(android.content.pm.PermissionInfo);
+ }
+
+ public class ShortcutInfoCompat {
+ method public android.content.ComponentName? getActivity();
+ method public java.util.Set<java.lang.String!>? getCategories();
+ method public CharSequence? getDisabledMessage();
+ method public int getDisabledReason();
+ method public int getExcludedFromSurfaces();
+ method public android.os.PersistableBundle? getExtras();
+ method public String getId();
+ method public android.content.Intent getIntent();
+ method public android.content.Intent![] getIntents();
+ method public long getLastChangedTimestamp();
+ method public androidx.core.content.LocusIdCompat? getLocusId();
+ method public CharSequence? getLongLabel();
+ method public String getPackage();
+ method public int getRank();
+ method public CharSequence getShortLabel();
+ method public android.os.UserHandle? getUserHandle();
+ method public boolean hasKeyFieldsOnly();
+ method public boolean isCached();
+ method public boolean isDeclaredInManifest();
+ method public boolean isDynamic();
+ method public boolean isEnabled();
+ method public boolean isExcludedFromSurfaces(int);
+ method public boolean isImmutable();
+ method public boolean isPinned();
+ method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+ field public static final int SURFACE_LAUNCHER = 1; // 0x1
+ }
+
+ public static class ShortcutInfoCompat.Builder {
+ ctor public ShortcutInfoCompat.Builder(android.content.Context, String);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String, String, java.util.List<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat build();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setActivity(android.content.ComponentName);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedFromSurfaces(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
+ method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived(boolean);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPerson(androidx.core.app.Person);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPersons(androidx.core.app.Person![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setRank(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setShortLabel(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setSliceUri(android.net.Uri);
+ }
+
+ public class ShortcutManagerCompat {
+ method public static boolean addDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static android.content.Intent createShortcutResultIntent(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void disableShortcuts(android.content.Context, java.util.List<java.lang.String!>, CharSequence?);
+ method public static void enableShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getDynamicShortcuts(android.content.Context);
+ method public static int getIconMaxHeight(android.content.Context);
+ method public static int getIconMaxWidth(android.content.Context);
+ method public static int getMaxShortcutCountPerActivity(android.content.Context);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getShortcuts(android.content.Context, int);
+ method public static boolean isRateLimitingActive(android.content.Context);
+ method public static boolean isRequestPinShortcutSupported(android.content.Context);
+ method public static boolean pushDynamicShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void removeAllDynamicShortcuts(android.content.Context);
+ method public static void removeDynamicShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void removeLongLivedShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void reportShortcutUsed(android.content.Context, String);
+ method public static boolean requestPinShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat, android.content.IntentSender?);
+ method public static boolean setDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static boolean updateShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ field public static final String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID";
+ field public static final int FLAG_MATCH_CACHED = 8; // 0x8
+ field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
+ field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
+ field public static final int FLAG_MATCH_PINNED = 4; // 0x4
+ }
+
+}
+
+package androidx.core.content.res {
+
+ public final class ConfigurationHelper {
+ method public static int getDensityDpi(android.content.res.Resources);
+ }
+
+ public final class ResourcesCompat {
+ method public static void clearCachesForTheme(android.content.res.Resources.Theme);
+ method public static android.graphics.Typeface? getCachedFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method @ColorInt public static int getColor(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.res.Resources, @DrawableRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawableForDensity(android.content.res.Resources, @DrawableRes int, int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static float getFloat(android.content.res.Resources, @DimenRes int);
+ method public static android.graphics.Typeface? getFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method public static void getFont(android.content.Context, @FontRes int, androidx.core.content.res.ResourcesCompat.FontCallback, android.os.Handler?) throws android.content.res.Resources.NotFoundException;
+ field @AnyRes public static final int ID_NULL = 0; // 0x0
+ }
+
+ public abstract static class ResourcesCompat.FontCallback {
+ ctor public ResourcesCompat.FontCallback();
+ method public abstract void onFontRetrievalFailed(int);
+ method public abstract void onFontRetrieved(android.graphics.Typeface);
+ }
+
+ public static final class ResourcesCompat.ThemeCompat {
+ method public static void rebase(android.content.res.Resources.Theme);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorWindowCompat {
+ method public static android.database.CursorWindow create(String?, long);
+ }
+
+ @Deprecated public final class DatabaseUtilsCompat {
+ method @Deprecated public static String![]! appendSelectionArgs(String![]!, String![]!);
+ method @Deprecated public static String! concatenateWhere(String!, String!);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteCursorCompat {
+ method public static void setFillWindowForwardOnly(android.database.sqlite.SQLiteCursor, boolean);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapCompat {
+ method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, android.graphics.Rect?, boolean);
+ method public static int getAllocationByteCount(android.graphics.Bitmap);
+ method public static boolean hasMipMap(android.graphics.Bitmap);
+ method public static void setHasMipMap(android.graphics.Bitmap, boolean);
+ }
+
+ public class BlendModeColorFilterCompat {
+ method public static android.graphics.ColorFilter? createBlendModeColorFilterCompat(int, androidx.core.graphics.BlendModeCompat);
+ }
+
+ public enum BlendModeCompat {
+ enum_constant public static final androidx.core.graphics.BlendModeCompat CLEAR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_BURN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_DODGE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DARKEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat DIFFERENCE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OVER;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat EXCLUSION;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HARD_LIGHT;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HUE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat LIGHTEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat LUMINOSITY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat MODULATE;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat MULTIPLY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat OVERLAY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat PLUS;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SATURATION;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SCREEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SOFT_LIGHT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OVER;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat XOR;
+ }
+
+ public final class ColorUtils {
+ method @ColorInt public static int HSLToColor(float[]);
+ method @ColorInt public static int LABToColor(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double);
+ method public static void LABToXYZ(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double, double[]);
+ method public static void RGBToHSL(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, float[]);
+ method public static void RGBToLAB(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method public static void RGBToXYZ(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method @ColorInt public static int XYZToColor(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double);
+ method public static void XYZToLAB(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double, double[]);
+ method @ColorInt public static int blendARGB(@ColorInt int, @ColorInt int, @FloatRange(from=0.0, to=1.0) float);
+ method public static void blendHSL(float[], float[], @FloatRange(from=0.0, to=1.0) float, float[]);
+ method public static void blendLAB(double[], double[], @FloatRange(from=0.0, to=1.0) double, double[]);
+ method public static double calculateContrast(@ColorInt int, @ColorInt int);
+ method @FloatRange(from=0.0, to=1.0) public static double calculateLuminance(@ColorInt int);
+ method public static int calculateMinimumAlpha(@ColorInt int, @ColorInt int, float);
+ method public static void colorToHSL(@ColorInt int, float[]);
+ method public static void colorToLAB(@ColorInt int, double[]);
+ method public static void colorToXYZ(@ColorInt int, double[]);
+ method public static int compositeColors(@ColorInt int, @ColorInt int);
+ method @RequiresApi(26) public static android.graphics.Color compositeColors(android.graphics.Color, android.graphics.Color);
+ method public static double distanceEuclidean(double[], double[]);
+ method @ColorInt public static int setAlphaComponent(@ColorInt int, @IntRange(from=0, to=255) int);
+ }
+
+ public final class Insets {
+ method public static androidx.core.graphics.Insets add(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets max(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets min(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets of(int, int, int, int);
+ method public static androidx.core.graphics.Insets of(android.graphics.Rect);
+ method public static androidx.core.graphics.Insets subtract(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method @RequiresApi(api=29) public static androidx.core.graphics.Insets toCompatInsets(android.graphics.Insets);
+ method @RequiresApi(29) public android.graphics.Insets toPlatformInsets();
+ field public static final androidx.core.graphics.Insets NONE;
+ field public final int bottom;
+ field public final int left;
+ field public final int right;
+ field public final int top;
+ }
+
+ public final class PaintCompat {
+ method public static boolean hasGlyph(android.graphics.Paint, String);
+ method public static boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat?);
+ }
+
+ public final class PathSegment {
+ ctor public PathSegment(android.graphics.PointF, float, android.graphics.PointF, float);
+ method public android.graphics.PointF getEnd();
+ method public float getEndFraction();
+ method public android.graphics.PointF getStart();
+ method public float getStartFraction();
+ }
+
+ public final class PathUtils {
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path);
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path, @FloatRange(from=0) float);
+ }
+
+ public class TypefaceCompat {
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, int);
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, @IntRange(from=1, to=1000) int, boolean);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class DrawableCompat {
+ method public static void applyTheme(android.graphics.drawable.Drawable, android.content.res.Resources.Theme);
+ method public static boolean canApplyTheme(android.graphics.drawable.Drawable);
+ method public static void clearColorFilter(android.graphics.drawable.Drawable);
+ method public static int getAlpha(android.graphics.drawable.Drawable);
+ method public static android.graphics.ColorFilter? getColorFilter(android.graphics.drawable.Drawable);
+ method public static int getLayoutDirection(android.graphics.drawable.Drawable);
+ method public static void inflate(android.graphics.drawable.Drawable, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
+ method @Deprecated public static void jumpToCurrentState(android.graphics.drawable.Drawable);
+ method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
+ method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
+ method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
+ method public static boolean setLayoutDirection(android.graphics.drawable.Drawable, int);
+ method public static void setTint(android.graphics.drawable.Drawable, @ColorInt int);
+ method public static void setTintList(android.graphics.drawable.Drawable, android.content.res.ColorStateList?);
+ method public static void setTintMode(android.graphics.drawable.Drawable, android.graphics.PorterDuff.Mode?);
+ method public static <T extends android.graphics.drawable.Drawable> T! unwrap(android.graphics.drawable.Drawable);
+ method public static android.graphics.drawable.Drawable wrap(android.graphics.drawable.Drawable);
+ }
+
+ public class IconCompat implements androidx.versionedparcelable.VersionedParcelable {
+ method public static androidx.core.graphics.drawable.IconCompat? createFromBundle(android.os.Bundle);
+ method @RequiresApi(23) public static androidx.core.graphics.drawable.IconCompat? createFromIcon(android.content.Context, android.graphics.drawable.Icon);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithData(byte[], int, int);
+ method public static androidx.core.graphics.drawable.IconCompat createWithResource(android.content.Context, @DrawableRes int);
+ method @DrawableRes public int getResId();
+ method public String getResPackage();
+ method public int getType();
+ method public android.net.Uri getUri();
+ method public android.graphics.drawable.Drawable? loadDrawable(android.content.Context);
+ method public void onPostParceling();
+ method public void onPreParceling(boolean);
+ method public androidx.core.graphics.drawable.IconCompat setTint(@ColorInt int);
+ method public androidx.core.graphics.drawable.IconCompat setTintList(android.content.res.ColorStateList?);
+ method public androidx.core.graphics.drawable.IconCompat setTintMode(android.graphics.PorterDuff.Mode?);
+ method public android.os.Bundle toBundle();
+ method @Deprecated @RequiresApi(23) public android.graphics.drawable.Icon toIcon();
+ method @RequiresApi(23) public android.graphics.drawable.Icon toIcon(android.content.Context?);
+ field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5
+ field public static final int TYPE_BITMAP = 1; // 0x1
+ field public static final int TYPE_DATA = 3; // 0x3
+ field public static final int TYPE_RESOURCE = 2; // 0x2
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ field public static final int TYPE_URI = 4; // 0x4
+ field public static final int TYPE_URI_ADAPTIVE_BITMAP = 6; // 0x6
+ }
+
+ public abstract class RoundedBitmapDrawable extends android.graphics.drawable.Drawable {
+ method public void draw(android.graphics.Canvas);
+ method public final android.graphics.Bitmap? getBitmap();
+ method public float getCornerRadius();
+ method public int getGravity();
+ method public int getOpacity();
+ method public final android.graphics.Paint getPaint();
+ method public boolean hasAntiAlias();
+ method public boolean hasMipMap();
+ method public boolean isCircular();
+ method public void setAlpha(int);
+ method public void setAntiAlias(boolean);
+ method public void setCircular(boolean);
+ method public void setColorFilter(android.graphics.ColorFilter!);
+ method public void setCornerRadius(float);
+ method public void setDither(boolean);
+ method public void setGravity(int);
+ method public void setMipMap(boolean);
+ method public void setTargetDensity(android.graphics.Canvas);
+ method public void setTargetDensity(android.util.DisplayMetrics);
+ method public void setTargetDensity(int);
+ }
+
+ public final class RoundedBitmapDrawableFactory {
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, android.graphics.Bitmap?);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, String);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, java.io.InputStream);
+ }
+
+}
+
+package androidx.core.hardware.display {
+
+ public final class DisplayManagerCompat {
+ method public android.view.Display? getDisplay(int);
+ method public android.view.Display![] getDisplays();
+ method public android.view.Display![] getDisplays(String?);
+ method public static androidx.core.hardware.display.DisplayManagerCompat getInstance(android.content.Context);
+ field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+ }
+
+}
+
+package androidx.core.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManagerCompat {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public void authenticate(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject?, int, androidx.core.os.CancellationSignal?, androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationCallback, android.os.Handler?);
+ method @Deprecated public static androidx.core.hardware.fingerprint.FingerprintManagerCompat from(android.content.Context);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected();
+ }
+
+ @Deprecated public abstract static class FingerprintManagerCompat.AuthenticationCallback {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationCallback();
+ method @Deprecated public void onAuthenticationError(int, CharSequence!);
+ method @Deprecated public void onAuthenticationFailed();
+ method @Deprecated public void onAuthenticationHelp(int, CharSequence!);
+ method @Deprecated public void onAuthenticationSucceeded(androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationResult!);
+ }
+
+ @Deprecated public static final class FingerprintManagerCompat.AuthenticationResult {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationResult(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject!);
+ method @Deprecated public androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject! getCryptoObject();
+ }
+
+ @Deprecated public static class FingerprintManagerCompat.CryptoObject {
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(java.security.Signature);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Cipher);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Mac);
+ method @Deprecated public javax.crypto.Cipher? getCipher();
+ method @Deprecated public javax.crypto.Mac? getMac();
+ method @Deprecated public java.security.Signature? getSignature();
+ }
+
+}
+
+package androidx.core.location {
+
+ public abstract class GnssStatusCompat {
+ method @FloatRange(from=0, to=360) public abstract float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public abstract float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getCn0DbHz(@IntRange(from=0) int);
+ method public abstract int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public abstract float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public abstract int getSatelliteCount();
+ method @IntRange(from=1, to=200) public abstract int getSvid(@IntRange(from=0) int);
+ method public abstract boolean hasAlmanacData(@IntRange(from=0) int);
+ method public abstract boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public abstract boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public abstract boolean hasEphemerisData(@IntRange(from=0) int);
+ method public abstract boolean usedInFix(@IntRange(from=0) int);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static androidx.core.location.GnssStatusCompat wrap(android.location.GnssStatus);
+ method public static androidx.core.location.GnssStatusCompat wrap(android.location.GpsStatus);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssStatusCompat.Callback {
+ ctor public GnssStatusCompat.Callback();
+ method public void onFirstFix(@IntRange(from=0) int);
+ method public void onSatelliteStatusChanged(androidx.core.location.GnssStatusCompat);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public final class LocationCompat {
+ method public static float getBearingAccuracyDegrees(android.location.Location);
+ method public static long getElapsedRealtimeMillis(android.location.Location);
+ method public static long getElapsedRealtimeNanos(android.location.Location);
+ method @FloatRange(from=0.0) public static float getMslAltitudeAccuracyMeters(android.location.Location);
+ method public static double getMslAltitudeMeters(android.location.Location);
+ method public static float getSpeedAccuracyMetersPerSecond(android.location.Location);
+ method public static float getVerticalAccuracyMeters(android.location.Location);
+ method public static boolean hasBearingAccuracy(android.location.Location);
+ method public static boolean hasMslAltitude(android.location.Location);
+ method public static boolean hasMslAltitudeAccuracy(android.location.Location);
+ method public static boolean hasSpeedAccuracy(android.location.Location);
+ method public static boolean hasVerticalAccuracy(android.location.Location);
+ method public static boolean isMock(android.location.Location);
+ method public static void removeMslAltitude(android.location.Location);
+ method public static void removeMslAltitudeAccuracy(android.location.Location);
+ method public static void setBearingAccuracyDegrees(android.location.Location, float);
+ method public static void setMock(android.location.Location, boolean);
+ method public static void setMslAltitudeAccuracyMeters(android.location.Location, @FloatRange(from=0.0) float);
+ method public static void setMslAltitudeMeters(android.location.Location, double);
+ method public static void setSpeedAccuracyMetersPerSecond(android.location.Location, float);
+ method public static void setVerticalAccuracyMeters(android.location.Location, float);
+ field public static final String EXTRA_BEARING_ACCURACY = "bearingAccuracy";
+ field public static final String EXTRA_IS_MOCK = "mockLocation";
+ field public static final String EXTRA_MSL_ALTITUDE = "androidx.core.location.extra.MSL_ALTITUDE";
+ field public static final String EXTRA_MSL_ALTITUDE_ACCURACY = "androidx.core.location.extra.MSL_ALTITUDE_ACCURACY";
+ field public static final String EXTRA_SPEED_ACCURACY = "speedAccuracy";
+ field public static final String EXTRA_VERTICAL_ACCURACY = "verticalAccuracy";
+ }
+
+ public interface LocationListenerCompat extends android.location.LocationListener {
+ method public default void onStatusChanged(String, int, android.os.Bundle?);
+ }
+
+ public final class LocationManagerCompat {
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void getCurrentLocation(android.location.LocationManager, String, androidx.core.os.CancellationSignal?, java.util.concurrent.Executor, androidx.core.util.Consumer<android.location.Location!>);
+ method public static String? getGnssHardwareModelName(android.location.LocationManager);
+ method public static int getGnssYearOfHardware(android.location.LocationManager);
+ method public static boolean hasProvider(android.location.LocationManager, String);
+ method public static boolean isLocationEnabled(android.location.LocationManager);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback, android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, java.util.concurrent.Executor, androidx.core.location.GnssStatusCompat.Callback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void removeUpdates(android.location.LocationManager, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, java.util.concurrent.Executor, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, androidx.core.location.LocationListenerCompat, android.os.Looper);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static void unregisterGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback);
+ method public static void unregisterGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback);
+ }
+
+ public final class LocationRequestCompat {
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method @RequiresApi(31) public android.location.LocationRequest toLocationRequest();
+ method @RequiresApi(19) public android.location.LocationRequest? toLocationRequest(String);
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequestCompat.Builder {
+ ctor public LocationRequestCompat.Builder(long);
+ ctor public LocationRequestCompat.Builder(androidx.core.location.LocationRequestCompat);
+ method public androidx.core.location.LocationRequestCompat build();
+ method public androidx.core.location.LocationRequestCompat.Builder clearMinUpdateIntervalMillis();
+ method public androidx.core.location.LocationRequestCompat.Builder setDurationMillis(@IntRange(from=1) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setQuality(int);
+ }
+
+}
+
+package androidx.core.math {
+
+ public class MathUtils {
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
+ method public static float clamp(float, float, float);
+ method public static double clamp(double, double, double);
+ method public static int clamp(int, int, int);
+ method public static long clamp(long, long, long);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
+ method public static int toIntExact(long);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class ConnectivityManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static android.net.NetworkInfo? getNetworkInfoFromBroadcast(android.net.ConnectivityManager, android.content.Intent);
+ method public static int getRestrictBackgroundStatus(android.net.ConnectivityManager);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static boolean isActiveNetworkMetered(android.net.ConnectivityManager);
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
+ }
+
+ public final class MailTo {
+ method public String? getBcc();
+ method public String? getBody();
+ method public String? getCc();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getHeaders();
+ method public String? getSubject();
+ method public String? getTo();
+ method public static boolean isMailTo(String?);
+ method public static boolean isMailTo(android.net.Uri?);
+ method public static androidx.core.net.MailTo parse(String) throws androidx.core.net.ParseException;
+ method public static androidx.core.net.MailTo parse(android.net.Uri) throws androidx.core.net.ParseException;
+ field public static final String MAILTO_SCHEME = "mailto:";
+ }
+
+ public class ParseException extends java.lang.RuntimeException {
+ field public final String response;
+ }
+
+ public final class TrafficStatsCompat {
+ method @Deprecated public static void clearThreadStatsTag();
+ method @Deprecated public static int getThreadStatsTag();
+ method @Deprecated public static void incrementOperationCount(int);
+ method @Deprecated public static void incrementOperationCount(int, int);
+ method @Deprecated public static void setThreadStatsTag(int);
+ method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void tagSocket(java.net.Socket!) throws java.net.SocketException;
+ method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void untagSocket(java.net.Socket!) throws java.net.SocketException;
+ }
+
+ public final class UriCompat {
+ method public static String toSafeString(android.net.Uri);
+ }
+
+}
+
+package androidx.core.os {
+
+ public class BuildCompat {
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N) public static boolean isAtLeastN();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N_MR1) public static boolean isAtLeastNMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O) public static boolean isAtLeastO();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O_MR1) public static boolean isAtLeastOMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.P) public static boolean isAtLeastP();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.Q) public static boolean isAtLeastQ();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.R) public static boolean isAtLeastR();
+ method @Deprecated @ChecksSdkIntAtLeast(api=31, codename="S") public static boolean isAtLeastS();
+ method @Deprecated @ChecksSdkIntAtLeast(api=32, codename="Sv2") @androidx.core.os.BuildCompat.PrereleaseSdkCheck public static boolean isAtLeastSv2();
+ method @ChecksSdkIntAtLeast(api=33, codename="Tiramisu") @androidx.core.os.BuildCompat.PrereleaseSdkCheck public static boolean isAtLeastT();
+ method @ChecksSdkIntAtLeast(codename="UpsideDownCake") @androidx.core.os.BuildCompat.PrereleaseSdkCheck public static boolean isAtLeastU();
+ field @ChecksSdkIntAtLeast(extension=android.os.ext.SdkExtensions.AD_SERVICES) public static final int AD_SERVICES_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.R) public static final int R_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.S) public static final int S_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.TIRAMISU) public static final int T_EXTENSION_INT;
+ }
+
+ @RequiresOptIn @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public static @interface BuildCompat.PrereleaseSdkCheck {
+ }
+
+ public final class BundleCompat {
+ method public static <T> T? getParcelable(android.os.Bundle, String?, Class<T!>);
+ method public static android.os.Parcelable![]? getParcelableArray(android.os.Bundle, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayList(android.os.Bundle, String?, Class<? extends T>);
+ method public static <T> android.util.SparseArray<T!>? getSparseParcelableArray(android.os.Bundle, String?, Class<? extends T>);
+ }
+
+ public final class CancellationSignal {
+ ctor public CancellationSignal();
+ method public void cancel();
+ method public Object? getCancellationSignalObject();
+ method public boolean isCanceled();
+ method public void setOnCancelListener(androidx.core.os.CancellationSignal.OnCancelListener?);
+ method public void throwIfCanceled();
+ }
+
+ public static interface CancellationSignal.OnCancelListener {
+ method public void onCancel();
+ }
+
+ public final class ConfigurationCompat {
+ method public static androidx.core.os.LocaleListCompat getLocales(android.content.res.Configuration);
+ }
+
+ public final class EnvironmentCompat {
+ method public static String getStorageState(java.io.File);
+ field public static final String MEDIA_UNKNOWN = "unknown";
+ }
+
+ public final class ExecutorCompat {
+ method public static java.util.concurrent.Executor create(android.os.Handler);
+ }
+
+ public final class HandlerCompat {
+ method public static android.os.Handler createAsync(android.os.Looper);
+ method public static android.os.Handler createAsync(android.os.Looper, android.os.Handler.Callback);
+ method @RequiresApi(16) public static boolean hasCallbacks(android.os.Handler, Runnable);
+ method public static boolean postDelayed(android.os.Handler, Runnable, Object?, long);
+ }
+
+ public final class LocaleListCompat {
+ method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
+ method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
+ method public java.util.Locale? get(int);
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
+ method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
+ method public java.util.Locale? getFirstMatch(String![]);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
+ method public boolean isEmpty();
+ method @RequiresApi(21) public static boolean matchesLanguageAndScript(java.util.Locale, java.util.Locale);
+ method @IntRange(from=0) public int size();
+ method public String toLanguageTags();
+ method public Object? unwrap();
+ method @Deprecated @RequiresApi(24) public static androidx.core.os.LocaleListCompat! wrap(Object!);
+ method @RequiresApi(24) public static androidx.core.os.LocaleListCompat wrap(android.os.LocaleList);
+ }
+
+ public final class MessageCompat {
+ method public static boolean isAsynchronous(android.os.Message);
+ method public static void setAsynchronous(android.os.Message, boolean);
+ }
+
+ public class OperationCanceledException extends java.lang.RuntimeException {
+ ctor public OperationCanceledException();
+ ctor public OperationCanceledException(String?);
+ }
+
+ public final class ParcelCompat {
+ method public static <T> Object![]? readArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> java.util.ArrayList<T!>? readArrayList(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static boolean readBoolean(android.os.Parcel);
+ method public static <K, V> java.util.HashMap<K!,V!>? readHashMap(android.os.Parcel, ClassLoader?, Class<? extends K>, Class<? extends V>);
+ method public static <T> void readList(android.os.Parcel, java.util.List<? super T>, ClassLoader?, Class<T!>);
+ method public static <K, V> void readMap(android.os.Parcel, java.util.Map<? super K,? super V>, ClassLoader?, Class<K!>, Class<V!>);
+ method public static <T extends android.os.Parcelable> T? readParcelable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @Deprecated public static <T> T![]? readParcelableArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.os.Parcelable![]? readParcelableArrayTyped(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(30) public static <T> android.os.Parcelable.Creator<T!>? readParcelableCreator(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(api=android.os.Build.VERSION_CODES.Q) public static <T> java.util.List<T!> readParcelableList(android.os.Parcel, java.util.List<T!>, ClassLoader?, Class<T!>);
+ method public static <T extends java.io.Serializable> T? readSerializable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.util.SparseArray<T!>? readSparseArray(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static void writeBoolean(android.os.Parcel, boolean);
+ }
+
+ @Deprecated public final class ParcelableCompat {
+ method @Deprecated public static <T> android.os.Parcelable.Creator<T!>! newCreator(androidx.core.os.ParcelableCompatCreatorCallbacks<T!>!);
+ }
+
+ @Deprecated public interface ParcelableCompatCreatorCallbacks<T> {
+ method @Deprecated public T! createFromParcel(android.os.Parcel!, ClassLoader!);
+ method @Deprecated public T![]! newArray(int);
+ }
+
+ public final class ProcessCompat {
+ method public static boolean isApplicationUid(int);
+ }
+
+ @Deprecated public final class TraceCompat {
+ method @Deprecated public static void beginAsyncSection(String, int);
+ method @Deprecated public static void beginSection(String);
+ method @Deprecated public static void endAsyncSection(String, int);
+ method @Deprecated public static void endSection();
+ method @Deprecated public static boolean isEnabled();
+ method @Deprecated public static void setCounter(String, int);
+ }
+
+ @RequiresApi(17) public class UserHandleCompat {
+ method public static android.os.UserHandle getUserHandleForUid(int);
+ }
+
+ public class UserManagerCompat {
+ method public static boolean isUserUnlocked(android.content.Context);
+ }
+
+}
+
+package androidx.core.provider {
+
+ public final class DocumentsContractCompat {
+ method public static android.net.Uri? buildChildDocumentsUri(String, String?);
+ method public static android.net.Uri? buildChildDocumentsUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildDocumentUri(String, String);
+ method public static android.net.Uri? buildDocumentUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildTreeDocumentUri(String, String);
+ method public static android.net.Uri? createDocument(android.content.ContentResolver, android.net.Uri, String, String) throws java.io.FileNotFoundException;
+ method public static String? getDocumentId(android.net.Uri);
+ method public static String? getTreeDocumentId(android.net.Uri);
+ method public static boolean isDocumentUri(android.content.Context, android.net.Uri?);
+ method public static boolean isTreeUri(android.net.Uri);
+ method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+ method public static android.net.Uri? renameDocument(android.content.ContentResolver, android.net.Uri, String) throws java.io.FileNotFoundException;
+ }
+
+ public static final class DocumentsContractCompat.DocumentCompat {
+ field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
+ }
+
+ public final class FontRequest {
+ ctor public FontRequest(String, String, String, java.util.List<java.util.List<byte[]!>!>);
+ ctor public FontRequest(String, String, String, @ArrayRes int);
+ method public java.util.List<java.util.List<byte[]!>!>? getCertificates();
+ method @ArrayRes public int getCertificatesArrayResId();
+ method public String getProviderAuthority();
+ method public String getProviderPackage();
+ method public String getQuery();
+ }
+
+ public class FontsContractCompat {
+ method public static android.graphics.Typeface? buildTypeface(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![]);
+ method public static androidx.core.provider.FontsContractCompat.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, androidx.core.provider.FontRequest, androidx.core.provider.FontsContractCompat.FontRequestCallback, android.os.Handler);
+ }
+
+ public static final class FontsContractCompat.Columns implements android.provider.BaseColumns {
+ ctor public FontsContractCompat.Columns();
+ field public static final String FILE_ID = "file_id";
+ field public static final String ITALIC = "font_italic";
+ field public static final String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
+ field public static final String TTC_INDEX = "font_ttc_index";
+ field public static final String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final String WEIGHT = "font_weight";
+ }
+
+ public static class FontsContractCompat.FontFamilyResult {
+ method public androidx.core.provider.FontsContractCompat.FontInfo![]! getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContractCompat.FontInfo {
+ method public int getResultCode();
+ method @IntRange(from=0) public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method @IntRange(from=1, to=1000) public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContractCompat.FontRequestCallback {
+ ctor public FontsContractCompat.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface!);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_SECURITY_VIOLATION = -4; // 0xfffffffc
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
+}
+
+package androidx.core.telephony {
+
+ @RequiresApi(22) public class SubscriptionManagerCompat {
+ method public static int getSlotIndex(int);
+ }
+
+ public class TelephonyManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static String? getImei(android.telephony.TelephonyManager);
+ method public static int getSubscriptionId(android.telephony.TelephonyManager);
+ }
+
+}
+
+package androidx.core.telephony.mbms {
+
+ public final class MbmsHelper {
+ method public static CharSequence? getBestNameForService(android.content.Context, android.telephony.mbms.ServiceInfo);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class BidiFormatter {
+ method public static androidx.core.text.BidiFormatter! getInstance();
+ method public static androidx.core.text.BidiFormatter! getInstance(boolean);
+ method public static androidx.core.text.BidiFormatter! getInstance(java.util.Locale!);
+ method public boolean getStereoReset();
+ method public boolean isRtl(String!);
+ method public boolean isRtl(CharSequence!);
+ method public boolean isRtlContext();
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public String! unicodeWrap(String!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, boolean);
+ method public String! unicodeWrap(String!);
+ method public CharSequence! unicodeWrap(CharSequence!);
+ }
+
+ public static final class BidiFormatter.Builder {
+ ctor public BidiFormatter.Builder();
+ ctor public BidiFormatter.Builder(boolean);
+ ctor public BidiFormatter.Builder(java.util.Locale!);
+ method public androidx.core.text.BidiFormatter! build();
+ method public androidx.core.text.BidiFormatter.Builder! setTextDirectionHeuristic(androidx.core.text.TextDirectionHeuristicCompat!);
+ method public androidx.core.text.BidiFormatter.Builder! stereoReset(boolean);
+ }
+
+ public final class HtmlCompat {
+ method public static android.text.Spanned fromHtml(String, int);
+ method public static android.text.Spanned fromHtml(String, int, android.text.Html.ImageGetter?, android.text.Html.TagHandler?);
+ method public static String toHtml(android.text.Spanned, int);
+ field public static final int FROM_HTML_MODE_COMPACT = 63; // 0x3f
+ field public static final int FROM_HTML_MODE_LEGACY = 0; // 0x0
+ field public static final int FROM_HTML_OPTION_USE_CSS_COLORS = 256; // 0x100
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE = 32; // 0x20
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_DIV = 16; // 0x10
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_HEADING = 2; // 0x2
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST = 8; // 0x8
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM = 4; // 0x4
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH = 1; // 0x1
+ field public static final int TO_HTML_PARAGRAPH_LINES_CONSECUTIVE = 0; // 0x0
+ field public static final int TO_HTML_PARAGRAPH_LINES_INDIVIDUAL = 1; // 0x1
+ }
+
+ public final class ICUCompat {
+ method public static String? maximizeAndGetScript(java.util.Locale);
+ }
+
+ public class PrecomputedTextCompat implements android.text.Spannable {
+ method public char charAt(int);
+ method public static androidx.core.text.PrecomputedTextCompat! create(CharSequence, androidx.core.text.PrecomputedTextCompat.Params);
+ method @IntRange(from=0) public int getParagraphCount();
+ method @IntRange(from=0) public int getParagraphEnd(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getParagraphStart(@IntRange(from=0) int);
+ method public androidx.core.text.PrecomputedTextCompat.Params getParams();
+ method public int getSpanEnd(Object!);
+ method public int getSpanFlags(Object!);
+ method public int getSpanStart(Object!);
+ method public <T> T![]! getSpans(int, int, Class<T!>!);
+ method @UiThread public static java.util.concurrent.Future<androidx.core.text.PrecomputedTextCompat!>! getTextFuture(CharSequence, androidx.core.text.PrecomputedTextCompat.Params, java.util.concurrent.Executor?);
+ method public int length();
+ method public int nextSpanTransition(int, int, Class!);
+ method public void removeSpan(Object!);
+ method public void setSpan(Object!, int, int, int);
+ method public CharSequence! subSequence(int, int);
+ }
+
+ public static final class PrecomputedTextCompat.Params {
+ ctor @RequiresApi(28) public PrecomputedTextCompat.Params(android.text.PrecomputedText.Params);
+ method @RequiresApi(23) public int getBreakStrategy();
+ method @RequiresApi(23) public int getHyphenationFrequency();
+ method @RequiresApi(18) public android.text.TextDirectionHeuristic? getTextDirection();
+ method public android.text.TextPaint getTextPaint();
+ }
+
+ public static class PrecomputedTextCompat.Params.Builder {
+ ctor public PrecomputedTextCompat.Params.Builder(android.text.TextPaint);
+ method public androidx.core.text.PrecomputedTextCompat.Params build();
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setBreakStrategy(int);
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setHyphenationFrequency(int);
+ method @RequiresApi(18) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setTextDirection(android.text.TextDirectionHeuristic);
+ }
+
+ public interface TextDirectionHeuristicCompat {
+ method public boolean isRtl(char[]!, int, int);
+ method public boolean isRtl(CharSequence!, int, int);
+ }
+
+ public final class TextDirectionHeuristicsCompat {
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! ANYRTL_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_RTL;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LOCALE;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! RTL;
+ }
+
+ public final class TextUtilsCompat {
+ method public static int getLayoutDirectionFromLocale(java.util.Locale?);
+ method public static String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.text.util {
+
+ public final class LinkifyCompat {
+ method public static boolean addLinks(android.text.Spannable, int);
+ method public static boolean addLinks(android.widget.TextView, int);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ }
+
+}
+
+package androidx.core.util {
+
+ public class AtomicFile {
+ ctor public AtomicFile(java.io.File);
+ method public void delete();
+ method public void failWrite(java.io.FileOutputStream?);
+ method public void finishWrite(java.io.FileOutputStream?);
+ method public java.io.File getBaseFile();
+ method public java.io.FileInputStream openRead() throws java.io.FileNotFoundException;
+ method public byte[] readFully() throws java.io.IOException;
+ method public java.io.FileOutputStream startWrite() throws java.io.IOException;
+ }
+
+ public interface Consumer<T> {
+ method public void accept(T!);
+ }
+
+ public class ObjectsCompat {
+ method public static boolean equals(Object?, Object?);
+ method public static int hash(java.lang.Object!...);
+ method public static int hashCode(Object?);
+ method public static <T> T requireNonNull(T?);
+ method public static <T> T requireNonNull(T?, String);
+ method public static String? toString(Object?, String?);
+ }
+
+ public class Pair<F, S> {
+ ctor public Pair(F!, S!);
+ method public static <A, B> androidx.core.util.Pair<A!,B!> create(A!, B!);
+ field public final F! first;
+ field public final S! second;
+ }
+
+ public final class PatternsCompat {
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
+ }
+
+ public final class Pools {
+ }
+
+ public static interface Pools.Pool<T> {
+ method public T? acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SimplePool<T> implements androidx.core.util.Pools.Pool<T> {
+ ctor public Pools.SimplePool(int);
+ method public T! acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SynchronizedPool<T> extends androidx.core.util.Pools.SimplePool<T> {
+ ctor public Pools.SynchronizedPool(int);
+ }
+
+ public interface Predicate<T> {
+ method public default androidx.core.util.Predicate<T!>! and(androidx.core.util.Predicate<? super T>!);
+ method public static <T> androidx.core.util.Predicate<T!>! isEqual(Object!);
+ method public default androidx.core.util.Predicate<T!>! negate();
+ method public static <T> androidx.core.util.Predicate<T!>! not(androidx.core.util.Predicate<? super T>!);
+ method public default androidx.core.util.Predicate<T!>! or(androidx.core.util.Predicate<? super T>!);
+ method public boolean test(T!);
+ }
+
+ public final class SizeFCompat {
+ ctor public SizeFCompat(float, float);
+ method public float getHeight();
+ method public float getWidth();
+ method @RequiresApi(21) public android.util.SizeF toSizeF();
+ method @RequiresApi(21) public static androidx.core.util.SizeFCompat toSizeFCompat(android.util.SizeF);
+ }
+
+ public interface Supplier<T> {
+ method public T! get();
+ }
+
+}
+
+package androidx.core.view {
+
+ public class AccessibilityDelegateCompat {
+ ctor public AccessibilityDelegateCompat();
+ method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public void sendAccessibilityEvent(android.view.View, int);
+ method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
+ }
+
+ public abstract class ActionProvider {
+ ctor public ActionProvider(android.content.Context);
+ method public android.content.Context getContext();
+ method public boolean hasSubMenu();
+ method public boolean isVisible();
+ method public abstract android.view.View onCreateActionView();
+ method public android.view.View onCreateActionView(android.view.MenuItem);
+ method public boolean onPerformDefaultAction();
+ method public void onPrepareSubMenu(android.view.SubMenu);
+ method public boolean overridesItemVisibility();
+ method public void refreshVisibility();
+ method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
+ }
+
+ public static interface ActionProvider.VisibilityListener {
+ method public void onActionProviderVisibilityChanged(boolean);
+ }
+
+ public final class ContentInfoCompat {
+ method public android.content.ClipData getClip();
+ method public android.os.Bundle? getExtras();
+ method public int getFlags();
+ method public android.net.Uri? getLinkUri();
+ method public int getSource();
+ method public android.util.Pair<androidx.core.view.ContentInfoCompat!,androidx.core.view.ContentInfoCompat!> partition(androidx.core.util.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public static android.util.Pair<android.view.ContentInfo!,android.view.ContentInfo!> partition(android.view.ContentInfo, java.util.function.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public android.view.ContentInfo toContentInfo();
+ method @RequiresApi(31) public static androidx.core.view.ContentInfoCompat toContentInfoCompat(android.view.ContentInfo);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_APP = 0; // 0x0
+ field public static final int SOURCE_AUTOFILL = 4; // 0x4
+ field public static final int SOURCE_CLIPBOARD = 1; // 0x1
+ field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3
+ field public static final int SOURCE_INPUT_METHOD = 2; // 0x2
+ field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5
+ }
+
+ public static final class ContentInfoCompat.Builder {
+ ctor public ContentInfoCompat.Builder(androidx.core.view.ContentInfoCompat);
+ ctor public ContentInfoCompat.Builder(android.content.ClipData, int);
+ method public androidx.core.view.ContentInfoCompat build();
+ method public androidx.core.view.ContentInfoCompat.Builder setClip(android.content.ClipData);
+ method public androidx.core.view.ContentInfoCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.view.ContentInfoCompat.Builder setFlags(int);
+ method public androidx.core.view.ContentInfoCompat.Builder setLinkUri(android.net.Uri?);
+ method public androidx.core.view.ContentInfoCompat.Builder setSource(int);
+ }
+
+ public final class DisplayCompat {
+ method public static androidx.core.view.DisplayCompat.ModeCompat getMode(android.content.Context, android.view.Display);
+ method public static androidx.core.view.DisplayCompat.ModeCompat![] getSupportedModes(android.content.Context, android.view.Display);
+ }
+
+ public static final class DisplayCompat.ModeCompat {
+ method public int getPhysicalHeight();
+ method public int getPhysicalWidth();
+ method @Deprecated public boolean isNative();
+ method @RequiresApi(android.os.Build.VERSION_CODES.M) public android.view.Display.Mode? toMode();
+ }
+
+ public final class DisplayCutoutCompat {
+ ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
+ ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
+ method public java.util.List<android.graphics.Rect!> getBoundingRects();
+ method public int getSafeInsetBottom();
+ method public int getSafeInsetLeft();
+ method public int getSafeInsetRight();
+ method public int getSafeInsetTop();
+ method public androidx.core.graphics.Insets getWaterfallInsets();
+ }
+
+ public final class DragAndDropPermissionsCompat {
+ method public void release();
+ }
+
+ public class DragStartHelper {
+ ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
+ method public void attach();
+ method public void detach();
+ method public void getTouchPosition(android.graphics.Point);
+ method public boolean onLongClick(android.view.View);
+ method public boolean onTouch(android.view.View, android.view.MotionEvent);
+ }
+
+ public static interface DragStartHelper.OnDragStartListener {
+ method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
+ }
+
+ public final class GestureDetectorCompat {
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener);
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener, android.os.Handler?);
+ method public boolean isLongpressEnabled();
+ method public boolean onTouchEvent(android.view.MotionEvent);
+ method public void setIsLongpressEnabled(boolean);
+ method public void setOnDoubleTapListener(android.view.GestureDetector.OnDoubleTapListener?);
+ }
+
+ public final class GravityCompat {
+ method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
+ method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static int getAbsoluteGravity(int, int);
+ field public static final int END = 8388613; // 0x800005
+ field public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = 8388615; // 0x800007
+ field public static final int RELATIVE_LAYOUT_DIRECTION = 8388608; // 0x800000
+ field public static final int START = 8388611; // 0x800003
+ }
+
+ public final class InputDeviceCompat {
+ field public static final int SOURCE_ANY = -256; // 0xffffff00
+ field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
+ field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
+ field public static final int SOURCE_CLASS_MASK = 255; // 0xff
+ field public static final int SOURCE_CLASS_NONE = 0; // 0x0
+ field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
+ field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
+ field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
+ field public static final int SOURCE_DPAD = 513; // 0x201
+ field public static final int SOURCE_GAMEPAD = 1025; // 0x401
+ field public static final int SOURCE_HDMI = 33554433; // 0x2000001
+ field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
+ field public static final int SOURCE_KEYBOARD = 257; // 0x101
+ field public static final int SOURCE_MOUSE = 8194; // 0x2002
+ field public static final int SOURCE_ROTARY_ENCODER = 4194304; // 0x400000
+ field public static final int SOURCE_STYLUS = 16386; // 0x4002
+ field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
+ field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
+ field public static final int SOURCE_TOUCH_NAVIGATION = 2097152; // 0x200000
+ field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
+ field public static final int SOURCE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class LayoutInflaterCompat {
+ method @Deprecated public static androidx.core.view.LayoutInflaterFactory! getFactory(android.view.LayoutInflater!);
+ method @Deprecated public static void setFactory(android.view.LayoutInflater, androidx.core.view.LayoutInflaterFactory);
+ method public static void setFactory2(android.view.LayoutInflater, android.view.LayoutInflater.Factory2);
+ }
+
+ @Deprecated public interface LayoutInflaterFactory {
+ method @Deprecated public android.view.View! onCreateView(android.view.View!, String!, android.content.Context!, android.util.AttributeSet!);
+ }
+
+ public final class MarginLayoutParamsCompat {
+ method public static int getLayoutDirection(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginEnd(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginStart(android.view.ViewGroup.MarginLayoutParams);
+ method public static boolean isMarginRelative(android.view.ViewGroup.MarginLayoutParams);
+ method public static void resolveLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginEnd(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginStart(android.view.ViewGroup.MarginLayoutParams, int);
+ }
+
+ public final class MenuCompat {
+ method public static void setGroupDividerEnabled(android.view.Menu, boolean);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ }
+
+ public interface MenuHost {
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void invalidateMenu();
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public class MenuHostHelper {
+ ctor public MenuHostHelper(Runnable);
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public void onPrepareMenu(android.view.Menu);
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public final class MenuItemCompat {
+ method @Deprecated public static boolean collapseActionView(android.view.MenuItem!);
+ method @Deprecated public static boolean expandActionView(android.view.MenuItem!);
+ method public static androidx.core.view.ActionProvider? getActionProvider(android.view.MenuItem);
+ method @Deprecated public static android.view.View! getActionView(android.view.MenuItem!);
+ method public static int getAlphabeticModifiers(android.view.MenuItem);
+ method public static CharSequence? getContentDescription(android.view.MenuItem);
+ method public static android.content.res.ColorStateList? getIconTintList(android.view.MenuItem);
+ method public static android.graphics.PorterDuff.Mode? getIconTintMode(android.view.MenuItem);
+ method public static int getNumericModifiers(android.view.MenuItem);
+ method public static CharSequence? getTooltipText(android.view.MenuItem);
+ method @Deprecated public static boolean isActionViewExpanded(android.view.MenuItem!);
+ method public static android.view.MenuItem? setActionProvider(android.view.MenuItem, androidx.core.view.ActionProvider?);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, android.view.View!);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, int);
+ method public static void setAlphabeticShortcut(android.view.MenuItem, char, int);
+ method public static void setContentDescription(android.view.MenuItem, CharSequence?);
+ method public static void setIconTintList(android.view.MenuItem, android.content.res.ColorStateList?);
+ method public static void setIconTintMode(android.view.MenuItem, android.graphics.PorterDuff.Mode?);
+ method public static void setNumericShortcut(android.view.MenuItem, char, int);
+ method @Deprecated public static android.view.MenuItem! setOnActionExpandListener(android.view.MenuItem!, androidx.core.view.MenuItemCompat.OnActionExpandListener!);
+ method public static void setShortcut(android.view.MenuItem, char, char, int, int);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ method public static void setTooltipText(android.view.MenuItem, CharSequence?);
+ field @Deprecated public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+ field @Deprecated public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
+ field @Deprecated public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
+ field @Deprecated public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
+ field @Deprecated public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
+ }
+
+ @Deprecated public static interface MenuItemCompat.OnActionExpandListener {
+ method @Deprecated public boolean onMenuItemActionCollapse(android.view.MenuItem!);
+ method @Deprecated public boolean onMenuItemActionExpand(android.view.MenuItem!);
+ }
+
+ public interface MenuProvider {
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public default void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public default void onPrepareMenu(android.view.Menu);
+ }
+
+ public final class MotionEventCompat {
+ method @Deprecated public static int findPointerIndex(android.view.MotionEvent!, int);
+ method @Deprecated public static int getActionIndex(android.view.MotionEvent!);
+ method @Deprecated public static int getActionMasked(android.view.MotionEvent!);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int, int);
+ method @Deprecated public static int getButtonState(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerCount(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerId(android.view.MotionEvent!, int);
+ method @Deprecated public static int getSource(android.view.MotionEvent!);
+ method @Deprecated public static float getX(android.view.MotionEvent!, int);
+ method @Deprecated public static float getY(android.view.MotionEvent!, int);
+ method public static boolean isFromSource(android.view.MotionEvent, int);
+ field @Deprecated public static final int ACTION_HOVER_ENTER = 9; // 0x9
+ field @Deprecated public static final int ACTION_HOVER_EXIT = 10; // 0xa
+ field @Deprecated public static final int ACTION_HOVER_MOVE = 7; // 0x7
+ field @Deprecated public static final int ACTION_MASK = 255; // 0xff
+ field @Deprecated public static final int ACTION_POINTER_DOWN = 5; // 0x5
+ field @Deprecated public static final int ACTION_POINTER_INDEX_MASK = 65280; // 0xff00
+ field @Deprecated public static final int ACTION_POINTER_INDEX_SHIFT = 8; // 0x8
+ field @Deprecated public static final int ACTION_POINTER_UP = 6; // 0x6
+ field @Deprecated public static final int ACTION_SCROLL = 8; // 0x8
+ field @Deprecated public static final int AXIS_BRAKE = 23; // 0x17
+ field @Deprecated public static final int AXIS_DISTANCE = 24; // 0x18
+ field @Deprecated public static final int AXIS_GAS = 22; // 0x16
+ field @Deprecated public static final int AXIS_GENERIC_1 = 32; // 0x20
+ field @Deprecated public static final int AXIS_GENERIC_10 = 41; // 0x29
+ field @Deprecated public static final int AXIS_GENERIC_11 = 42; // 0x2a
+ field @Deprecated public static final int AXIS_GENERIC_12 = 43; // 0x2b
+ field @Deprecated public static final int AXIS_GENERIC_13 = 44; // 0x2c
+ field @Deprecated public static final int AXIS_GENERIC_14 = 45; // 0x2d
+ field @Deprecated public static final int AXIS_GENERIC_15 = 46; // 0x2e
+ field @Deprecated public static final int AXIS_GENERIC_16 = 47; // 0x2f
+ field @Deprecated public static final int AXIS_GENERIC_2 = 33; // 0x21
+ field @Deprecated public static final int AXIS_GENERIC_3 = 34; // 0x22
+ field @Deprecated public static final int AXIS_GENERIC_4 = 35; // 0x23
+ field @Deprecated public static final int AXIS_GENERIC_5 = 36; // 0x24
+ field @Deprecated public static final int AXIS_GENERIC_6 = 37; // 0x25
+ field @Deprecated public static final int AXIS_GENERIC_7 = 38; // 0x26
+ field @Deprecated public static final int AXIS_GENERIC_8 = 39; // 0x27
+ field @Deprecated public static final int AXIS_GENERIC_9 = 40; // 0x28
+ field @Deprecated public static final int AXIS_HAT_X = 15; // 0xf
+ field @Deprecated public static final int AXIS_HAT_Y = 16; // 0x10
+ field @Deprecated public static final int AXIS_HSCROLL = 10; // 0xa
+ field @Deprecated public static final int AXIS_LTRIGGER = 17; // 0x11
+ field @Deprecated public static final int AXIS_ORIENTATION = 8; // 0x8
+ field @Deprecated public static final int AXIS_PRESSURE = 2; // 0x2
+ field public static final int AXIS_RELATIVE_X = 27; // 0x1b
+ field public static final int AXIS_RELATIVE_Y = 28; // 0x1c
+ field @Deprecated public static final int AXIS_RTRIGGER = 18; // 0x12
+ field @Deprecated public static final int AXIS_RUDDER = 20; // 0x14
+ field @Deprecated public static final int AXIS_RX = 12; // 0xc
+ field @Deprecated public static final int AXIS_RY = 13; // 0xd
+ field @Deprecated public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
+ field @Deprecated public static final int AXIS_SIZE = 3; // 0x3
+ field @Deprecated public static final int AXIS_THROTTLE = 19; // 0x13
+ field @Deprecated public static final int AXIS_TILT = 25; // 0x19
+ field @Deprecated public static final int AXIS_TOOL_MAJOR = 6; // 0x6
+ field @Deprecated public static final int AXIS_TOOL_MINOR = 7; // 0x7
+ field @Deprecated public static final int AXIS_TOUCH_MAJOR = 4; // 0x4
+ field @Deprecated public static final int AXIS_TOUCH_MINOR = 5; // 0x5
+ field @Deprecated public static final int AXIS_VSCROLL = 9; // 0x9
+ field @Deprecated public static final int AXIS_WHEEL = 21; // 0x15
+ field @Deprecated public static final int AXIS_X = 0; // 0x0
+ field @Deprecated public static final int AXIS_Y = 1; // 0x1
+ field @Deprecated public static final int AXIS_Z = 11; // 0xb
+ field @Deprecated public static final int BUTTON_PRIMARY = 1; // 0x1
+ }
+
+ public interface NestedScrollingChild {
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean isNestedScrollingEnabled();
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(int);
+ method public void stopNestedScroll();
+ }
+
+ public interface NestedScrollingChild2 extends androidx.core.view.NestedScrollingChild {
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll(int);
+ }
+
+ public interface NestedScrollingChild3 extends androidx.core.view.NestedScrollingChild2 {
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]);
+ }
+
+ public class NestedScrollingChildHelper {
+ ctor public NestedScrollingChildHelper(android.view.View);
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean isNestedScrollingEnabled();
+ method public void onDetachedFromWindow();
+ method public void onStopNestedScroll(android.view.View);
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll();
+ method public void stopNestedScroll(int);
+ }
+
+ public interface NestedScrollingParent {
+ method public int getNestedScrollAxes();
+ method public boolean onNestedFling(android.view.View, float, float, boolean);
+ method public boolean onNestedPreFling(android.view.View, float, float);
+ method public void onNestedPreScroll(android.view.View, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
+ method public void onStopNestedScroll(android.view.View);
+ }
+
+ public interface NestedScrollingParent2 extends androidx.core.view.NestedScrollingParent {
+ method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View, int);
+ }
+
+ public interface NestedScrollingParent3 extends androidx.core.view.NestedScrollingParent2 {
+ method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]);
+ }
+
+ public class NestedScrollingParentHelper {
+ ctor public NestedScrollingParentHelper(android.view.ViewGroup);
+ method public int getNestedScrollAxes();
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View);
+ method public void onStopNestedScroll(android.view.View, int);
+ }
+
+ public interface OnApplyWindowInsetsListener {
+ method public androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ }
+
+ public interface OnReceiveContentListener {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ }
+
+ public interface OnReceiveContentViewBehavior {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(androidx.core.view.ContentInfoCompat);
+ }
+
+ public final class OneShotPreDrawListener implements android.view.View.OnAttachStateChangeListener android.view.ViewTreeObserver.OnPreDrawListener {
+ method public static androidx.core.view.OneShotPreDrawListener add(android.view.View, Runnable);
+ method public boolean onPreDraw();
+ method public void onViewAttachedToWindow(android.view.View);
+ method public void onViewDetachedFromWindow(android.view.View);
+ method public void removeListener();
+ }
+
+ public final class PointerIconCompat {
+ method public static androidx.core.view.PointerIconCompat create(android.graphics.Bitmap, float, float);
+ method public static androidx.core.view.PointerIconCompat getSystemIcon(android.content.Context, int);
+ method public static androidx.core.view.PointerIconCompat load(android.content.res.Resources, int);
+ field public static final int TYPE_ALIAS = 1010; // 0x3f2
+ field public static final int TYPE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int TYPE_ARROW = 1000; // 0x3e8
+ field public static final int TYPE_CELL = 1006; // 0x3ee
+ field public static final int TYPE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int TYPE_COPY = 1011; // 0x3f3
+ field public static final int TYPE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int TYPE_DEFAULT = 1000; // 0x3e8
+ field public static final int TYPE_GRAB = 1020; // 0x3fc
+ field public static final int TYPE_GRABBING = 1021; // 0x3fd
+ field public static final int TYPE_HAND = 1002; // 0x3ea
+ field public static final int TYPE_HELP = 1003; // 0x3eb
+ field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int TYPE_NO_DROP = 1012; // 0x3f4
+ field public static final int TYPE_NULL = 0; // 0x0
+ field public static final int TYPE_TEXT = 1008; // 0x3f0
+ field public static final int TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int TYPE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int TYPE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int TYPE_WAIT = 1004; // 0x3ec
+ field public static final int TYPE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int TYPE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
+ public final class ScaleGestureDetectorCompat {
+ method @Deprecated public static boolean isQuickScaleEnabled(Object!);
+ method public static boolean isQuickScaleEnabled(android.view.ScaleGestureDetector);
+ method @Deprecated public static void setQuickScaleEnabled(Object!, boolean);
+ method public static void setQuickScaleEnabled(android.view.ScaleGestureDetector, boolean);
+ }
+
+ public interface ScrollingView {
+ method public int computeHorizontalScrollExtent();
+ method public int computeHorizontalScrollOffset();
+ method public int computeHorizontalScrollRange();
+ method public int computeVerticalScrollExtent();
+ method public int computeVerticalScrollOffset();
+ method public int computeVerticalScrollRange();
+ }
+
+ public interface TintableBackgroundView {
+ method public android.content.res.ColorStateList? getSupportBackgroundTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
+ method public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
+ method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ @Deprecated public final class VelocityTrackerCompat {
+ method @Deprecated public static float getXVelocity(android.view.VelocityTracker!, int);
+ method @Deprecated public static float getYVelocity(android.view.VelocityTracker!, int);
+ }
+
+ public class ViewCompat {
+ ctor @Deprecated protected ViewCompat();
+ method public static int addAccessibilityAction(android.view.View, CharSequence, androidx.core.view.accessibility.AccessibilityViewCommand);
+ method public static void addKeyboardNavigationClusters(android.view.View, java.util.Collection<android.view.View!>, int);
+ method public static void addOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static androidx.core.view.ViewPropertyAnimatorCompat animate(android.view.View);
+ method @Deprecated public static boolean canScrollHorizontally(android.view.View!, int);
+ method @Deprecated public static boolean canScrollVertically(android.view.View!, int);
+ method public static void cancelDragAndDrop(android.view.View);
+ method @Deprecated public static int combineMeasuredStates(int, int);
+ method public static androidx.core.view.WindowInsetsCompat computeSystemWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat, android.graphics.Rect);
+ method public static androidx.core.view.WindowInsetsCompat dispatchApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method public static void dispatchFinishTemporaryDetach(android.view.View);
+ method public static boolean dispatchNestedFling(android.view.View, float, float, boolean);
+ method public static boolean dispatchNestedPreFling(android.view.View, float, float);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?, int);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?);
+ method public static void dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, int, int[]);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, int);
+ method public static void dispatchStartTemporaryDetach(android.view.View);
+ method public static void enableAccessibleClickableSpanSupport(android.view.View);
+ method public static int generateViewId();
+ method public static androidx.core.view.AccessibilityDelegateCompat? getAccessibilityDelegate(android.view.View);
+ method public static int getAccessibilityLiveRegion(android.view.View);
+ method public static androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method @UiThread public static CharSequence? getAccessibilityPaneTitle(android.view.View);
+ method @Deprecated public static float getAlpha(android.view.View!);
+ method public static android.content.res.ColorStateList? getBackgroundTintList(android.view.View);
+ method public static android.graphics.PorterDuff.Mode? getBackgroundTintMode(android.view.View);
+ method public static android.graphics.Rect? getClipBounds(android.view.View);
+ method public static android.view.Display? getDisplay(android.view.View);
+ method public static float getElevation(android.view.View);
+ method public static boolean getFitsSystemWindows(android.view.View);
+ method public static int getImportantForAccessibility(android.view.View);
+ method public static int getImportantForAutofill(android.view.View);
+ method public static int getLabelFor(android.view.View);
+ method @Deprecated public static int getLayerType(android.view.View!);
+ method public static int getLayoutDirection(android.view.View);
+ method @Deprecated public static android.graphics.Matrix? getMatrix(android.view.View!);
+ method @Deprecated public static int getMeasuredHeightAndState(android.view.View!);
+ method @Deprecated public static int getMeasuredState(android.view.View!);
+ method @Deprecated public static int getMeasuredWidthAndState(android.view.View!);
+ method public static int getMinimumHeight(android.view.View);
+ method public static int getMinimumWidth(android.view.View);
+ method public static int getNextClusterForwardId(android.view.View);
+ method public static String![]? getOnReceiveContentMimeTypes(android.view.View);
+ method @Deprecated public static int getOverScrollMode(android.view.View!);
+ method @Px public static int getPaddingEnd(android.view.View);
+ method @Px public static int getPaddingStart(android.view.View);
+ method public static android.view.ViewParent? getParentForAccessibility(android.view.View);
+ method @Deprecated public static float getPivotX(android.view.View!);
+ method @Deprecated public static float getPivotY(android.view.View!);
+ method public static androidx.core.view.WindowInsetsCompat? getRootWindowInsets(android.view.View);
+ method @Deprecated public static float getRotation(android.view.View!);
+ method @Deprecated public static float getRotationX(android.view.View!);
+ method @Deprecated public static float getRotationY(android.view.View!);
+ method @Deprecated public static float getScaleX(android.view.View!);
+ method @Deprecated public static float getScaleY(android.view.View!);
+ method public static int getScrollIndicators(android.view.View);
+ method @UiThread public static CharSequence? getStateDescription(android.view.View);
+ method public static java.util.List<android.graphics.Rect!> getSystemGestureExclusionRects(android.view.View);
+ method public static String? getTransitionName(android.view.View);
+ method @Deprecated public static float getTranslationX(android.view.View!);
+ method @Deprecated public static float getTranslationY(android.view.View!);
+ method public static float getTranslationZ(android.view.View);
+ method @Deprecated public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
+ method @Deprecated public static int getWindowSystemUiVisibility(android.view.View);
+ method @Deprecated public static float getX(android.view.View!);
+ method @Deprecated public static float getY(android.view.View!);
+ method public static float getZ(android.view.View);
+ method public static boolean hasAccessibilityDelegate(android.view.View);
+ method public static boolean hasExplicitFocusable(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View, int);
+ method public static boolean hasOnClickListeners(android.view.View);
+ method public static boolean hasOverlappingRendering(android.view.View);
+ method public static boolean hasTransientState(android.view.View);
+ method @UiThread public static boolean isAccessibilityHeading(android.view.View);
+ method public static boolean isAttachedToWindow(android.view.View);
+ method public static boolean isFocusedByDefault(android.view.View);
+ method public static boolean isImportantForAccessibility(android.view.View);
+ method public static boolean isImportantForAutofill(android.view.View);
+ method public static boolean isInLayout(android.view.View);
+ method public static boolean isKeyboardNavigationCluster(android.view.View);
+ method public static boolean isLaidOut(android.view.View);
+ method public static boolean isLayoutDirectionResolved(android.view.View);
+ method public static boolean isNestedScrollingEnabled(android.view.View);
+ method @Deprecated public static boolean isOpaque(android.view.View!);
+ method public static boolean isPaddingRelative(android.view.View);
+ method @UiThread public static boolean isScreenReaderFocusable(android.view.View);
+ method @Deprecated public static void jumpDrawablesToCurrentState(android.view.View!);
+ method public static android.view.View? keyboardNavigationClusterSearch(android.view.View, android.view.View?, int);
+ method public static void offsetLeftAndRight(android.view.View, int);
+ method public static void offsetTopAndBottom(android.view.View, int);
+ method public static androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method @Deprecated public static void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method @Deprecated public static void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public static androidx.core.view.ContentInfoCompat? performReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ method public static void postInvalidateOnAnimation(android.view.View);
+ method public static void postInvalidateOnAnimation(android.view.View, int, int, int, int);
+ method public static void postOnAnimation(android.view.View, Runnable);
+ method public static void postOnAnimationDelayed(android.view.View, Runnable, long);
+ method public static void removeAccessibilityAction(android.view.View, int);
+ method public static void removeOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static void replaceAccessibilityAction(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat, CharSequence?, androidx.core.view.accessibility.AccessibilityViewCommand?);
+ method public static void requestApplyInsets(android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.View, @IdRes int);
+ method @Deprecated public static int resolveSizeAndState(int, int, int);
+ method public static boolean restoreDefaultFocus(android.view.View);
+ method public static void saveAttributeDataForStyleable(android.view.View, android.content.Context, int[], android.util.AttributeSet?, android.content.res.TypedArray, int, int);
+ method public static void setAccessibilityDelegate(android.view.View, androidx.core.view.AccessibilityDelegateCompat?);
+ method @UiThread public static void setAccessibilityHeading(android.view.View, boolean);
+ method public static void setAccessibilityLiveRegion(android.view.View, int);
+ method @UiThread public static void setAccessibilityPaneTitle(android.view.View, CharSequence?);
+ method @Deprecated public static void setActivated(android.view.View!, boolean);
+ method @Deprecated public static void setAlpha(android.view.View!, @FloatRange(from=0.0, to=1.0) float);
+ method public static void setAutofillHints(android.view.View, java.lang.String!...);
+ method public static void setBackground(android.view.View, android.graphics.drawable.Drawable?);
+ method public static void setBackgroundTintList(android.view.View, android.content.res.ColorStateList?);
+ method public static void setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode?);
+ method @Deprecated public static void setChildrenDrawingOrderEnabled(android.view.ViewGroup!, boolean);
+ method public static void setClipBounds(android.view.View, android.graphics.Rect?);
+ method public static void setElevation(android.view.View, float);
+ method @Deprecated public static void setFitsSystemWindows(android.view.View!, boolean);
+ method public static void setFocusedByDefault(android.view.View, boolean);
+ method public static void setHasTransientState(android.view.View, boolean);
+ method @UiThread public static void setImportantForAccessibility(android.view.View, int);
+ method public static void setImportantForAutofill(android.view.View, int);
+ method public static void setKeyboardNavigationCluster(android.view.View, boolean);
+ method public static void setLabelFor(android.view.View, @IdRes int);
+ method public static void setLayerPaint(android.view.View, android.graphics.Paint?);
+ method @Deprecated public static void setLayerType(android.view.View!, int, android.graphics.Paint!);
+ method public static void setLayoutDirection(android.view.View, int);
+ method public static void setNestedScrollingEnabled(android.view.View, boolean);
+ method public static void setNextClusterForwardId(android.view.View, int);
+ method public static void setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener?);
+ method public static void setOnReceiveContentListener(android.view.View, String![]?, androidx.core.view.OnReceiveContentListener?);
+ method @Deprecated public static void setOverScrollMode(android.view.View!, int);
+ method public static void setPaddingRelative(android.view.View, @Px int, @Px int, @Px int, @Px int);
+ method @Deprecated public static void setPivotX(android.view.View!, float);
+ method @Deprecated public static void setPivotY(android.view.View!, float);
+ method public static void setPointerIcon(android.view.View, androidx.core.view.PointerIconCompat?);
+ method @Deprecated public static void setRotation(android.view.View!, float);
+ method @Deprecated public static void setRotationX(android.view.View!, float);
+ method @Deprecated public static void setRotationY(android.view.View!, float);
+ method @Deprecated public static void setSaveFromParentEnabled(android.view.View!, boolean);
+ method @Deprecated public static void setScaleX(android.view.View!, float);
+ method @Deprecated public static void setScaleY(android.view.View!, float);
+ method @UiThread public static void setScreenReaderFocusable(android.view.View, boolean);
+ method public static void setScrollIndicators(android.view.View, int);
+ method public static void setScrollIndicators(android.view.View, int, int);
+ method @UiThread public static void setStateDescription(android.view.View, CharSequence?);
+ method public static void setSystemGestureExclusionRects(android.view.View, java.util.List<android.graphics.Rect!>);
+ method public static void setTooltipText(android.view.View, CharSequence?);
+ method public static void setTransitionName(android.view.View, String?);
+ method @Deprecated public static void setTranslationX(android.view.View!, float);
+ method @Deprecated public static void setTranslationY(android.view.View!, float);
+ method public static void setTranslationZ(android.view.View, float);
+ method public static void setWindowInsetsAnimationCallback(android.view.View, androidx.core.view.WindowInsetsAnimationCompat.Callback?);
+ method @Deprecated public static void setX(android.view.View!, float);
+ method @Deprecated public static void setY(android.view.View!, float);
+ method public static void setZ(android.view.View, float);
+ method public static boolean startDragAndDrop(android.view.View, android.content.ClipData?, android.view.View.DragShadowBuilder, Object?, int);
+ method public static boolean startNestedScroll(android.view.View, int);
+ method public static boolean startNestedScroll(android.view.View, int, int);
+ method public static void stopNestedScroll(android.view.View);
+ method public static void stopNestedScroll(android.view.View, int);
+ method public static void updateDragShadow(android.view.View, android.view.View.DragShadowBuilder);
+ field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
+ field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
+ field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field @Deprecated public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
+ field @Deprecated public static final int LAYER_TYPE_NONE = 0; // 0x0
+ field @Deprecated public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
+ field public static final int LAYOUT_DIRECTION_INHERIT = 2; // 0x2
+ field public static final int LAYOUT_DIRECTION_LOCALE = 3; // 0x3
+ field public static final int LAYOUT_DIRECTION_LTR = 0; // 0x0
+ field public static final int LAYOUT_DIRECTION_RTL = 1; // 0x1
+ field @Deprecated public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; // 0x10
+ field @Deprecated public static final int MEASURED_SIZE_MASK = 16777215; // 0xffffff
+ field @Deprecated public static final int MEASURED_STATE_MASK = -16777216; // 0xff000000
+ field @Deprecated public static final int MEASURED_STATE_TOO_SMALL = 16777216; // 0x1000000
+ field @Deprecated public static final int OVER_SCROLL_ALWAYS = 0; // 0x0
+ field @Deprecated public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; // 0x1
+ field @Deprecated public static final int OVER_SCROLL_NEVER = 2; // 0x2
+ field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
+ field public static final int SCROLL_AXIS_NONE = 0; // 0x0
+ field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+ field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+ field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+ field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+ field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
+ field public static final int TYPE_NON_TOUCH = 1; // 0x1
+ field public static final int TYPE_TOUCH = 0; // 0x0
+ }
+
+ public static interface ViewCompat.OnUnhandledKeyEventListenerCompat {
+ method public boolean onUnhandledKeyEvent(android.view.View, android.view.KeyEvent);
+ }
+
+ public final class ViewConfigurationCompat {
+ method public static float getScaledHorizontalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method public static int getScaledHoverSlop(android.view.ViewConfiguration);
+ method @Deprecated public static int getScaledPagingTouchSlop(android.view.ViewConfiguration!);
+ method public static float getScaledVerticalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method @Deprecated public static boolean hasPermanentMenuKey(android.view.ViewConfiguration!);
+ method public static boolean shouldShowMenuShortcutsWhenKeyboardPresent(android.view.ViewConfiguration, android.content.Context);
+ }
+
+ public final class ViewGroupCompat {
+ method public static int getLayoutMode(android.view.ViewGroup);
+ method public static int getNestedScrollAxes(android.view.ViewGroup);
+ method public static boolean isTransitionGroup(android.view.ViewGroup);
+ method @Deprecated public static boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void setLayoutMode(android.view.ViewGroup, int);
+ method @Deprecated public static void setMotionEventSplittingEnabled(android.view.ViewGroup!, boolean);
+ method public static void setTransitionGroup(android.view.ViewGroup, boolean);
+ field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
+ field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
+ }
+
+ public final class ViewParentCompat {
+ method public static void notifySubtreeAccessibilityStateChanged(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onNestedFling(android.view.ViewParent, android.view.View, float, float, boolean);
+ method public static boolean onNestedPreFling(android.view.ViewParent, android.view.View, float, float);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[]);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[], int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int, int[]);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View, int);
+ method @Deprecated public static boolean requestSendAccessibilityEvent(android.view.ViewParent!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ }
+
+ public final class ViewPropertyAnimatorCompat {
+ method public androidx.core.view.ViewPropertyAnimatorCompat alpha(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat alphaBy(float);
+ method public void cancel();
+ method public long getDuration();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method public long getStartDelay();
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotation(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setDuration(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setInterpolator(android.view.animation.Interpolator?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setListener(androidx.core.view.ViewPropertyAnimatorListener?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setStartDelay(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setUpdateListener(androidx.core.view.ViewPropertyAnimatorUpdateListener?);
+ method public void start();
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZ(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withEndAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withLayer();
+ method public androidx.core.view.ViewPropertyAnimatorCompat withStartAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat x(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat xBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat y(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat yBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat z(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat zBy(float);
+ }
+
+ public interface ViewPropertyAnimatorListener {
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public class ViewPropertyAnimatorListenerAdapter implements androidx.core.view.ViewPropertyAnimatorListener {
+ ctor public ViewPropertyAnimatorListenerAdapter();
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public interface ViewPropertyAnimatorUpdateListener {
+ method public void onAnimationUpdate(android.view.View);
+ }
+
+ public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat getInsetsController(android.view.Window, android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
+ method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
+ field public static final int FEATURE_ACTION_BAR = 8; // 0x8
+ field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9
+ field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
+ }
+
+ public final class WindowInsetsAnimationCompat {
+ ctor public WindowInsetsAnimationCompat(int, android.view.animation.Interpolator?, long);
+ method @FloatRange(from=0.0f, to=1.0f) public float getAlpha();
+ method public long getDurationMillis();
+ method @FloatRange(from=0.0f, to=1.0f) public float getFraction();
+ method public float getInterpolatedFraction();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method public int getTypeMask();
+ method public void setAlpha(@FloatRange(from=0.0f, to=1.0f) float);
+ method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public static final class WindowInsetsAnimationCompat.BoundsCompat {
+ ctor public WindowInsetsAnimationCompat.BoundsCompat(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public androidx.core.graphics.Insets getLowerBound();
+ method public androidx.core.graphics.Insets getUpperBound();
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat inset(androidx.core.graphics.Insets);
+ method @RequiresApi(30) public android.view.WindowInsetsAnimation.Bounds toBounds();
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat toBoundsCompat(android.view.WindowInsetsAnimation.Bounds);
+ }
+
+ public abstract static class WindowInsetsAnimationCompat.Callback {
+ ctor public WindowInsetsAnimationCompat.Callback(int);
+ method public final int getDispatchMode();
+ method public void onEnd(androidx.core.view.WindowInsetsAnimationCompat);
+ method public void onPrepare(androidx.core.view.WindowInsetsAnimationCompat);
+ method public abstract androidx.core.view.WindowInsetsCompat onProgress(androidx.core.view.WindowInsetsCompat, java.util.List<androidx.core.view.WindowInsetsAnimationCompat!>);
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat onStart(androidx.core.view.WindowInsetsAnimationCompat, androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat);
+ field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
+ field public static final int DISPATCH_MODE_STOP = 0; // 0x0
+ }
+
+ public interface WindowInsetsAnimationControlListenerCompat {
+ method public void onCancelled(androidx.core.view.WindowInsetsAnimationControllerCompat?);
+ method public void onFinished(androidx.core.view.WindowInsetsAnimationControllerCompat);
+ method public void onReady(androidx.core.view.WindowInsetsAnimationControllerCompat, int);
+ }
+
+ public final class WindowInsetsAnimationControllerCompat {
+ method public void finish(boolean);
+ method public float getCurrentAlpha();
+ method @FloatRange(from=0.0f, to=1.0f) public float getCurrentFraction();
+ method public androidx.core.graphics.Insets getCurrentInsets();
+ method public androidx.core.graphics.Insets getHiddenStateInsets();
+ method public androidx.core.graphics.Insets getShownStateInsets();
+ method public int getTypes();
+ method public boolean isCancelled();
+ method public boolean isFinished();
+ method public boolean isReady();
+ method public void setInsetsAndAlpha(androidx.core.graphics.Insets?, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public class WindowInsetsCompat {
+ ctor public WindowInsetsCompat(androidx.core.view.WindowInsetsCompat?);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeDisplayCutout();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeStableInsets();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeSystemWindowInsets();
+ method public androidx.core.view.DisplayCutoutCompat? getDisplayCutout();
+ method public androidx.core.graphics.Insets getInsets(int);
+ method public androidx.core.graphics.Insets getInsetsIgnoringVisibility(int);
+ method @Deprecated public androidx.core.graphics.Insets getMandatorySystemGestureInsets();
+ method @Deprecated public int getStableInsetBottom();
+ method @Deprecated public int getStableInsetLeft();
+ method @Deprecated public int getStableInsetRight();
+ method @Deprecated public int getStableInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getStableInsets();
+ method @Deprecated public androidx.core.graphics.Insets getSystemGestureInsets();
+ method @Deprecated public int getSystemWindowInsetBottom();
+ method @Deprecated public int getSystemWindowInsetLeft();
+ method @Deprecated public int getSystemWindowInsetRight();
+ method @Deprecated public int getSystemWindowInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getSystemWindowInsets();
+ method @Deprecated public androidx.core.graphics.Insets getTappableElementInsets();
+ method public boolean hasInsets();
+ method @Deprecated public boolean hasStableInsets();
+ method @Deprecated public boolean hasSystemWindowInsets();
+ method public androidx.core.view.WindowInsetsCompat inset(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat inset(@IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+ method public boolean isConsumed();
+ method public boolean isRound();
+ method public boolean isVisible(int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(int, int, int, int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
+ method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets, android.view.View?);
+ field public static final androidx.core.view.WindowInsetsCompat CONSUMED;
+ }
+
+ public static final class WindowInsetsCompat.Builder {
+ ctor public WindowInsetsCompat.Builder();
+ ctor public WindowInsetsCompat.Builder(androidx.core.view.WindowInsetsCompat);
+ method public androidx.core.view.WindowInsetsCompat build();
+ method public androidx.core.view.WindowInsetsCompat.Builder setDisplayCutout(androidx.core.view.DisplayCutoutCompat?);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsets(int, androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsetsIgnoringVisibility(int, androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setMandatorySystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setStableInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemWindowInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setTappableElementInsets(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setVisible(int, boolean);
+ }
+
+ public static final class WindowInsetsCompat.Type {
+ method public static int captionBar();
+ method public static int displayCutout();
+ method public static int ime();
+ method public static int mandatorySystemGestures();
+ method public static int navigationBars();
+ method public static int statusBars();
+ method public static int systemBars();
+ method public static int systemGestures();
+ method public static int tappableElement();
+ }
+
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public void addOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void controlWindowInsetsAnimation(int, long, android.view.animation.Interpolator?, android.os.CancellationSignal?, androidx.core.view.WindowInsetsAnimationControlListenerCompat);
+ method public int getSystemBarsBehavior();
+ method public void hide(int);
+ method public boolean isAppearanceLightNavigationBars();
+ method public boolean isAppearanceLightStatusBars();
+ method public void removeOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void setAppearanceLightNavigationBars(boolean);
+ method public void setAppearanceLightStatusBars(boolean);
+ method public void setSystemBarsBehavior(int);
+ method public void show(int);
+ method @Deprecated @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_DEFAULT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
+ public static interface WindowInsetsControllerCompat.OnControllableInsetsChangedListener {
+ method public void onControllableInsetsChanged(androidx.core.view.WindowInsetsControllerCompat, int);
+ }
+
+}
+
+package androidx.core.view.accessibility {
+
+ public final class AccessibilityClickableSpanCompat extends android.text.style.ClickableSpan {
+ method public void onClick(android.view.View);
+ }
+
+ public final class AccessibilityEventCompat {
+ method @Deprecated public static void appendRecord(android.view.accessibility.AccessibilityEvent!, androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! asRecord(android.view.accessibility.AccessibilityEvent!);
+ method public static int getAction(android.view.accessibility.AccessibilityEvent);
+ method public static int getContentChangeTypes(android.view.accessibility.AccessibilityEvent);
+ method public static int getMovementGranularity(android.view.accessibility.AccessibilityEvent);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! getRecord(android.view.accessibility.AccessibilityEvent!, int);
+ method @Deprecated public static int getRecordCount(android.view.accessibility.AccessibilityEvent!);
+ method public static void setAction(android.view.accessibility.AccessibilityEvent, int);
+ method public static void setContentChangeTypes(android.view.accessibility.AccessibilityEvent, int);
+ method public static void setMovementGranularity(android.view.accessibility.AccessibilityEvent, int);
+ field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 512; // 0x200
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 256; // 0x100
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 128; // 0x80
+ field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10
+ field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20
+ field public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 8; // 0x8
+ field public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 64; // 0x40
+ field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
+ field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
+ field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
+ field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+ field public static final int TYPE_ASSIST_READING_CONTEXT = 16777216; // 0x1000000
+ field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
+ field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
+ field public static final int TYPE_TOUCH_INTERACTION_END = 2097152; // 0x200000
+ field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
+ field public static final int TYPE_VIEW_CONTEXT_CLICKED = 8388608; // 0x800000
+ field @Deprecated public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
+ field @Deprecated public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
+ field @Deprecated public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
+ field @Deprecated public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
+ field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
+ field public static final int TYPE_WINDOWS_CHANGED = 4194304; // 0x400000
+ field @Deprecated public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
+ }
+
+ public final class AccessibilityManagerCompat {
+ method @Deprecated public static boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getEnabledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!, int);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getInstalledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean isTouchExplorationEnabled(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ }
+
+ @Deprecated public static interface AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ method @Deprecated public void onAccessibilityStateChanged(boolean);
+ }
+
+ @Deprecated public abstract static class AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat implements androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ ctor @Deprecated public AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat();
+ }
+
+ public static interface AccessibilityManagerCompat.TouchExplorationStateChangeListener {
+ method public void onTouchExplorationStateChanged(boolean);
+ }
+
+ public class AccessibilityNodeInfoCompat {
+ ctor @Deprecated public AccessibilityNodeInfoCompat(Object!);
+ method public void addAction(int);
+ method public void addAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public void addChild(android.view.View!);
+ method public void addChild(android.view.View!, int);
+ method public boolean canOpenPopup();
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByText(String!);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByViewId(String!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! findFocus(int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! focusSearch(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!>! getActionList();
+ method @Deprecated public int getActions();
+ method public java.util.List<java.lang.String!> getAvailableExtraData();
+ method @Deprecated public void getBoundsInParent(android.graphics.Rect!);
+ method public void getBoundsInScreen(android.graphics.Rect!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getChild(int);
+ method public int getChildCount();
+ method public CharSequence! getClassName();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! getCollectionInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! getCollectionItemInfo();
+ method public CharSequence! getContentDescription();
+ method public int getDrawingOrder();
+ method public CharSequence! getError();
+ method public android.view.accessibility.AccessibilityNodeInfo.ExtraRenderingInfo? getExtraRenderingInfo();
+ method public android.os.Bundle! getExtras();
+ method public CharSequence? getHintText();
+ method @Deprecated public Object! getInfo();
+ method public int getInputType();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabelFor();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
+ method public int getLiveRegion();
+ method public int getMaxTextLength();
+ method public long getMinDurationBetweenContentChangesMillis();
+ method public int getMovementGranularities();
+ method public CharSequence! getPackageName();
+ method public CharSequence? getPaneTitle();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getParent();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! getRangeInfo();
+ method public CharSequence? getRoleDescription();
+ method public CharSequence? getStateDescription();
+ method public CharSequence! getText();
+ method public int getTextSelectionEnd();
+ method public int getTextSelectionStart();
+ method public CharSequence? getTooltipText();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat? getTouchDelegateInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalAfter();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalBefore();
+ method public String? getUniqueId();
+ method public String! getViewIdResourceName();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat! getWindow();
+ method public int getWindowId();
+ method public boolean hasRequestInitialAccessibilityFocus();
+ method public boolean isAccessibilityFocused();
+ method public boolean isCheckable();
+ method public boolean isChecked();
+ method public boolean isClickable();
+ method public boolean isContentInvalid();
+ method public boolean isContextClickable();
+ method public boolean isDismissable();
+ method public boolean isEditable();
+ method public boolean isEnabled();
+ method public boolean isFocusable();
+ method public boolean isFocused();
+ method public boolean isHeading();
+ method public boolean isImportantForAccessibility();
+ method public boolean isLongClickable();
+ method public boolean isMultiLine();
+ method public boolean isPassword();
+ method public boolean isScreenReaderFocusable();
+ method public boolean isScrollable();
+ method public boolean isSelected();
+ method public boolean isShowingHintText();
+ method public boolean isTextEntryKey();
+ method public boolean isTextSelectable();
+ method public boolean isVisibleToUser();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
+ method public boolean performAction(int);
+ method public boolean performAction(int, android.os.Bundle!);
+ method @Deprecated public void recycle();
+ method public boolean refresh();
+ method public boolean removeAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public boolean removeChild(android.view.View!);
+ method public boolean removeChild(android.view.View!, int);
+ method public void setAccessibilityFocused(boolean);
+ method public void setAvailableExtraData(java.util.List<java.lang.String!>);
+ method @Deprecated public void setBoundsInParent(android.graphics.Rect!);
+ method public void setBoundsInScreen(android.graphics.Rect!);
+ method public void setCanOpenPopup(boolean);
+ method public void setCheckable(boolean);
+ method public void setChecked(boolean);
+ method public void setClassName(CharSequence!);
+ method public void setClickable(boolean);
+ method public void setCollectionInfo(Object!);
+ method public void setCollectionItemInfo(Object!);
+ method public void setContentDescription(CharSequence!);
+ method public void setContentInvalid(boolean);
+ method public void setContextClickable(boolean);
+ method public void setDismissable(boolean);
+ method public void setDrawingOrder(int);
+ method public void setEditable(boolean);
+ method public void setEnabled(boolean);
+ method public void setError(CharSequence!);
+ method public void setFocusable(boolean);
+ method public void setFocused(boolean);
+ method public void setHeading(boolean);
+ method public void setHintText(CharSequence?);
+ method public void setImportantForAccessibility(boolean);
+ method public void setInputType(int);
+ method public void setLabelFor(android.view.View!);
+ method public void setLabelFor(android.view.View!, int);
+ method public void setLabeledBy(android.view.View!);
+ method public void setLabeledBy(android.view.View!, int);
+ method public void setLiveRegion(int);
+ method public void setLongClickable(boolean);
+ method public void setMaxTextLength(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
+ method public void setMovementGranularities(int);
+ method public void setMultiLine(boolean);
+ method public void setPackageName(CharSequence!);
+ method public void setPaneTitle(CharSequence?);
+ method public void setParent(android.view.View!);
+ method public void setParent(android.view.View!, int);
+ method public void setPassword(boolean);
+ method public void setRangeInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat!);
+ method public void setRequestInitialAccessibilityFocus(boolean);
+ method public void setRoleDescription(CharSequence?);
+ method public void setScreenReaderFocusable(boolean);
+ method public void setScrollable(boolean);
+ method public void setSelected(boolean);
+ method public void setShowingHintText(boolean);
+ method public void setSource(android.view.View!);
+ method public void setSource(android.view.View!, int);
+ method public void setStateDescription(CharSequence?);
+ method public void setText(CharSequence!);
+ method public void setTextEntryKey(boolean);
+ method public void setTextSelectable(boolean);
+ method public void setTextSelection(int, int);
+ method public void setTooltipText(CharSequence?);
+ method public void setTouchDelegateInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat);
+ method public void setTraversalAfter(android.view.View!);
+ method public void setTraversalAfter(android.view.View!, int);
+ method public void setTraversalBefore(android.view.View!);
+ method public void setTraversalBefore(android.view.View!, int);
+ method public void setUniqueId(String?);
+ method public void setViewIdResourceName(String!);
+ method public void setVisibleToUser(boolean);
+ method public android.view.accessibility.AccessibilityNodeInfo! unwrap();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! wrap(android.view.accessibility.AccessibilityNodeInfo);
+ field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+ field public static final String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
+ field public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
+ field public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
+ field public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_X = "ACTION_ARGUMENT_MOVE_WINDOW_X";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y = "ACTION_ARGUMENT_MOVE_WINDOW_Y";
+ field public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT = "android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT";
+ field public static final String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
+ field public static final String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
+ field public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
+ field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
+ field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
+ field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
+ field public static final int ACTION_CLICK = 16; // 0x10
+ field public static final int ACTION_COLLAPSE = 524288; // 0x80000
+ field public static final int ACTION_COPY = 16384; // 0x4000
+ field public static final int ACTION_CUT = 65536; // 0x10000
+ field public static final int ACTION_DISMISS = 1048576; // 0x100000
+ field public static final int ACTION_EXPAND = 262144; // 0x40000
+ field public static final int ACTION_FOCUS = 1; // 0x1
+ field public static final int ACTION_LONG_CLICK = 32; // 0x20
+ field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
+ field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
+ field public static final int ACTION_PASTE = 32768; // 0x8000
+ field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
+ field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
+ field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
+ field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
+ field public static final int ACTION_SELECT = 4; // 0x4
+ field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
+ field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+ field public static final int EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH = 20000; // 0x4e20
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
+ field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
+ field public static final int FOCUS_INPUT = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_LINE = 4; // 0x4
+ field public static final int MOVEMENT_GRANULARITY_PAGE = 16; // 0x10
+ field public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 8; // 0x8
+ field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
+ }
+
+ public static class AccessibilityNodeInfoCompat.AccessibilityActionCompat {
+ ctor public AccessibilityNodeInfoCompat.AccessibilityActionCompat(int, CharSequence!);
+ method public int getId();
+ method public CharSequence! getLabel();
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COLLAPSE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CONTEXT_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COPY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CUT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_DISMISS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_CANCEL;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_DROP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_START;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_EXPAND;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_HIDE_TOOLTIP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_IME_ENTER;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_LONG_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_MOVE_WINDOW;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PASTE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PRESS_AND_HOLD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_BACKWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_FORWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_TO_POSITION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SELECT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_PROGRESS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_TEXT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_ON_SCREEN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_SHOW_TEXT_SUGGESTIONS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_TOOLTIP;
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionInfoCompat {
+ method public int getColumnCount();
+ method public int getRowCount();
+ method public int getSelectionMode();
+ method public boolean isHierarchical();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean);
+ field public static final int SELECTION_MODE_MULTIPLE = 2; // 0x2
+ field public static final int SELECTION_MODE_NONE = 0; // 0x0
+ field public static final int SELECTION_MODE_SINGLE = 1; // 0x1
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionItemInfoCompat {
+ method public int getColumnIndex();
+ method public int getColumnSpan();
+ method public int getRowIndex();
+ method public int getRowSpan();
+ method @Deprecated public boolean isHeading();
+ method public boolean isSelected();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean, boolean);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean);
+ }
+
+ public static class AccessibilityNodeInfoCompat.RangeInfoCompat {
+ method public float getCurrent();
+ method public float getMax();
+ method public float getMin();
+ method public int getType();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! obtain(int, float, float, float);
+ field public static final int RANGE_TYPE_FLOAT = 1; // 0x1
+ field public static final int RANGE_TYPE_INT = 0; // 0x0
+ field public static final int RANGE_TYPE_PERCENT = 2; // 0x2
+ }
+
+ public static final class AccessibilityNodeInfoCompat.TouchDelegateInfoCompat {
+ ctor public AccessibilityNodeInfoCompat.TouchDelegateInfoCompat(java.util.Map<android.graphics.Region!,android.view.View!>);
+ method public android.graphics.Region? getRegionAt(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getRegionCount();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getTargetForRegion(android.graphics.Region);
+ }
+
+ public class AccessibilityNodeProviderCompat {
+ ctor public AccessibilityNodeProviderCompat();
+ ctor public AccessibilityNodeProviderCompat(Object?);
+ method public void addExtraDataToAccessibilityNodeInfo(int, androidx.core.view.accessibility.AccessibilityNodeInfoCompat, String, android.os.Bundle?);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? createAccessibilityNodeInfo(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>? findAccessibilityNodeInfosByText(String, int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? findFocus(int);
+ method public Object? getProvider();
+ method public boolean performAction(int, int, android.os.Bundle?);
+ field public static final int HOST_VIEW_ID = -1; // 0xffffffff
+ }
+
+ public class AccessibilityRecordCompat {
+ ctor @Deprecated public AccessibilityRecordCompat(Object!);
+ method @Deprecated public boolean equals(Object?);
+ method @Deprecated public int getAddedCount();
+ method @Deprecated public CharSequence! getBeforeText();
+ method @Deprecated public CharSequence! getClassName();
+ method @Deprecated public CharSequence! getContentDescription();
+ method @Deprecated public int getCurrentItemIndex();
+ method @Deprecated public int getFromIndex();
+ method @Deprecated public Object! getImpl();
+ method @Deprecated public int getItemCount();
+ method @Deprecated public int getMaxScrollX();
+ method public static int getMaxScrollX(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public int getMaxScrollY();
+ method public static int getMaxScrollY(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public android.os.Parcelable! getParcelableData();
+ method @Deprecated public int getRemovedCount();
+ method @Deprecated public int getScrollX();
+ method @Deprecated public int getScrollY();
+ method @Deprecated public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getSource();
+ method @Deprecated public java.util.List<java.lang.CharSequence!>! getText();
+ method @Deprecated public int getToIndex();
+ method @Deprecated public int getWindowId();
+ method @Deprecated public int hashCode();
+ method @Deprecated public boolean isChecked();
+ method @Deprecated public boolean isEnabled();
+ method @Deprecated public boolean isFullScreen();
+ method @Deprecated public boolean isPassword();
+ method @Deprecated public boolean isScrollable();
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain(androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain();
+ method @Deprecated public void recycle();
+ method @Deprecated public void setAddedCount(int);
+ method @Deprecated public void setBeforeText(CharSequence!);
+ method @Deprecated public void setChecked(boolean);
+ method @Deprecated public void setClassName(CharSequence!);
+ method @Deprecated public void setContentDescription(CharSequence!);
+ method @Deprecated public void setCurrentItemIndex(int);
+ method @Deprecated public void setEnabled(boolean);
+ method @Deprecated public void setFromIndex(int);
+ method @Deprecated public void setFullScreen(boolean);
+ method @Deprecated public void setItemCount(int);
+ method @Deprecated public void setMaxScrollX(int);
+ method public static void setMaxScrollX(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setMaxScrollY(int);
+ method public static void setMaxScrollY(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setParcelableData(android.os.Parcelable!);
+ method @Deprecated public void setPassword(boolean);
+ method @Deprecated public void setRemovedCount(int);
+ method @Deprecated public void setScrollX(int);
+ method @Deprecated public void setScrollY(int);
+ method @Deprecated public void setScrollable(boolean);
+ method @Deprecated public void setSource(android.view.View!);
+ method @Deprecated public void setSource(android.view.View!, int);
+ method public static void setSource(android.view.accessibility.AccessibilityRecord, android.view.View?, int);
+ method @Deprecated public void setToIndex(int);
+ }
+
+ public interface AccessibilityViewCommand {
+ method public boolean perform(android.view.View, androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments?);
+ }
+
+ public abstract static class AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.CommandArguments();
+ }
+
+ public static final class AccessibilityViewCommand.MoveAtGranularityArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveAtGranularityArguments();
+ method public boolean getExtendSelection();
+ method public int getGranularity();
+ }
+
+ public static final class AccessibilityViewCommand.MoveHtmlArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveHtmlArguments();
+ method public String? getHTMLElement();
+ }
+
+ public static final class AccessibilityViewCommand.MoveWindowArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveWindowArguments();
+ method public int getX();
+ method public int getY();
+ }
+
+ public static final class AccessibilityViewCommand.ScrollToPositionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.ScrollToPositionArguments();
+ method public int getColumn();
+ method public int getRow();
+ }
+
+ public static final class AccessibilityViewCommand.SetProgressArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetProgressArguments();
+ method public float getProgress();
+ }
+
+ public static final class AccessibilityViewCommand.SetSelectionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetSelectionArguments();
+ method public int getEnd();
+ method public int getStart();
+ }
+
+ public static final class AccessibilityViewCommand.SetTextArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetTextArguments();
+ method public CharSequence? getText();
+ }
+
+ public class AccessibilityWindowInfoCompat {
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getAnchor();
+ method public void getBoundsInScreen(android.graphics.Rect);
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getChild(int);
+ method public int getChildCount();
+ method public int getDisplayId();
+ method public int getId();
+ method public int getLayer();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getParent();
+ method public void getRegionInScreen(android.graphics.Region);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getRoot();
+ method public CharSequence? getTitle();
+ method public int getType();
+ method public boolean isAccessibilityFocused();
+ method public boolean isActive();
+ method public boolean isFocused();
+ method public boolean isInPictureInPictureMode();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain(androidx.core.view.accessibility.AccessibilityWindowInfoCompat?);
+ method @Deprecated public void recycle();
+ method public android.view.accessibility.AccessibilityWindowInfo? unwrap();
+ field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
+ field public static final int TYPE_APPLICATION = 1; // 0x1
+ field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
+ field public static final int TYPE_SYSTEM = 3; // 0x3
+ }
+
+}
+
+package androidx.core.view.animation {
+
+ public final class PathInterpolatorCompat {
+ method public static android.view.animation.Interpolator create(android.graphics.Path);
+ method public static android.view.animation.Interpolator create(float, float);
+ method public static android.view.animation.Interpolator create(float, float, float, float);
+ }
+
+}
+
+package androidx.core.view.inputmethod {
+
+ public final class EditorInfoCompat {
+ ctor @Deprecated public EditorInfoCompat();
+ method public static String![] getContentMimeTypes(android.view.inputmethod.EditorInfo);
+ method public static CharSequence? getInitialSelectedText(android.view.inputmethod.EditorInfo, int);
+ method public static CharSequence? getInitialTextAfterCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static CharSequence? getInitialTextBeforeCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static void setContentMimeTypes(android.view.inputmethod.EditorInfo, String![]?);
+ method public static void setInitialSurroundingSubText(android.view.inputmethod.EditorInfo, CharSequence, int);
+ method public static void setInitialSurroundingText(android.view.inputmethod.EditorInfo, CharSequence);
+ field public static final int IME_FLAG_FORCE_ASCII = -2147483648; // 0x80000000
+ field public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 16777216; // 0x1000000
+ }
+
+ public final class InputConnectionCompat {
+ ctor @Deprecated public InputConnectionCompat();
+ method public static boolean commitContent(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ method @Deprecated public static android.view.inputmethod.InputConnection createWrapper(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener);
+ method public static android.view.inputmethod.InputConnection createWrapper(android.view.View, android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
+ }
+
+ public static interface InputConnectionCompat.OnCommitContentListener {
+ method public boolean onCommitContent(androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ }
+
+ public final class InputContentInfoCompat {
+ ctor public InputContentInfoCompat(android.net.Uri, android.content.ClipDescription, android.net.Uri?);
+ method public android.net.Uri getContentUri();
+ method public android.content.ClipDescription getDescription();
+ method public android.net.Uri? getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
+ method public Object? unwrap();
+ method public static androidx.core.view.inputmethod.InputContentInfoCompat? wrap(Object?);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public abstract class AutoScrollHelper implements android.view.View.OnTouchListener {
+ ctor public AutoScrollHelper(android.view.View);
+ method public abstract boolean canTargetScrollHorizontally(int);
+ method public abstract boolean canTargetScrollVertically(int);
+ method public boolean isEnabled();
+ method public boolean isExclusive();
+ method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+ method public abstract void scrollTargetBy(int, int);
+ method public androidx.core.widget.AutoScrollHelper setActivationDelay(int);
+ method public androidx.core.widget.AutoScrollHelper setEdgeType(int);
+ method public androidx.core.widget.AutoScrollHelper! setEnabled(boolean);
+ method public androidx.core.widget.AutoScrollHelper! setExclusive(boolean);
+ method public androidx.core.widget.AutoScrollHelper setMaximumEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMaximumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMinimumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRampDownDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRampUpDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRelativeEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRelativeVelocity(float, float);
+ field public static final int EDGE_TYPE_INSIDE = 0; // 0x0
+ field public static final int EDGE_TYPE_INSIDE_EXTEND = 1; // 0x1
+ field public static final int EDGE_TYPE_OUTSIDE = 2; // 0x2
+ field public static final float NO_MAX = 3.4028235E38f;
+ field public static final float NO_MIN = 0.0f;
+ field public static final float RELATIVE_UNSPECIFIED = 0.0f;
+ }
+
+ public final class CheckedTextViewCompat {
+ method public static android.graphics.drawable.Drawable? getCheckMarkDrawable(android.widget.CheckedTextView);
+ method public static android.content.res.ColorStateList? getCheckMarkTintList(android.widget.CheckedTextView);
+ method public static android.graphics.PorterDuff.Mode? getCheckMarkTintMode(android.widget.CheckedTextView);
+ method public static void setCheckMarkTintList(android.widget.CheckedTextView, android.content.res.ColorStateList?);
+ method public static void setCheckMarkTintMode(android.widget.CheckedTextView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class CompoundButtonCompat {
+ method public static android.graphics.drawable.Drawable? getButtonDrawable(android.widget.CompoundButton);
+ method public static android.content.res.ColorStateList? getButtonTintList(android.widget.CompoundButton);
+ method public static android.graphics.PorterDuff.Mode? getButtonTintMode(android.widget.CompoundButton);
+ method public static void setButtonTintList(android.widget.CompoundButton, android.content.res.ColorStateList?);
+ method public static void setButtonTintMode(android.widget.CompoundButton, android.graphics.PorterDuff.Mode?);
+ }
+
+ public class ContentLoadingProgressBar extends android.widget.ProgressBar {
+ ctor public ContentLoadingProgressBar(android.content.Context);
+ ctor public ContentLoadingProgressBar(android.content.Context, android.util.AttributeSet?);
+ method public void hide();
+ method public void onAttachedToWindow();
+ method public void onDetachedFromWindow();
+ method public void show();
+ }
+
+ public final class EdgeEffectCompat {
+ ctor @Deprecated public EdgeEffectCompat(android.content.Context!);
+ method public static android.widget.EdgeEffect create(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public boolean draw(android.graphics.Canvas!);
+ method @Deprecated public void finish();
+ method public static float getDistance(android.widget.EdgeEffect);
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean onAbsorb(int);
+ method @Deprecated public boolean onPull(float);
+ method @Deprecated public boolean onPull(float, float);
+ method public static void onPull(android.widget.EdgeEffect, float, float);
+ method public static float onPullDistance(android.widget.EdgeEffect, float, float);
+ method @Deprecated public boolean onRelease();
+ method @Deprecated public void setSize(int, int);
+ }
+
+ public class ImageViewCompat {
+ method public static android.content.res.ColorStateList? getImageTintList(android.widget.ImageView);
+ method public static android.graphics.PorterDuff.Mode? getImageTintMode(android.widget.ImageView);
+ method public static void setImageTintList(android.widget.ImageView, android.content.res.ColorStateList?);
+ method public static void setImageTintMode(android.widget.ImageView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class ListPopupWindowCompat {
+ method @Deprecated public static android.view.View.OnTouchListener! createDragToOpenListener(Object!, android.view.View!);
+ method public static android.view.View.OnTouchListener? createDragToOpenListener(android.widget.ListPopupWindow, android.view.View);
+ }
+
+ public class ListViewAutoScrollHelper extends androidx.core.widget.AutoScrollHelper {
+ ctor public ListViewAutoScrollHelper(android.widget.ListView);
+ method public boolean canTargetScrollHorizontally(int);
+ method public boolean canTargetScrollVertically(int);
+ method public void scrollTargetBy(int, int);
+ }
+
+ public final class ListViewCompat {
+ method public static boolean canScrollList(android.widget.ListView, int);
+ method public static void scrollListBy(android.widget.ListView, int);
+ }
+
+ public class NestedScrollView extends android.widget.FrameLayout implements androidx.core.view.NestedScrollingChild3 androidx.core.view.NestedScrollingParent3 androidx.core.view.ScrollingView {
+ ctor public NestedScrollView(android.content.Context);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?, int);
+ method public boolean arrowScroll(int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollRange();
+ method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollRange();
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public boolean executeKeyEvent(android.view.KeyEvent);
+ method public void fling(int);
+ method public boolean fullScroll(int);
+ method public int getMaxScrollAmount();
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean isFillViewport();
+ method public boolean isSmoothScrollingEnabled();
+ method public void onAttachedToWindow();
+ method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View, int);
+ method public boolean pageScroll(int);
+ method public void setFillViewport(boolean);
+ method public void setOnScrollChangeListener(androidx.core.widget.NestedScrollView.OnScrollChangeListener?);
+ method public void setSmoothScrollingEnabled(boolean);
+ method public final void smoothScrollBy(int, int);
+ method public final void smoothScrollBy(int, int, int);
+ method public final void smoothScrollTo(int, int);
+ method public final void smoothScrollTo(int, int, int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll(int);
+ }
+
+ public static interface NestedScrollView.OnScrollChangeListener {
+ method public void onScrollChange(androidx.core.widget.NestedScrollView, int, int, int, int);
+ }
+
+ public final class PopupMenuCompat {
+ method public static android.view.View.OnTouchListener? getDragToOpenListener(Object);
+ }
+
+ public final class PopupWindowCompat {
+ method public static boolean getOverlapAnchor(android.widget.PopupWindow);
+ method public static int getWindowLayoutType(android.widget.PopupWindow);
+ method public static void setOverlapAnchor(android.widget.PopupWindow, boolean);
+ method public static void setWindowLayoutType(android.widget.PopupWindow, int);
+ method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
+ }
+
+ @Deprecated public final class ScrollerCompat {
+ method @Deprecated public void abortAnimation();
+ method @Deprecated public boolean computeScrollOffset();
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!);
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!, android.view.animation.Interpolator!);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int, int, int);
+ method @Deprecated public float getCurrVelocity();
+ method @Deprecated public int getCurrX();
+ method @Deprecated public int getCurrY();
+ method @Deprecated public int getFinalX();
+ method @Deprecated public int getFinalY();
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean isOverScrolled();
+ method @Deprecated public void notifyHorizontalEdgeReached(int, int, int);
+ method @Deprecated public void notifyVerticalEdgeReached(int, int, int);
+ method @Deprecated public boolean springBack(int, int, int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int, int);
+ }
+
+ public final class TextViewCompat {
+ method public static int getAutoSizeMaxTextSize(android.widget.TextView);
+ method public static int getAutoSizeMinTextSize(android.widget.TextView);
+ method public static int getAutoSizeStepGranularity(android.widget.TextView);
+ method public static int[] getAutoSizeTextAvailableSizes(android.widget.TextView);
+ method public static int getAutoSizeTextType(android.widget.TextView);
+ method public static android.content.res.ColorStateList? getCompoundDrawableTintList(android.widget.TextView);
+ method public static android.graphics.PorterDuff.Mode? getCompoundDrawableTintMode(android.widget.TextView);
+ method public static android.graphics.drawable.Drawable![] getCompoundDrawablesRelative(android.widget.TextView);
+ method public static int getFirstBaselineToTopHeight(android.widget.TextView);
+ method public static int getLastBaselineToBottomHeight(android.widget.TextView);
+ method public static int getMaxLines(android.widget.TextView);
+ method public static int getMinLines(android.widget.TextView);
+ method public static androidx.core.text.PrecomputedTextCompat.Params getTextMetricsParams(android.widget.TextView);
+ method public static void setAutoSizeTextTypeUniformWithConfiguration(android.widget.TextView, int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeUniformWithPresetSizes(android.widget.TextView, int[], int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeWithDefaults(android.widget.TextView, int);
+ method public static void setCompoundDrawableTintList(android.widget.TextView, android.content.res.ColorStateList?);
+ method public static void setCompoundDrawableTintMode(android.widget.TextView, android.graphics.PorterDuff.Mode?);
+ method public static void setCompoundDrawablesRelative(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, @DrawableRes int, @DrawableRes int, @DrawableRes int, @DrawableRes int);
+ method public static void setCustomSelectionActionModeCallback(android.widget.TextView, android.view.ActionMode.Callback);
+ method public static void setFirstBaselineToTopHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLastBaselineToBottomHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLineHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setPrecomputedText(android.widget.TextView, androidx.core.text.PrecomputedTextCompat);
+ method public static void setTextAppearance(android.widget.TextView, @StyleRes int);
+ method public static void setTextMetricsParams(android.widget.TextView, androidx.core.text.PrecomputedTextCompat.Params);
+ field public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0; // 0x0
+ field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
+ }
+
+ public interface TintableCompoundButton {
+ method public android.content.res.ColorStateList? getSupportButtonTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
+ method public void setSupportButtonTintList(android.content.res.ColorStateList?);
+ method public void setSupportButtonTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ public interface TintableCompoundDrawablesView {
+ method public android.content.res.ColorStateList? getSupportCompoundDrawablesTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportCompoundDrawablesTintMode();
+ method public void setSupportCompoundDrawablesTintList(android.content.res.ColorStateList?);
+ method public void setSupportCompoundDrawablesTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+}
+
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index 2b431b6..a1e0e3c 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -3259,7 +3259,7 @@
method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
method public int getLiveRegion();
method public int getMaxTextLength();
- method public int getMinMillisBetweenContentChanges();
+ method public long getMinDurationBetweenContentChangesMillis();
method public int getMovementGranularities();
method public CharSequence! getPackageName();
method public CharSequence? getPaneTitle();
@@ -3345,7 +3345,7 @@
method public void setLiveRegion(int);
method public void setLongClickable(boolean);
method public void setMaxTextLength(int);
- method public void setMinMillisBetweenContentChanges(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
method public void setMovementGranularities(int);
method public void setMultiLine(boolean);
method public void setPackageName(CharSequence!);
diff --git a/core/core/api/res-1.10.0-beta01.txt b/core/core/api/res-1.10.0-beta01.txt
new file mode 100644
index 0000000..dd913d3
--- /dev/null
+++ b/core/core/api/res-1.10.0-beta01.txt
@@ -0,0 +1,21 @@
+attr alpha
+attr font
+attr fontProviderAuthority
+attr fontProviderCerts
+attr fontProviderFetchStrategy
+attr fontProviderFetchTimeout
+attr fontProviderPackage
+attr fontProviderQuery
+attr fontProviderSystemFontFamily
+attr fontStyle
+attr fontVariationSettings
+attr fontWeight
+attr lStar
+attr queryPatterns
+attr shortcutMatchRequired
+attr ttcIndex
+style TextAppearance_Compat_Notification
+style TextAppearance_Compat_Notification_Info
+style TextAppearance_Compat_Notification_Line2
+style TextAppearance_Compat_Notification_Time
+style TextAppearance_Compat_Notification_Title
diff --git a/core/core/api/restricted_1.10.0-beta01.txt b/core/core/api/restricted_1.10.0-beta01.txt
new file mode 100644
index 0000000..07bd416
--- /dev/null
+++ b/core/core/api/restricted_1.10.0-beta01.txt
@@ -0,0 +1,4438 @@
+// Signature format: 4.0
+package android.support.v4.os {
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ResultReceiver implements android.os.Parcelable {
+ ctor public ResultReceiver(android.os.Handler!);
+ method public int describeContents();
+ method protected void onReceiveResult(int, android.os.Bundle!);
+ method public void send(int, android.os.Bundle!);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.support.v4.os.ResultReceiver!>! CREATOR;
+ }
+
+}
+
+package androidx.core.accessibilityservice {
+
+ public final class AccessibilityServiceInfoCompat {
+ method public static String capabilityToString(int);
+ method public static String feedbackTypeToString(int);
+ method public static String? flagToString(int);
+ method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
+ method public static String? loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
+ field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
+ field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
+ field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
+ field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
+ field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
+ field public static final int FEEDBACK_BRAILLE = 32; // 0x20
+ field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
+ field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
+ field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
+ field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
+ }
+
+}
+
+package androidx.core.app {
+
+ public class ActivityCompat extends androidx.core.content.ContextCompat {
+ ctor protected ActivityCompat();
+ method public static void finishAffinity(android.app.Activity);
+ method public static void finishAfterTransition(android.app.Activity);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.app.ActivityCompat.PermissionCompatDelegate? getPermissionCompatDelegate();
+ method public static android.net.Uri? getReferrer(android.app.Activity);
+ method @Deprecated public static boolean invalidateOptionsMenu(android.app.Activity!);
+ method public static boolean isLaunchedFromBubble(android.app.Activity);
+ method public static void postponeEnterTransition(android.app.Activity);
+ method public static void recreate(android.app.Activity);
+ method public static androidx.core.view.DragAndDropPermissionsCompat? requestDragAndDropPermissions(android.app.Activity, android.view.DragEvent);
+ method public static void requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ method public static <T extends android.view.View> T requireViewById(android.app.Activity, @IdRes int);
+ method public static void setEnterSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setExitSharedElementCallback(android.app.Activity, androidx.core.app.SharedElementCallback?);
+ method public static void setLocusContext(android.app.Activity, androidx.core.content.LocusIdCompat?, android.os.Bundle?);
+ method public static void setPermissionCompatDelegate(androidx.core.app.ActivityCompat.PermissionCompatDelegate?);
+ method public static boolean shouldShowRequestPermissionRationale(android.app.Activity, String);
+ method public static void startActivityForResult(android.app.Activity, android.content.Intent, int, android.os.Bundle?);
+ method public static void startIntentSenderForResult(android.app.Activity, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public static void startPostponedEnterTransition(android.app.Activity);
+ }
+
+ public static interface ActivityCompat.OnRequestPermissionsResultCallback {
+ method public void onRequestPermissionsResult(int, String![], int[]);
+ }
+
+ public static interface ActivityCompat.PermissionCompatDelegate {
+ method public boolean onActivityResult(android.app.Activity, @IntRange(from=0) int, int, android.content.Intent?);
+ method public boolean requestPermissions(android.app.Activity, String![], @IntRange(from=0) int);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static interface ActivityCompat.RequestPermissionsRequestCodeValidator {
+ method public void validateRequestPermissionsRequestCode(int);
+ }
+
+ public final class ActivityManagerCompat {
+ method public static boolean isLowRamDevice(android.app.ActivityManager);
+ }
+
+ public class ActivityOptionsCompat {
+ ctor protected ActivityOptionsCompat();
+ method public android.graphics.Rect? getLaunchBounds();
+ method public static androidx.core.app.ActivityOptionsCompat makeBasic();
+ method public static androidx.core.app.ActivityOptionsCompat makeClipRevealAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeCustomAnimation(android.content.Context, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeScaleUpAnimation(android.view.View, int, int, int, int);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, android.view.View, String);
+ method public static androidx.core.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, androidx.core.util.Pair<android.view.View!,java.lang.String!>!...);
+ method public static androidx.core.app.ActivityOptionsCompat makeTaskLaunchBehind();
+ method public static androidx.core.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+ method public void requestUsageTimeReport(android.app.PendingIntent);
+ method public androidx.core.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect?);
+ method public android.os.Bundle? toBundle();
+ method public void update(androidx.core.app.ActivityOptionsCompat);
+ field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
+ field public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
+ }
+
+ public final class AlarmManagerCompat {
+ method public static void setAlarmClock(android.app.AlarmManager, long, android.app.PendingIntent, android.app.PendingIntent);
+ method public static void setAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExact(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ method public static void setExactAndAllowWhileIdle(android.app.AlarmManager, int, long, android.app.PendingIntent);
+ }
+
+ @RequiresApi(28) public class AppComponentFactory extends android.app.AppComponentFactory {
+ ctor public AppComponentFactory();
+ method public final android.app.Activity instantiateActivity(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Activity instantiateActivityCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Application instantiateApplication(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Application instantiateApplicationCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.ContentProvider instantiateProvider(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.ContentProvider instantiateProviderCompat(ClassLoader, String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.content.BroadcastReceiver instantiateReceiver(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.content.BroadcastReceiver instantiateReceiverCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public final android.app.Service instantiateService(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ method public android.app.Service instantiateServiceCompat(ClassLoader, String, android.content.Intent?) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+ }
+
+ public class AppLaunchChecker {
+ ctor @Deprecated public AppLaunchChecker();
+ method public static boolean hasStartedFromLauncher(android.content.Context);
+ method public static void onActivityCreate(android.app.Activity);
+ }
+
+ public final class AppOpsManagerCompat {
+ method public static int checkOrNoteProxyOp(android.content.Context, int, String, String);
+ method public static int noteOp(android.content.Context, String, int, String);
+ method public static int noteOpNoThrow(android.content.Context, String, int, String);
+ method public static int noteProxyOp(android.content.Context, String, String);
+ method public static int noteProxyOpNoThrow(android.content.Context, String, String);
+ method public static String? permissionToOp(String);
+ field public static final int MODE_ALLOWED = 0; // 0x0
+ field public static final int MODE_DEFAULT = 3; // 0x3
+ field public static final int MODE_ERRORED = 2; // 0x2
+ field public static final int MODE_IGNORED = 1; // 0x1
+ }
+
+ public final class BundleCompat {
+ method public static android.os.IBinder? getBinder(android.os.Bundle, String?);
+ method public static void putBinder(android.os.Bundle, String?, android.os.IBinder?);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ComponentActivity extends android.app.Activity implements androidx.core.view.KeyEventDispatcher.Component androidx.lifecycle.LifecycleOwner {
+ ctor public ComponentActivity();
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T extends androidx.core.app.ComponentActivity.ExtraData> T! getExtraData(Class<T!>!);
+ method public androidx.lifecycle.Lifecycle getLifecycle();
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void putExtraData(androidx.core.app.ComponentActivity.ExtraData!);
+ method protected final boolean shouldDumpInternalState(String![]?);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean superDispatchKeyEvent(android.view.KeyEvent);
+ }
+
+ @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static class ComponentActivity.ExtraData {
+ ctor @Deprecated public ComponentActivity.ExtraData();
+ }
+
+ @RequiresApi(api=28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class CoreComponentFactory extends android.app.AppComponentFactory {
+ ctor public CoreComponentFactory();
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static interface CoreComponentFactory.CompatWrapped {
+ method public Object! getWrapper();
+ }
+
+ public class DialogCompat {
+ method public static android.view.View requireViewById(android.app.Dialog, int);
+ }
+
+ public class FrameMetricsAggregator {
+ ctor public FrameMetricsAggregator();
+ ctor public FrameMetricsAggregator(@androidx.core.app.FrameMetricsAggregator.MetricType int);
+ method public void add(android.app.Activity);
+ method public android.util.SparseIntArray![]? getMetrics();
+ method public android.util.SparseIntArray![]? remove(android.app.Activity);
+ method public android.util.SparseIntArray![]? reset();
+ method public android.util.SparseIntArray![]? stop();
+ field public static final int ANIMATION_DURATION = 256; // 0x100
+ field public static final int ANIMATION_INDEX = 8; // 0x8
+ field public static final int COMMAND_DURATION = 32; // 0x20
+ field public static final int COMMAND_INDEX = 5; // 0x5
+ field public static final int DELAY_DURATION = 128; // 0x80
+ field public static final int DELAY_INDEX = 7; // 0x7
+ field public static final int DRAW_DURATION = 8; // 0x8
+ field public static final int DRAW_INDEX = 3; // 0x3
+ field public static final int EVERY_DURATION = 511; // 0x1ff
+ field public static final int INPUT_DURATION = 2; // 0x2
+ field public static final int INPUT_INDEX = 1; // 0x1
+ field public static final int LAYOUT_MEASURE_DURATION = 4; // 0x4
+ field public static final int LAYOUT_MEASURE_INDEX = 2; // 0x2
+ field public static final int SWAP_DURATION = 64; // 0x40
+ field public static final int SWAP_INDEX = 6; // 0x6
+ field public static final int SYNC_DURATION = 16; // 0x10
+ field public static final int SYNC_INDEX = 4; // 0x4
+ field public static final int TOTAL_DURATION = 1; // 0x1
+ field public static final int TOTAL_INDEX = 0; // 0x0
+ }
+
+ @IntDef(flag=true, value={androidx.core.app.FrameMetricsAggregator.TOTAL_DURATION, androidx.core.app.FrameMetricsAggregator.INPUT_DURATION, androidx.core.app.FrameMetricsAggregator.LAYOUT_MEASURE_DURATION, androidx.core.app.FrameMetricsAggregator.DRAW_DURATION, androidx.core.app.FrameMetricsAggregator.SYNC_DURATION, androidx.core.app.FrameMetricsAggregator.COMMAND_DURATION, androidx.core.app.FrameMetricsAggregator.SWAP_DURATION, androidx.core.app.FrameMetricsAggregator.DELAY_DURATION, androidx.core.app.FrameMetricsAggregator.ANIMATION_DURATION, androidx.core.app.FrameMetricsAggregator.EVERY_DURATION}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface FrameMetricsAggregator.MetricType {
+ }
+
+ @Deprecated public abstract class JobIntentService extends android.app.Service {
+ ctor @Deprecated public JobIntentService();
+ method @Deprecated public static void enqueueWork(android.content.Context, Class<?>, int, android.content.Intent);
+ method @Deprecated public static void enqueueWork(android.content.Context, android.content.ComponentName, int, android.content.Intent);
+ method @Deprecated public boolean isStopped();
+ method @Deprecated public android.os.IBinder! onBind(android.content.Intent);
+ method @Deprecated protected abstract void onHandleWork(android.content.Intent);
+ method @Deprecated public boolean onStopCurrentWork();
+ method @Deprecated public void setInterruptIfStopped(boolean);
+ }
+
+ public final class LocaleManagerCompat {
+ method @AnyThread public static androidx.core.os.LocaleListCompat getSystemLocales(android.content.Context);
+ }
+
+ public final class MultiWindowModeChangedInfo {
+ ctor public MultiWindowModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public MultiWindowModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInMultiWindowMode();
+ }
+
+ public final class NavUtils {
+ method public static android.content.Intent? getParentActivityIntent(android.app.Activity);
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, Class<?>) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static android.content.Intent? getParentActivityIntent(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static String? getParentActivityName(android.app.Activity);
+ method public static String? getParentActivityName(android.content.Context, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void navigateUpFromSameTask(android.app.Activity);
+ method public static void navigateUpTo(android.app.Activity, android.content.Intent);
+ method public static boolean shouldUpRecreateTask(android.app.Activity, android.content.Intent);
+ field public static final String PARENT_ACTIVITY = "android.support.PARENT_ACTIVITY";
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface NotificationBuilderWithBuilderAccessor {
+ method public android.app.Notification.Builder! getBuilder();
+ }
+
+ public class NotificationChannelCompat {
+ method public boolean canBubble();
+ method public boolean canBypassDnd();
+ method public boolean canShowBadge();
+ method public android.media.AudioAttributes? getAudioAttributes();
+ method public String? getConversationId();
+ method public String? getDescription();
+ method public String? getGroup();
+ method public String getId();
+ method public int getImportance();
+ method public int getLightColor();
+ method @androidx.core.app.NotificationCompat.NotificationVisibility public int getLockscreenVisibility();
+ method public CharSequence? getName();
+ method public String? getParentChannelId();
+ method public android.net.Uri? getSound();
+ method public long[]? getVibrationPattern();
+ method public boolean isImportantConversation();
+ method public boolean shouldShowLights();
+ method public boolean shouldVibrate();
+ method public androidx.core.app.NotificationChannelCompat.Builder toBuilder();
+ field public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
+ }
+
+ public static class NotificationChannelCompat.Builder {
+ ctor public NotificationChannelCompat.Builder(String, int);
+ method public androidx.core.app.NotificationChannelCompat build();
+ method public androidx.core.app.NotificationChannelCompat.Builder setConversationId(String, String);
+ method public androidx.core.app.NotificationChannelCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setImportance(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightColor(int);
+ method public androidx.core.app.NotificationChannelCompat.Builder setLightsEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setName(CharSequence?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setShowBadge(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setSound(android.net.Uri?, android.media.AudioAttributes?);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationEnabled(boolean);
+ method public androidx.core.app.NotificationChannelCompat.Builder setVibrationPattern(long[]?);
+ }
+
+ public class NotificationChannelGroupCompat {
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getChannels();
+ method public String? getDescription();
+ method public String getId();
+ method public CharSequence? getName();
+ method public boolean isBlocked();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder toBuilder();
+ }
+
+ public static class NotificationChannelGroupCompat.Builder {
+ ctor public NotificationChannelGroupCompat.Builder(String);
+ method public androidx.core.app.NotificationChannelGroupCompat build();
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setDescription(String?);
+ method public androidx.core.app.NotificationChannelGroupCompat.Builder setName(CharSequence?);
+ }
+
+ public class NotificationCompat {
+ ctor @Deprecated public NotificationCompat();
+ method public static androidx.core.app.NotificationCompat.Action? getAction(android.app.Notification, int);
+ method public static int getActionCount(android.app.Notification);
+ method public static boolean getAllowSystemGeneratedContextualActions(android.app.Notification);
+ method public static boolean getAutoCancel(android.app.Notification);
+ method public static int getBadgeIconType(android.app.Notification);
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? getBubbleMetadata(android.app.Notification);
+ method public static String? getCategory(android.app.Notification);
+ method public static String? getChannelId(android.app.Notification);
+ method public static int getColor(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentInfo(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentText(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getContentTitle(android.app.Notification);
+ method public static android.os.Bundle? getExtras(android.app.Notification);
+ method public static String? getGroup(android.app.Notification);
+ method @androidx.core.app.NotificationCompat.GroupAlertBehavior public static int getGroupAlertBehavior(android.app.Notification);
+ method @RequiresApi(21) public static java.util.List<androidx.core.app.NotificationCompat.Action!> getInvisibleActions(android.app.Notification);
+ method public static boolean getLocalOnly(android.app.Notification);
+ method public static androidx.core.content.LocusIdCompat? getLocusId(android.app.Notification);
+ method public static boolean getOngoing(android.app.Notification);
+ method public static boolean getOnlyAlertOnce(android.app.Notification);
+ method public static java.util.List<androidx.core.app.Person!> getPeople(android.app.Notification);
+ method public static android.app.Notification? getPublicVersion(android.app.Notification);
+ method public static CharSequence? getSettingsText(android.app.Notification);
+ method public static String? getShortcutId(android.app.Notification);
+ method @RequiresApi(19) public static boolean getShowWhen(android.app.Notification);
+ method public static String? getSortKey(android.app.Notification);
+ method @RequiresApi(19) public static CharSequence? getSubText(android.app.Notification);
+ method public static long getTimeoutAfter(android.app.Notification);
+ method @RequiresApi(19) public static boolean getUsesChronometer(android.app.Notification);
+ method @androidx.core.app.NotificationCompat.NotificationVisibility public static int getVisibility(android.app.Notification);
+ method public static boolean isGroupSummary(android.app.Notification);
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
+ field public static final String CATEGORY_ALARM = "alarm";
+ field public static final String CATEGORY_CALL = "call";
+ field public static final String CATEGORY_EMAIL = "email";
+ field public static final String CATEGORY_ERROR = "err";
+ field public static final String CATEGORY_EVENT = "event";
+ field public static final String CATEGORY_LOCATION_SHARING = "location_sharing";
+ field public static final String CATEGORY_MESSAGE = "msg";
+ field public static final String CATEGORY_MISSED_CALL = "missed_call";
+ field public static final String CATEGORY_NAVIGATION = "navigation";
+ field public static final String CATEGORY_PROGRESS = "progress";
+ field public static final String CATEGORY_PROMO = "promo";
+ field public static final String CATEGORY_RECOMMENDATION = "recommendation";
+ field public static final String CATEGORY_REMINDER = "reminder";
+ field public static final String CATEGORY_SERVICE = "service";
+ field public static final String CATEGORY_SOCIAL = "social";
+ field public static final String CATEGORY_STATUS = "status";
+ field public static final String CATEGORY_STOPWATCH = "stopwatch";
+ field public static final String CATEGORY_SYSTEM = "sys";
+ field public static final String CATEGORY_TRANSPORT = "transport";
+ field public static final String CATEGORY_WORKOUT = "workout";
+ field @ColorInt public static final int COLOR_DEFAULT = 0; // 0x0
+ field public static final int DEFAULT_ALL = -1; // 0xffffffff
+ field public static final int DEFAULT_LIGHTS = 4; // 0x4
+ field public static final int DEFAULT_SOUND = 1; // 0x1
+ field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
+ field public static final String EXTRA_ANSWER_INTENT = "android.answerIntent";
+ field public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
+ field public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
+ field public static final String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final String EXTRA_CALL_IS_VIDEO = "android.callIsVideo";
+ field public static final String EXTRA_CALL_PERSON = "android.callPerson";
+ field public static final String EXTRA_CALL_PERSON_COMPAT = "android.callPersonCompat";
+ field public static final String EXTRA_CALL_TYPE = "android.callType";
+ field public static final String EXTRA_CHANNEL_GROUP_ID = "android.intent.extra.CHANNEL_GROUP_ID";
+ field public static final String EXTRA_CHANNEL_ID = "android.intent.extra.CHANNEL_ID";
+ field public static final String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+ field public static final String EXTRA_COLORIZED = "android.colorized";
+ field public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
+ field public static final String EXTRA_COMPAT_TEMPLATE = "androidx.core.app.extra.COMPAT_TEMPLATE";
+ field public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
+ field public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
+ field public static final String EXTRA_DECLINE_INTENT = "android.declineIntent";
+ field public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
+ field public static final String EXTRA_HIDDEN_CONVERSATION_TITLE = "android.hiddenConversationTitle";
+ field public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
+ field public static final String EXTRA_INFO_TEXT = "android.infoText";
+ field public static final String EXTRA_IS_GROUP_CONVERSATION = "android.isGroupConversation";
+ field public static final String EXTRA_LARGE_ICON = "android.largeIcon";
+ field public static final String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
+ field public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final String EXTRA_MESSAGES = "android.messages";
+ field public static final String EXTRA_MESSAGING_STYLE_USER = "android.messagingStyleUser";
+ field public static final String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
+ field public static final String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
+ field @Deprecated public static final String EXTRA_PEOPLE = "android.people";
+ field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
+ field public static final String EXTRA_PICTURE = "android.picture";
+ field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
+ field public static final String EXTRA_PICTURE_ICON = "android.pictureIcon";
+ field public static final String EXTRA_PROGRESS = "android.progress";
+ field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
+ field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
+ field public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+ field public static final String EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED = "android.showBigPictureWhenCollapsed";
+ field public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
+ field public static final String EXTRA_SHOW_WHEN = "android.showWhen";
+ field public static final String EXTRA_SMALL_ICON = "android.icon";
+ field public static final String EXTRA_SUB_TEXT = "android.subText";
+ field public static final String EXTRA_SUMMARY_TEXT = "android.summaryText";
+ field public static final String EXTRA_TEMPLATE = "android.template";
+ field public static final String EXTRA_TEXT = "android.text";
+ field public static final String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final String EXTRA_TITLE = "android.title";
+ field public static final String EXTRA_TITLE_BIG = "android.title.big";
+ field public static final String EXTRA_VERIFICATION_ICON = "android.verificationIcon";
+ field public static final String EXTRA_VERIFICATION_ICON_COMPAT = "android.verificationIconCompat";
+ field public static final String EXTRA_VERIFICATION_TEXT = "android.verificationText";
+ field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
+ field public static final int FLAG_BUBBLE = 4096; // 0x1000
+ field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+ field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
+ field @Deprecated public static final int FLAG_HIGH_PRIORITY = 128; // 0x80
+ field public static final int FLAG_INSISTENT = 4; // 0x4
+ field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
+ field public static final int FLAG_NO_CLEAR = 32; // 0x20
+ field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
+ field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
+ field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
+ field public static final int FOREGROUND_SERVICE_DEFAULT = 0; // 0x0
+ field public static final int FOREGROUND_SERVICE_DEFERRED = 2; // 0x2
+ field public static final int FOREGROUND_SERVICE_IMMEDIATE = 1; // 0x1
+ field public static final int GROUP_ALERT_ALL = 0; // 0x0
+ field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2
+ field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1
+ field public static final String GROUP_KEY_SILENT = "silent";
+ field public static final String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final int MAX_ACTION_BUTTONS = 3; // 0x3
+ field public static final int PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int PRIORITY_HIGH = 1; // 0x1
+ field public static final int PRIORITY_LOW = -1; // 0xffffffff
+ field public static final int PRIORITY_MAX = 2; // 0x2
+ field public static final int PRIORITY_MIN = -2; // 0xfffffffe
+ field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+ field public static final int VISIBILITY_PRIVATE = 0; // 0x0
+ field public static final int VISIBILITY_PUBLIC = 1; // 0x1
+ field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
+ }
+
+ public static class NotificationCompat.Action {
+ ctor public NotificationCompat.Action(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ method public android.app.PendingIntent? getActionIntent();
+ method public boolean getAllowGeneratedReplies();
+ method public androidx.core.app.RemoteInput![]? getDataOnlyRemoteInputs();
+ method public android.os.Bundle getExtras();
+ method @Deprecated public int getIcon();
+ method public androidx.core.graphics.drawable.IconCompat? getIconCompat();
+ method public androidx.core.app.RemoteInput![]? getRemoteInputs();
+ method @androidx.core.app.NotificationCompat.Action.SemanticAction public int getSemanticAction();
+ method public boolean getShowsUserInterface();
+ method public CharSequence? getTitle();
+ method public boolean isAuthenticationRequired();
+ method public boolean isContextual();
+ field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
+ field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa
+ field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
+ field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
+ field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
+ field public static final int SEMANTIC_ACTION_MUTE = 6; // 0x6
+ field public static final int SEMANTIC_ACTION_NONE = 0; // 0x0
+ field public static final int SEMANTIC_ACTION_REPLY = 1; // 0x1
+ field public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9; // 0x9
+ field public static final int SEMANTIC_ACTION_THUMBS_UP = 8; // 0x8
+ field public static final int SEMANTIC_ACTION_UNMUTE = 7; // 0x7
+ field public android.app.PendingIntent? actionIntent;
+ field @Deprecated public int icon;
+ field public CharSequence! title;
+ }
+
+ public static final class NotificationCompat.Action.Builder {
+ ctor public NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat?, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(int, CharSequence?, android.app.PendingIntent?);
+ ctor public NotificationCompat.Action.Builder(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.Builder addExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Action.Builder addRemoteInput(androidx.core.app.RemoteInput?);
+ method public androidx.core.app.NotificationCompat.Action build();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Extender);
+ method @RequiresApi(19) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.app.NotificationCompat.Action.Builder fromAndroidAction(android.app.Notification.Action);
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.NotificationCompat.Action.Builder setAllowGeneratedReplies(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setAuthenticationRequired(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setContextual(boolean);
+ method public androidx.core.app.NotificationCompat.Action.Builder setSemanticAction(@androidx.core.app.NotificationCompat.Action.SemanticAction int);
+ method public androidx.core.app.NotificationCompat.Action.Builder setShowsUserInterface(boolean);
+ }
+
+ public static interface NotificationCompat.Action.Extender {
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_NONE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_REPLY, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_UNREAD, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_DELETE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_MUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_UNMUTE, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_UP, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_THUMBS_DOWN, androidx.core.app.NotificationCompat.Action.SEMANTIC_ACTION_CALL}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.Action.SemanticAction {
+ }
+
+ public static final class NotificationCompat.Action.WearableExtender implements androidx.core.app.NotificationCompat.Action.Extender {
+ ctor public NotificationCompat.Action.WearableExtender();
+ ctor public NotificationCompat.Action.WearableExtender(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Action.Builder extend(androidx.core.app.NotificationCompat.Action.Builder);
+ method @Deprecated public CharSequence? getCancelLabel();
+ method @Deprecated public CharSequence? getConfirmLabel();
+ method public boolean getHintDisplayActionInline();
+ method public boolean getHintLaunchesActivity();
+ method @Deprecated public CharSequence? getInProgressLabel();
+ method public boolean isAvailableOffline();
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setCancelLabel(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setConfirmLabel(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintDisplayActionInline(boolean);
+ method public androidx.core.app.NotificationCompat.Action.WearableExtender setHintLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.Action.WearableExtender setInProgressLabel(CharSequence?);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.BADGE_ICON_NONE, androidx.core.app.NotificationCompat.BADGE_ICON_SMALL, androidx.core.app.NotificationCompat.BADGE_ICON_LARGE}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.BadgeIconType {
+ }
+
+ public static class NotificationCompat.BigPictureStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigPictureStyle();
+ ctor public NotificationCompat.BigPictureStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.Bitmap?);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.Bitmap?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle bigPicture(android.graphics.drawable.Icon?);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.graphics.drawable.IconCompat? getPictureIcon(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setBigContentTitle(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle setContentDescription(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigPictureStyle setSummaryText(CharSequence?);
+ method @RequiresApi(31) public androidx.core.app.NotificationCompat.BigPictureStyle showBigPictureWhenCollapsed(boolean);
+ }
+
+ public static class NotificationCompat.BigTextStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.BigTextStyle();
+ ctor public NotificationCompat.BigTextStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle bigText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.BigTextStyle setSummaryText(CharSequence?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata {
+ method public static androidx.core.app.NotificationCompat.BubbleMetadata? fromPlatform(android.app.Notification.BubbleMetadata?);
+ method public boolean getAutoExpandBubble();
+ method public android.app.PendingIntent? getDeleteIntent();
+ method @Dimension(unit=androidx.annotation.Dimension.DP) public int getDesiredHeight();
+ method @DimenRes public int getDesiredHeightResId();
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public android.app.PendingIntent? getIntent();
+ method public String? getShortcutId();
+ method public boolean isNotificationSuppressed();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setFlags(int);
+ method public static android.app.Notification.BubbleMetadata? toPlatform(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ }
+
+ public static final class NotificationCompat.BubbleMetadata.Builder {
+ ctor @Deprecated public NotificationCompat.BubbleMetadata.Builder();
+ ctor @RequiresApi(30) public NotificationCompat.BubbleMetadata.Builder(String);
+ ctor public NotificationCompat.BubbleMetadata.Builder(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata build();
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeight(@Dimension(unit=androidx.annotation.Dimension.DP) int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
+ method public androidx.core.app.NotificationCompat.BubbleMetadata.Builder setSuppressNotification(boolean);
+ }
+
+ public static class NotificationCompat.Builder {
+ ctor @RequiresApi(19) public NotificationCompat.Builder(android.content.Context, android.app.Notification);
+ ctor public NotificationCompat.Builder(android.content.Context, String);
+ ctor @Deprecated public NotificationCompat.Builder(android.content.Context);
+ method public androidx.core.app.NotificationCompat.Builder addAction(int, CharSequence?, android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder addAction(androidx.core.app.NotificationCompat.Action?);
+ method public androidx.core.app.NotificationCompat.Builder addExtras(android.os.Bundle?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(int, CharSequence?, android.app.PendingIntent?);
+ method @RequiresApi(21) public androidx.core.app.NotificationCompat.Builder addInvisibleAction(androidx.core.app.NotificationCompat.Action?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder addPerson(String?);
+ method public androidx.core.app.NotificationCompat.Builder addPerson(androidx.core.app.Person?);
+ method public android.app.Notification build();
+ method public androidx.core.app.NotificationCompat.Builder clearActions();
+ method public androidx.core.app.NotificationCompat.Builder clearInvisibleActions();
+ method public androidx.core.app.NotificationCompat.Builder clearPeople();
+ method public android.widget.RemoteViews? createBigContentView();
+ method public android.widget.RemoteViews? createContentView();
+ method public android.widget.RemoteViews? createHeadsUpContentView();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Extender);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! getBigContentView();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.core.app.NotificationCompat.BubbleMetadata? getBubbleMetadata();
+ method @ColorInt @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getColor();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! getContentView();
+ method public android.os.Bundle getExtras();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getForegroundServiceBehavior();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! getHeadsUpContentView();
+ method @Deprecated public android.app.Notification getNotification();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getPriority();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public long getWhenIfShowing();
+ method protected static CharSequence? limitCharSequenceLength(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setAllowSystemGeneratedContextualActions(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setAutoCancel(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setBadgeIconType(@androidx.core.app.NotificationCompat.BadgeIconType int);
+ method public androidx.core.app.NotificationCompat.Builder setBubbleMetadata(androidx.core.app.NotificationCompat.BubbleMetadata?);
+ method public androidx.core.app.NotificationCompat.Builder setCategory(String?);
+ method public androidx.core.app.NotificationCompat.Builder setChannelId(String);
+ method @RequiresApi(24) public androidx.core.app.NotificationCompat.Builder setChronometerCountDown(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.Builder setColorized(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setContent(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setContentInfo(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setContentText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomBigContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setCustomHeadsUpContentView(android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setDefaults(int);
+ method public androidx.core.app.NotificationCompat.Builder setDeleteIntent(android.app.PendingIntent?);
+ method public androidx.core.app.NotificationCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.app.NotificationCompat.Builder setForegroundServiceBehavior(@androidx.core.app.NotificationCompat.ServiceNotificationBehavior int);
+ method public androidx.core.app.NotificationCompat.Builder setFullScreenIntent(android.app.PendingIntent?, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setGroup(String?);
+ method public androidx.core.app.NotificationCompat.Builder setGroupAlertBehavior(@androidx.core.app.NotificationCompat.GroupAlertBehavior int);
+ method public androidx.core.app.NotificationCompat.Builder setGroupSummary(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLargeIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.Builder setLights(@ColorInt int, int, int);
+ method public androidx.core.app.NotificationCompat.Builder setLocalOnly(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setNotificationSilent();
+ method public androidx.core.app.NotificationCompat.Builder setNumber(int);
+ method public androidx.core.app.NotificationCompat.Builder setOngoing(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setOnlyAlertOnce(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPriority(int);
+ method public androidx.core.app.NotificationCompat.Builder setProgress(int, int, boolean);
+ method public androidx.core.app.NotificationCompat.Builder setPublicVersion(android.app.Notification?);
+ method public androidx.core.app.NotificationCompat.Builder setRemoteInputHistory(CharSequence![]?);
+ method public androidx.core.app.NotificationCompat.Builder setSettingsText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutId(String?);
+ method public androidx.core.app.NotificationCompat.Builder setShortcutInfo(androidx.core.content.pm.ShortcutInfoCompat?);
+ method public androidx.core.app.NotificationCompat.Builder setShowWhen(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setSilent(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.Builder setSmallIcon(androidx.core.graphics.drawable.IconCompat);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int);
+ method public androidx.core.app.NotificationCompat.Builder setSmallIcon(int, int);
+ method public androidx.core.app.NotificationCompat.Builder setSortKey(String?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?);
+ method public androidx.core.app.NotificationCompat.Builder setSound(android.net.Uri?, @androidx.core.app.NotificationCompat.StreamType int);
+ method public androidx.core.app.NotificationCompat.Builder setStyle(androidx.core.app.NotificationCompat.Style?);
+ method public androidx.core.app.NotificationCompat.Builder setSubText(CharSequence?);
+ method public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?);
+ method @Deprecated public androidx.core.app.NotificationCompat.Builder setTicker(CharSequence?, android.widget.RemoteViews?);
+ method public androidx.core.app.NotificationCompat.Builder setTimeoutAfter(long);
+ method public androidx.core.app.NotificationCompat.Builder setUsesChronometer(boolean);
+ method public androidx.core.app.NotificationCompat.Builder setVibrate(long[]?);
+ method public androidx.core.app.NotificationCompat.Builder setVisibility(@androidx.core.app.NotificationCompat.NotificationVisibility int);
+ method public androidx.core.app.NotificationCompat.Builder setWhen(long);
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public java.util.ArrayList<androidx.core.app.NotificationCompat.Action!>! mActions;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.Context! mContext;
+ field @Deprecated public java.util.ArrayList<java.lang.String!>! mPeople;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public java.util.ArrayList<androidx.core.app.Person!> mPersonList;
+ }
+
+ public static class NotificationCompat.CallStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.CallStyle();
+ ctor public NotificationCompat.CallStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public static androidx.core.app.NotificationCompat.CallStyle forIncomingCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forOngoingCall(androidx.core.app.Person, android.app.PendingIntent);
+ method public static androidx.core.app.NotificationCompat.CallStyle forScreeningCall(androidx.core.app.Person, android.app.PendingIntent, android.app.PendingIntent);
+ method @RequiresApi(20) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public java.util.ArrayList<androidx.core.app.NotificationCompat.Action!> getActionsListWithSystemActions();
+ method public androidx.core.app.NotificationCompat.CallStyle setAnswerButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setDeclineButtonColorHint(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CallStyle setIsVideo(boolean);
+ method @RequiresApi(23) public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.drawable.Icon?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationIcon(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.CallStyle setVerificationText(CharSequence?);
+ field public static final int CALL_TYPE_INCOMING = 1; // 0x1
+ field public static final int CALL_TYPE_ONGOING = 2; // 0x2
+ field public static final int CALL_TYPE_SCREENING = 3; // 0x3
+ field public static final int CALL_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.CallStyle.CALL_TYPE_UNKNOWN, androidx.core.app.NotificationCompat.CallStyle.CALL_TYPE_INCOMING, androidx.core.app.NotificationCompat.CallStyle.CALL_TYPE_ONGOING, androidx.core.app.NotificationCompat.CallStyle.CALL_TYPE_SCREENING}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.CallStyle.CallType {
+ }
+
+ public static final class NotificationCompat.CarExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.CarExtender();
+ ctor public NotificationCompat.CarExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method @ColorInt public int getColor();
+ method public android.graphics.Bitmap? getLargeIcon();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation? getUnreadConversation();
+ method public androidx.core.app.NotificationCompat.CarExtender setColor(@ColorInt int);
+ method public androidx.core.app.NotificationCompat.CarExtender setLargeIcon(android.graphics.Bitmap?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender setUnreadConversation(androidx.core.app.NotificationCompat.CarExtender.UnreadConversation?);
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation {
+ method @Deprecated public long getLatestTimestamp();
+ method @Deprecated public String![]? getMessages();
+ method @Deprecated public String? getParticipant();
+ method @Deprecated public String![]? getParticipants();
+ method @Deprecated public android.app.PendingIntent? getReadPendingIntent();
+ method @Deprecated public androidx.core.app.RemoteInput? getRemoteInput();
+ method @Deprecated public android.app.PendingIntent? getReplyPendingIntent();
+ }
+
+ @Deprecated public static class NotificationCompat.CarExtender.UnreadConversation.Builder {
+ ctor @Deprecated public NotificationCompat.CarExtender.UnreadConversation.Builder(String);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder addMessage(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation build();
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setLatestTimestamp(long);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReadPendingIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.CarExtender.UnreadConversation.Builder setReplyAction(android.app.PendingIntent?, androidx.core.app.RemoteInput?);
+ }
+
+ public static class NotificationCompat.DecoratedCustomViewStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.DecoratedCustomViewStyle();
+ }
+
+ public static interface NotificationCompat.Extender {
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.GROUP_ALERT_ALL, androidx.core.app.NotificationCompat.GROUP_ALERT_SUMMARY, androidx.core.app.NotificationCompat.GROUP_ALERT_CHILDREN}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.GroupAlertBehavior {
+ }
+
+ public static class NotificationCompat.InboxStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor public NotificationCompat.InboxStyle();
+ ctor public NotificationCompat.InboxStyle(androidx.core.app.NotificationCompat.Builder?);
+ method public androidx.core.app.NotificationCompat.InboxStyle addLine(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setBigContentTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.InboxStyle setSummaryText(CharSequence?);
+ }
+
+ public static class NotificationCompat.MessagingStyle extends androidx.core.app.NotificationCompat.Style {
+ ctor @Deprecated public NotificationCompat.MessagingStyle(CharSequence);
+ ctor public NotificationCompat.MessagingStyle(androidx.core.app.Person);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addHistoricMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method @Deprecated public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(CharSequence?, long, androidx.core.app.Person?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle addMessage(androidx.core.app.NotificationCompat.MessagingStyle.Message?);
+ method public static androidx.core.app.NotificationCompat.MessagingStyle? extractMessagingStyleFromNotification(android.app.Notification);
+ method public CharSequence? getConversationTitle();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getHistoricMessages();
+ method public java.util.List<androidx.core.app.NotificationCompat.MessagingStyle.Message!> getMessages();
+ method public androidx.core.app.Person getUser();
+ method @Deprecated public CharSequence? getUserDisplayName();
+ method public boolean isGroupConversation();
+ method public androidx.core.app.NotificationCompat.MessagingStyle setConversationTitle(CharSequence?);
+ method public androidx.core.app.NotificationCompat.MessagingStyle setGroupConversation(boolean);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class NotificationCompat.MessagingStyle.Message {
+ ctor public NotificationCompat.MessagingStyle.Message(CharSequence?, long, androidx.core.app.Person?);
+ ctor @Deprecated public NotificationCompat.MessagingStyle.Message(CharSequence?, long, CharSequence?);
+ method public String? getDataMimeType();
+ method public android.net.Uri? getDataUri();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.Person? getPerson();
+ method @Deprecated public CharSequence? getSender();
+ method public CharSequence? getText();
+ method public long getTimestamp();
+ method public androidx.core.app.NotificationCompat.MessagingStyle.Message setData(String?, android.net.Uri?);
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.VISIBILITY_PUBLIC, androidx.core.app.NotificationCompat.VISIBILITY_PRIVATE, androidx.core.app.NotificationCompat.VISIBILITY_SECRET}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.NotificationVisibility {
+ }
+
+ @IntDef({androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_DEFAULT, androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE, androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_DEFERRED}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.ServiceNotificationBehavior {
+ }
+
+ @IntDef({android.media.AudioManager.STREAM_VOICE_CALL, android.media.AudioManager.STREAM_SYSTEM, android.media.AudioManager.STREAM_RING, android.media.AudioManager.STREAM_MUSIC, android.media.AudioManager.STREAM_ALARM, android.media.AudioManager.STREAM_NOTIFICATION, android.media.AudioManager.STREAM_DTMF, android.media.AudioManager.STREAM_ACCESSIBILITY}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NotificationCompat.StreamType {
+ }
+
+ public abstract static class NotificationCompat.Style {
+ ctor public NotificationCompat.Style();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void addCompatExtras(android.os.Bundle);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void apply(androidx.core.app.NotificationBuilderWithBuilderAccessor!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews applyStandardTemplate(boolean, int, boolean);
+ method public android.app.Notification? build();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void buildIntoRemoteViews(android.widget.RemoteViews!, android.widget.RemoteViews!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected void clearCompatExtraKeys(android.os.Bundle);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.Bitmap! createColoredBitmap(int, int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean displayCustomViewInline();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.app.NotificationCompat.Style? extractStyleFromNotification(android.app.Notification);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected String? getClassName();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! makeBigContentView(androidx.core.app.NotificationBuilderWithBuilderAccessor!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! makeContentView(androidx.core.app.NotificationBuilderWithBuilderAccessor!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.widget.RemoteViews! makeHeadsUpContentView(androidx.core.app.NotificationBuilderWithBuilderAccessor!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected void restoreFromCompatExtras(android.os.Bundle);
+ method public void setBuilder(androidx.core.app.NotificationCompat.Builder?);
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected androidx.core.app.NotificationCompat.Builder! mBuilder;
+ }
+
+ public static final class NotificationCompat.WearableExtender implements androidx.core.app.NotificationCompat.Extender {
+ ctor public NotificationCompat.WearableExtender();
+ ctor public NotificationCompat.WearableExtender(android.app.Notification);
+ method public androidx.core.app.NotificationCompat.WearableExtender addAction(androidx.core.app.NotificationCompat.Action);
+ method public androidx.core.app.NotificationCompat.WearableExtender addActions(java.util.List<androidx.core.app.NotificationCompat.Action!>);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPage(android.app.Notification);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender addPages(java.util.List<android.app.Notification!>);
+ method public androidx.core.app.NotificationCompat.WearableExtender clearActions();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender clearPages();
+ method public androidx.core.app.NotificationCompat.WearableExtender clone();
+ method public androidx.core.app.NotificationCompat.Builder extend(androidx.core.app.NotificationCompat.Builder);
+ method public java.util.List<androidx.core.app.NotificationCompat.Action!> getActions();
+ method @Deprecated public android.graphics.Bitmap? getBackground();
+ method public String? getBridgeTag();
+ method public int getContentAction();
+ method @Deprecated public int getContentIcon();
+ method @Deprecated public int getContentIconGravity();
+ method public boolean getContentIntentAvailableOffline();
+ method @Deprecated public int getCustomContentHeight();
+ method @Deprecated public int getCustomSizePreset();
+ method public String? getDismissalId();
+ method @Deprecated public android.app.PendingIntent? getDisplayIntent();
+ method @Deprecated public int getGravity();
+ method @Deprecated public boolean getHintAmbientBigPicture();
+ method @Deprecated public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
+ method @Deprecated public boolean getHintHideIcon();
+ method @Deprecated public int getHintScreenTimeout();
+ method @Deprecated public boolean getHintShowBackgroundOnly();
+ method @Deprecated public java.util.List<android.app.Notification!> getPages();
+ method public boolean getStartScrollBottom();
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setBackground(android.graphics.Bitmap?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setBridgeTag(String?);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentAction(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIcon(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setContentIconGravity(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setContentIntentAvailableOffline(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomContentHeight(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setCustomSizePreset(int);
+ method public androidx.core.app.NotificationCompat.WearableExtender setDismissalId(String?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setDisplayIntent(android.app.PendingIntent?);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setGravity(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAmbientBigPicture(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setHintContentIntentLaunchesActivity(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintHideIcon(boolean);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintScreenTimeout(int);
+ method @Deprecated public androidx.core.app.NotificationCompat.WearableExtender setHintShowBackgroundOnly(boolean);
+ method public androidx.core.app.NotificationCompat.WearableExtender setStartScrollBottom(boolean);
+ field @Deprecated public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff
+ field @Deprecated public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0
+ field @Deprecated public static final int SIZE_DEFAULT = 0; // 0x0
+ field @Deprecated public static final int SIZE_FULL_SCREEN = 5; // 0x5
+ field @Deprecated public static final int SIZE_LARGE = 4; // 0x4
+ field @Deprecated public static final int SIZE_MEDIUM = 3; // 0x3
+ field @Deprecated public static final int SIZE_SMALL = 2; // 0x2
+ field @Deprecated public static final int SIZE_XSMALL = 1; // 0x1
+ field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+ }
+
+ public final class NotificationCompatExtras {
+ field public static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras";
+ field public static final String EXTRA_GROUP_KEY = "android.support.groupKey";
+ field public static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary";
+ field public static final String EXTRA_LOCAL_ONLY = "android.support.localOnly";
+ field public static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs";
+ field public static final String EXTRA_SORT_KEY = "android.support.sortKey";
+ }
+
+ public abstract class NotificationCompatSideChannelService extends android.app.Service {
+ ctor public NotificationCompatSideChannelService();
+ method public abstract void cancel(String!, int, String!);
+ method public abstract void cancelAll(String!);
+ method public abstract void notify(String!, int, String!, android.app.Notification!);
+ method public android.os.IBinder! onBind(android.content.Intent!);
+ }
+
+ public final class NotificationManagerCompat {
+ method public boolean areNotificationsEnabled();
+ method public void cancel(int);
+ method public void cancel(String?, int);
+ method public void cancelAll();
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(androidx.core.app.NotificationChannelCompat);
+ method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+ method public void createNotificationChannelGroup(androidx.core.app.NotificationChannelGroupCompat);
+ method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup!>);
+ method public void createNotificationChannelGroupsCompat(java.util.List<androidx.core.app.NotificationChannelGroupCompat!>);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel!>);
+ method public void createNotificationChannelsCompat(java.util.List<androidx.core.app.NotificationChannelCompat!>);
+ method public void deleteNotificationChannel(String);
+ method public void deleteNotificationChannelGroup(String);
+ method public void deleteUnlistedNotificationChannels(java.util.Collection<java.lang.String!>);
+ method public static androidx.core.app.NotificationManagerCompat from(android.content.Context);
+ method public static java.util.Set<java.lang.String!> getEnabledListenerPackages(android.content.Context);
+ method public int getImportance();
+ method public android.app.NotificationChannel? getNotificationChannel(String);
+ method public android.app.NotificationChannel? getNotificationChannel(String, String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String);
+ method public androidx.core.app.NotificationChannelCompat? getNotificationChannelCompat(String, String);
+ method public android.app.NotificationChannelGroup? getNotificationChannelGroup(String);
+ method public androidx.core.app.NotificationChannelGroupCompat? getNotificationChannelGroupCompat(String);
+ method public java.util.List<android.app.NotificationChannelGroup!> getNotificationChannelGroups();
+ method public java.util.List<androidx.core.app.NotificationChannelGroupCompat!> getNotificationChannelGroupsCompat();
+ method public java.util.List<android.app.NotificationChannel!> getNotificationChannels();
+ method public java.util.List<androidx.core.app.NotificationChannelCompat!> getNotificationChannelsCompat();
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(int, android.app.Notification);
+ method @RequiresPermission(android.Manifest.permission.POST_NOTIFICATIONS) public void notify(String?, int, android.app.Notification);
+ field public static final String ACTION_BIND_SIDE_CHANNEL = "android.support.BIND_NOTIFICATION_SIDE_CHANNEL";
+ field public static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
+ field public static final int IMPORTANCE_NONE = 0; // 0x0
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
+ }
+
+ public interface OnMultiWindowModeChangedProvider {
+ method public void addOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ method public void removeOnMultiWindowModeChangedListener(androidx.core.util.Consumer<androidx.core.app.MultiWindowModeChangedInfo!>);
+ }
+
+ public interface OnNewIntentProvider {
+ method public void addOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ method public void removeOnNewIntentListener(androidx.core.util.Consumer<android.content.Intent!>);
+ }
+
+ public interface OnPictureInPictureModeChangedProvider {
+ method public void addOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ method public void removeOnPictureInPictureModeChangedListener(androidx.core.util.Consumer<androidx.core.app.PictureInPictureModeChangedInfo!>);
+ }
+
+ public final class PendingIntentCompat {
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent![], int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle, boolean);
+ method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int, boolean);
+ method @RequiresApi(26) public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int, boolean);
+ method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int, boolean);
+ }
+
+ public class Person {
+ method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.app.Person fromAndroidPerson(android.app.Person);
+ method public static androidx.core.app.Person fromBundle(android.os.Bundle);
+ method @RequiresApi(22) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.app.Person fromPersistableBundle(android.os.PersistableBundle);
+ method public androidx.core.graphics.drawable.IconCompat? getIcon();
+ method public String? getKey();
+ method public CharSequence? getName();
+ method public String? getUri();
+ method public boolean isBot();
+ method public boolean isImportant();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public String resolveToLegacyUri();
+ method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.app.Person toAndroidPerson();
+ method public androidx.core.app.Person.Builder toBuilder();
+ method public android.os.Bundle toBundle();
+ method @RequiresApi(22) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.os.PersistableBundle toPersistableBundle();
+ }
+
+ public static class Person.Builder {
+ ctor public Person.Builder();
+ method public androidx.core.app.Person build();
+ method public androidx.core.app.Person.Builder setBot(boolean);
+ method public androidx.core.app.Person.Builder setIcon(androidx.core.graphics.drawable.IconCompat?);
+ method public androidx.core.app.Person.Builder setImportant(boolean);
+ method public androidx.core.app.Person.Builder setKey(String?);
+ method public androidx.core.app.Person.Builder setName(CharSequence?);
+ method public androidx.core.app.Person.Builder setUri(String?);
+ }
+
+ public final class PictureInPictureModeChangedInfo {
+ ctor public PictureInPictureModeChangedInfo(boolean);
+ ctor @RequiresApi(26) public PictureInPictureModeChangedInfo(boolean, android.content.res.Configuration);
+ method @RequiresApi(26) public android.content.res.Configuration getNewConfig();
+ method public boolean isInPictureInPictureMode();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(jetifyAs="android.support.v4.app.RemoteActionCompat") public final class RemoteActionCompat implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public RemoteActionCompat(androidx.core.graphics.drawable.IconCompat, CharSequence, CharSequence, android.app.PendingIntent);
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public RemoteActionCompat();
+ ctor public RemoteActionCompat(androidx.core.app.RemoteActionCompat);
+ method @RequiresApi(26) public static androidx.core.app.RemoteActionCompat createFromRemoteAction(android.app.RemoteAction);
+ method public android.app.PendingIntent getActionIntent();
+ method public CharSequence getContentDescription();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
+ method public CharSequence getTitle();
+ method public boolean isEnabled();
+ method public void setEnabled(boolean);
+ method public void setShouldShowIcon(boolean);
+ method public boolean shouldShowIcon();
+ method @RequiresApi(26) public android.app.RemoteAction toRemoteAction();
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(4) public android.app.PendingIntent mActionIntent;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(3) public CharSequence mContentDescription;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(5) public boolean mEnabled;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(1) public androidx.core.graphics.drawable.IconCompat mIcon;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(6) public boolean mShouldShowIcon;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(2) public CharSequence mTitle;
+ }
+
+ public final class RemoteInput {
+ method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+ method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
+ method public boolean getAllowFreeFormInput();
+ method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+ method public CharSequence![]? getChoices();
+ method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
+ method @androidx.core.app.RemoteInput.EditChoicesBeforeSending public int getEditChoicesBeforeSending();
+ method public android.os.Bundle getExtras();
+ method public CharSequence? getLabel();
+ method public String getResultKey();
+ method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
+ method @androidx.core.app.RemoteInput.Source public static int getResultsSource(android.content.Intent);
+ method public boolean isDataOnly();
+ method public static void setResultsSource(android.content.Intent, @androidx.core.app.RemoteInput.Source int);
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_AUTO = 0; // 0x0
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_DISABLED = 1; // 0x1
+ field public static final int EDIT_CHOICES_BEFORE_SENDING_ENABLED = 2; // 0x2
+ field public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+ field public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+ field public static final int SOURCE_CHOICE = 1; // 0x1
+ field public static final int SOURCE_FREE_FORM_INPUT = 0; // 0x0
+ }
+
+ public static final class RemoteInput.Builder {
+ ctor public RemoteInput.Builder(String);
+ method public androidx.core.app.RemoteInput.Builder addExtras(android.os.Bundle);
+ method public androidx.core.app.RemoteInput build();
+ method public android.os.Bundle getExtras();
+ method public androidx.core.app.RemoteInput.Builder setAllowDataType(String, boolean);
+ method public androidx.core.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+ method public androidx.core.app.RemoteInput.Builder setChoices(CharSequence![]?);
+ method public androidx.core.app.RemoteInput.Builder setEditChoicesBeforeSending(@androidx.core.app.RemoteInput.EditChoicesBeforeSending int);
+ method public androidx.core.app.RemoteInput.Builder setLabel(CharSequence?);
+ }
+
+ @IntDef({androidx.core.app.RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, androidx.core.app.RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, androidx.core.app.RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface RemoteInput.EditChoicesBeforeSending {
+ }
+
+ @IntDef({androidx.core.app.RemoteInput.SOURCE_FREE_FORM_INPUT, androidx.core.app.RemoteInput.SOURCE_CHOICE}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface RemoteInput.Source {
+ }
+
+ public final class ServiceCompat {
+ method public static void stopForeground(android.app.Service, @androidx.core.app.ServiceCompat.StopForegroundFlags int);
+ field public static final int START_STICKY = 1; // 0x1
+ field public static final int STOP_FOREGROUND_DETACH = 2; // 0x2
+ field public static final int STOP_FOREGROUND_REMOVE = 1; // 0x1
+ }
+
+ @IntDef(flag=true, value={androidx.core.app.ServiceCompat.STOP_FOREGROUND_REMOVE, androidx.core.app.ServiceCompat.STOP_FOREGROUND_DETACH}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ServiceCompat.StopForegroundFlags {
+ }
+
+ public final class ShareCompat {
+ method @Deprecated public static void configureMenuItem(android.view.MenuItem, androidx.core.app.ShareCompat.IntentBuilder);
+ method @Deprecated public static void configureMenuItem(android.view.Menu, @IdRes int, androidx.core.app.ShareCompat.IntentBuilder);
+ method public static android.content.ComponentName? getCallingActivity(android.app.Activity);
+ method public static String? getCallingPackage(android.app.Activity);
+ field public static final String EXTRA_CALLING_ACTIVITY = "androidx.core.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_ACTIVITY_INTEROP = "android.support.v4.app.EXTRA_CALLING_ACTIVITY";
+ field public static final String EXTRA_CALLING_PACKAGE = "androidx.core.app.EXTRA_CALLING_PACKAGE";
+ field public static final String EXTRA_CALLING_PACKAGE_INTEROP = "android.support.v4.app.EXTRA_CALLING_PACKAGE";
+ }
+
+ public static class ShareCompat.IntentBuilder {
+ ctor public ShareCompat.IntentBuilder(android.content.Context);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailBcc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailCc(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String);
+ method public androidx.core.app.ShareCompat.IntentBuilder addEmailTo(String![]);
+ method public androidx.core.app.ShareCompat.IntentBuilder addStream(android.net.Uri);
+ method public android.content.Intent createChooserIntent();
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentBuilder from(android.app.Activity);
+ method public android.content.Intent getIntent();
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setChooserTitle(@StringRes int);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailBcc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailCc(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setEmailTo(String![]?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setHtmlText(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setStream(android.net.Uri?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setSubject(String?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setText(CharSequence?);
+ method public androidx.core.app.ShareCompat.IntentBuilder setType(String?);
+ method public void startChooser();
+ }
+
+ public static class ShareCompat.IntentReader {
+ ctor public ShareCompat.IntentReader(android.app.Activity);
+ ctor public ShareCompat.IntentReader(android.content.Context, android.content.Intent);
+ method @Deprecated public static androidx.core.app.ShareCompat.IntentReader from(android.app.Activity);
+ method public android.content.ComponentName? getCallingActivity();
+ method public android.graphics.drawable.Drawable? getCallingActivityIcon();
+ method public android.graphics.drawable.Drawable? getCallingApplicationIcon();
+ method public CharSequence? getCallingApplicationLabel();
+ method public String? getCallingPackage();
+ method public String![]? getEmailBcc();
+ method public String![]? getEmailCc();
+ method public String![]? getEmailTo();
+ method public String? getHtmlText();
+ method public android.net.Uri? getStream();
+ method public android.net.Uri? getStream(int);
+ method public int getStreamCount();
+ method public String? getSubject();
+ method public CharSequence? getText();
+ method public String? getType();
+ method public boolean isMultipleShare();
+ method public boolean isShareIntent();
+ method public boolean isSingleShare();
+ }
+
+ public abstract class SharedElementCallback {
+ ctor public SharedElementCallback();
+ method public android.os.Parcelable! onCaptureSharedElementSnapshot(android.view.View!, android.graphics.Matrix!, android.graphics.RectF!);
+ method public android.view.View! onCreateSnapshotView(android.content.Context!, android.os.Parcelable!);
+ method public void onMapSharedElements(java.util.List<java.lang.String!>!, java.util.Map<java.lang.String!,android.view.View!>!);
+ method public void onRejectSharedElements(java.util.List<android.view.View!>!);
+ method public void onSharedElementEnd(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementStart(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, java.util.List<android.view.View!>!);
+ method public void onSharedElementsArrived(java.util.List<java.lang.String!>!, java.util.List<android.view.View!>!, androidx.core.app.SharedElementCallback.OnSharedElementsReadyListener!);
+ }
+
+ public static interface SharedElementCallback.OnSharedElementsReadyListener {
+ method public void onSharedElementsReady();
+ }
+
+ public final class TaskStackBuilder implements java.lang.Iterable<android.content.Intent> {
+ method public androidx.core.app.TaskStackBuilder addNextIntent(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
+ method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
+ method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
+ method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
+ method public android.content.Intent? editIntentAt(int);
+ method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
+ method @Deprecated public android.content.Intent! getIntent(int);
+ method public int getIntentCount();
+ method public android.content.Intent![] getIntents();
+ method public android.app.PendingIntent? getPendingIntent(int, int);
+ method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
+ method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
+ method public void startActivities();
+ method public void startActivities(android.os.Bundle?);
+ }
+
+ public static interface TaskStackBuilder.SupportParentable {
+ method public android.content.Intent? getSupportParentActivityIntent();
+ }
+
+}
+
+package androidx.core.content {
+
+ public final class ContentProviderCompat {
+ method public static android.content.Context requireContext(android.content.ContentProvider);
+ }
+
+ public final class ContentResolverCompat {
+ method public static android.database.Cursor? query(android.content.ContentResolver, android.net.Uri, String![]?, String?, String![]?, String?, androidx.core.os.CancellationSignal?);
+ }
+
+ public class ContextCompat {
+ ctor protected ContextCompat();
+ method public static int checkSelfPermission(android.content.Context, String);
+ method public static android.content.Context? createDeviceProtectedStorageContext(android.content.Context);
+ method public static String? getAttributionTag(android.content.Context);
+ method public static java.io.File getCodeCacheDir(android.content.Context);
+ method @ColorInt public static int getColor(android.content.Context, @ColorRes int);
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.Context, @ColorRes int);
+ method public static java.io.File? getDataDir(android.content.Context);
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.Context, @DrawableRes int);
+ method public static java.io.File![] getExternalCacheDirs(android.content.Context);
+ method public static java.io.File![] getExternalFilesDirs(android.content.Context, String?);
+ method public static java.util.concurrent.Executor getMainExecutor(android.content.Context);
+ method public static java.io.File? getNoBackupFilesDir(android.content.Context);
+ method public static java.io.File![] getObbDirs(android.content.Context);
+ method public static <T> T? getSystemService(android.content.Context, Class<T!>);
+ method public static String? getSystemServiceName(android.content.Context, Class<?>);
+ method public static boolean isDeviceProtectedStorage(android.content.Context);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+ method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![]);
+ method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
+ method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
+ method public static void startForegroundService(android.content.Context, android.content.Intent);
+ field public static final int RECEIVER_EXPORTED = 2; // 0x2
+ field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+ field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
+ }
+
+ public class FileProvider extends android.content.ContentProvider {
+ ctor public FileProvider();
+ ctor protected FileProvider(@XmlRes int);
+ method public int delete(android.net.Uri, String?, String![]?);
+ method public String? getType(android.net.Uri);
+ method public static android.net.Uri! getUriForFile(android.content.Context, String, java.io.File);
+ method public static android.net.Uri getUriForFile(android.content.Context, String, java.io.File, String);
+ method public android.net.Uri! insert(android.net.Uri, android.content.ContentValues);
+ method public boolean onCreate();
+ method public android.database.Cursor query(android.net.Uri, String![]?, String?, String![]?, String?);
+ method public int update(android.net.Uri, android.content.ContentValues, String?, String![]?);
+ }
+
+ public final class IntentCompat {
+ method public static android.content.Intent createManageUnusedAppRestrictionsIntent(android.content.Context, String);
+ method public static android.os.Parcelable![]? getParcelableArrayExtra(android.content.Intent, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayListExtra(android.content.Intent, String?, Class<? extends T>);
+ method public static <T> T? getParcelableExtra(android.content.Intent, String?, Class<T!>);
+ method public static android.content.Intent makeMainSelectorActivity(String, String);
+ field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
+ field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
+ field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
+ field public static final String EXTRA_TIME = "android.intent.extra.TIME";
+ }
+
+ public class IntentSanitizer {
+ method public android.content.Intent sanitize(android.content.Intent, androidx.core.util.Consumer<java.lang.String!>);
+ method public android.content.Intent sanitizeByFiltering(android.content.Intent);
+ method public android.content.Intent sanitizeByThrowing(android.content.Intent);
+ }
+
+ public static final class IntentSanitizer.Builder {
+ ctor public IntentSanitizer.Builder();
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowAction(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowAnyComponent();
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowCategory(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipData(androidx.core.util.Predicate<android.content.ClipData!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataText();
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUri(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowClipDataUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(android.content.ComponentName);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponent(androidx.core.util.Predicate<android.content.ComponentName!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowComponentWithPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowData(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowDataWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<?>);
+ method public <T> androidx.core.content.IntentSanitizer.Builder allowExtra(String, Class<T!>, androidx.core.util.Predicate<T!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtra(String, androidx.core.util.Predicate<java.lang.Object!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraOutput(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStream(androidx.core.util.Predicate<android.net.Uri!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowExtraStreamUriWithAuthority(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowFlags(int);
+ method public androidx.core.content.IntentSanitizer.Builder allowHistoryStackFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowIdentifier();
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowPackage(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer.Builder allowReceiverFlags();
+ method public androidx.core.content.IntentSanitizer.Builder allowSelector();
+ method public androidx.core.content.IntentSanitizer.Builder allowSourceBounds();
+ method public androidx.core.content.IntentSanitizer.Builder allowType(String);
+ method public androidx.core.content.IntentSanitizer.Builder allowType(androidx.core.util.Predicate<java.lang.String!>);
+ method public androidx.core.content.IntentSanitizer build();
+ }
+
+ public final class LocusIdCompat {
+ ctor public LocusIdCompat(String);
+ method public String getId();
+ method @RequiresApi(29) public android.content.LocusId toLocusId();
+ method @RequiresApi(29) public static androidx.core.content.LocusIdCompat toLocusIdCompat(android.content.LocusId);
+ }
+
+ public final class MimeTypeFilter {
+ method public static boolean matches(String?, String);
+ method public static String? matches(String?, String![]);
+ method public static String? matches(String![]?, String);
+ method public static String![] matchesMany(String![]?, String);
+ }
+
+ public interface OnConfigurationChangedProvider {
+ method public void addOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ method public void removeOnConfigurationChangedListener(androidx.core.util.Consumer<android.content.res.Configuration!>);
+ }
+
+ public interface OnTrimMemoryProvider {
+ method public void addOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ method public void removeOnTrimMemoryListener(androidx.core.util.Consumer<java.lang.Integer!>);
+ }
+
+ public final class PackageManagerCompat {
+ method public static com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> getUnusedAppRestrictionsStatus(android.content.Context);
+ field public static final String ACTION_PERMISSION_REVOCATION_SETTINGS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
+ }
+
+ public final class PermissionChecker {
+ method @androidx.core.content.PermissionChecker.PermissionResult public static int checkCallingOrSelfPermission(android.content.Context, String);
+ method @androidx.core.content.PermissionChecker.PermissionResult public static int checkCallingPermission(android.content.Context, String, String?);
+ method @androidx.core.content.PermissionChecker.PermissionResult public static int checkPermission(android.content.Context, String, int, int, String?);
+ method @androidx.core.content.PermissionChecker.PermissionResult public static int checkSelfPermission(android.content.Context, String);
+ field public static final int PERMISSION_DENIED = -1; // 0xffffffff
+ field public static final int PERMISSION_DENIED_APP_OP = -2; // 0xfffffffe
+ field public static final int PERMISSION_GRANTED = 0; // 0x0
+ }
+
+ @IntDef({androidx.core.content.PermissionChecker.PERMISSION_GRANTED, androidx.core.content.PermissionChecker.PERMISSION_DENIED, androidx.core.content.PermissionChecker.PERMISSION_DENIED_APP_OP}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PermissionChecker.PermissionResult {
+ }
+
+ @Deprecated public final class SharedPreferencesCompat {
+ }
+
+ @Deprecated public static final class SharedPreferencesCompat.EditorCompat {
+ method @Deprecated public void apply(android.content.SharedPreferences.Editor);
+ method @Deprecated public static androidx.core.content.SharedPreferencesCompat.EditorCompat! getInstance();
+ }
+
+ public class UnusedAppRestrictionsBackportCallback {
+ method public void onResult(boolean, boolean) throws android.os.RemoteException;
+ }
+
+ public abstract class UnusedAppRestrictionsBackportService extends android.app.Service {
+ ctor public UnusedAppRestrictionsBackportService();
+ method protected abstract void isPermissionRevocationEnabled(androidx.core.content.UnusedAppRestrictionsBackportCallback);
+ method public android.os.IBinder? onBind(android.content.Intent?);
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS_BACKPORT_CONNECTION = "android.support.unusedapprestrictions.action.CustomUnusedAppRestrictionsBackportService";
+ }
+
+ public final class UnusedAppRestrictionsConstants {
+ field public static final int API_30 = 4; // 0x4
+ field public static final int API_30_BACKPORT = 3; // 0x3
+ field public static final int API_31 = 5; // 0x5
+ field public static final int DISABLED = 2; // 0x2
+ field public static final int ERROR = 0; // 0x0
+ field public static final int FEATURE_NOT_AVAILABLE = 1; // 0x1
+ }
+
+ public class UriMatcherCompat {
+ method public static androidx.core.util.Predicate<android.net.Uri!> asPredicate(android.content.UriMatcher);
+ }
+
+}
+
+package androidx.core.content.pm {
+
+ @Deprecated public final class ActivityInfoCompat {
+ field @Deprecated public static final int CONFIG_UI_MODE = 512; // 0x200
+ }
+
+ public final class PackageInfoCompat {
+ method public static long getLongVersionCode(android.content.pm.PackageInfo);
+ method public static java.util.List<android.content.pm.Signature!> getSignatures(android.content.pm.PackageManager, String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static boolean hasSignatures(android.content.pm.PackageManager, String, @Size(min=1) java.util.Map<byte[]!,java.lang.Integer!>, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
+ }
+
+ public final class PermissionInfoCompat {
+ method public static int getProtection(android.content.pm.PermissionInfo);
+ method public static int getProtectionFlags(android.content.pm.PermissionInfo);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class ShortcutInfoChangeListener {
+ ctor public ShortcutInfoChangeListener();
+ method @AnyThread public void onAllShortcutsRemoved();
+ method @AnyThread public void onShortcutAdded(java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method @AnyThread public void onShortcutRemoved(java.util.List<java.lang.String!>);
+ method @AnyThread public void onShortcutUpdated(java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method @AnyThread public void onShortcutUsageReported(java.util.List<java.lang.String!>);
+ }
+
+ public class ShortcutInfoCompat {
+ method public android.content.ComponentName? getActivity();
+ method public java.util.Set<java.lang.String!>? getCategories();
+ method public CharSequence? getDisabledMessage();
+ method public int getDisabledReason();
+ method @androidx.core.content.pm.ShortcutInfoCompat.Surface public int getExcludedFromSurfaces();
+ method public android.os.PersistableBundle? getExtras();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.core.graphics.drawable.IconCompat! getIcon();
+ method public String getId();
+ method public android.content.Intent getIntent();
+ method public android.content.Intent![] getIntents();
+ method public long getLastChangedTimestamp();
+ method public androidx.core.content.LocusIdCompat? getLocusId();
+ method public CharSequence? getLongLabel();
+ method public String getPackage();
+ method public int getRank();
+ method public CharSequence getShortLabel();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.os.Bundle? getTransientExtras();
+ method public android.os.UserHandle? getUserHandle();
+ method public boolean hasKeyFieldsOnly();
+ method public boolean isCached();
+ method public boolean isDeclaredInManifest();
+ method public boolean isDynamic();
+ method public boolean isEnabled();
+ method public boolean isExcludedFromSurfaces(@androidx.core.content.pm.ShortcutInfoCompat.Surface int);
+ method public boolean isImmutable();
+ method public boolean isPinned();
+ method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+ field public static final int SURFACE_LAUNCHER = 1; // 0x1
+ }
+
+ public static class ShortcutInfoCompat.Builder {
+ ctor public ShortcutInfoCompat.Builder(android.content.Context, String);
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public ShortcutInfoCompat.Builder(androidx.core.content.pm.ShortcutInfoCompat);
+ ctor @RequiresApi(25) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public ShortcutInfoCompat.Builder(android.content.Context, android.content.pm.ShortcutInfo);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder addCapabilityBinding(String, String, java.util.List<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat build();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setActivity(android.content.ComponentName);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedFromSurfaces(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
+ method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived(boolean);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPerson(androidx.core.app.Person);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setPersons(androidx.core.app.Person![]);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setRank(int);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setShortLabel(CharSequence);
+ method public androidx.core.content.pm.ShortcutInfoCompat.Builder setSliceUri(android.net.Uri);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.core.content.pm.ShortcutInfoCompat.Builder setTransientExtras(android.os.Bundle);
+ }
+
+ @IntDef(flag=true, value={androidx.core.content.pm.ShortcutInfoCompat.SURFACE_LAUNCHER}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ShortcutInfoCompat.Surface {
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class ShortcutInfoCompatSaver<T> {
+ ctor public ShortcutInfoCompatSaver();
+ method @AnyThread public abstract T! addShortcuts(java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>!);
+ method @WorkerThread public java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>! getShortcuts() throws java.lang.Exception;
+ method @AnyThread public abstract T! removeAllShortcuts();
+ method @AnyThread public abstract T! removeShortcuts(java.util.List<java.lang.String!>!);
+ }
+
+ public class ShortcutManagerCompat {
+ method public static boolean addDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static android.content.Intent createShortcutResultIntent(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void disableShortcuts(android.content.Context, java.util.List<java.lang.String!>, CharSequence?);
+ method public static void enableShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getDynamicShortcuts(android.content.Context);
+ method public static int getIconMaxHeight(android.content.Context);
+ method public static int getIconMaxWidth(android.content.Context);
+ method public static int getMaxShortcutCountPerActivity(android.content.Context);
+ method public static java.util.List<androidx.core.content.pm.ShortcutInfoCompat!> getShortcuts(android.content.Context, @androidx.core.content.pm.ShortcutManagerCompat.ShortcutMatchFlags int);
+ method public static boolean isRateLimitingActive(android.content.Context);
+ method public static boolean isRequestPinShortcutSupported(android.content.Context);
+ method public static boolean pushDynamicShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat);
+ method public static void removeAllDynamicShortcuts(android.content.Context);
+ method public static void removeDynamicShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void removeLongLivedShortcuts(android.content.Context, java.util.List<java.lang.String!>);
+ method public static void reportShortcutUsed(android.content.Context, String);
+ method public static boolean requestPinShortcut(android.content.Context, androidx.core.content.pm.ShortcutInfoCompat, android.content.IntentSender?);
+ method public static boolean setDynamicShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ method public static boolean updateShortcuts(android.content.Context, java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>);
+ field public static final String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID";
+ field public static final int FLAG_MATCH_CACHED = 8; // 0x8
+ field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
+ field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
+ field public static final int FLAG_MATCH_PINNED = 4; // 0x4
+ }
+
+ @IntDef(flag=true, value={androidx.core.content.pm.ShortcutManagerCompat.FLAG_MATCH_MANIFEST, androidx.core.content.pm.ShortcutManagerCompat.FLAG_MATCH_DYNAMIC, androidx.core.content.pm.ShortcutManagerCompat.FLAG_MATCH_PINNED, androidx.core.content.pm.ShortcutManagerCompat.FLAG_MATCH_CACHED}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ShortcutManagerCompat.ShortcutMatchFlags {
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public class ShortcutXmlParser {
+ method @WorkerThread public static java.util.List<java.lang.String!> getShortcutIds(android.content.Context);
+ method @VisibleForTesting public static java.util.List<java.lang.String!> parseShortcutIds(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
+package androidx.core.content.res {
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class ColorStateListInflaterCompat {
+ method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.content.res.ColorStateList createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.content.res.ColorStateList? inflate(android.content.res.Resources, @XmlRes int, android.content.res.Resources.Theme?);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class ComplexColorCompat {
+ method @ColorInt public int getColor();
+ method public android.graphics.Shader? getShader();
+ method public static androidx.core.content.res.ComplexColorCompat? inflate(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?);
+ method public boolean isGradient();
+ method public boolean isStateful();
+ method public boolean onStateChanged(int[]!);
+ method public void setColor(@ColorInt int);
+ method public boolean willDraw();
+ }
+
+ public final class ConfigurationHelper {
+ method public static int getDensityDpi(android.content.res.Resources);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class FontResourcesParserCompat {
+ method public static androidx.core.content.res.FontResourcesParserCompat.FamilyResourceEntry? parse(org.xmlpull.v1.XmlPullParser, android.content.res.Resources) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static java.util.List<java.util.List<byte[]!>!> readCerts(android.content.res.Resources, @ArrayRes int);
+ field public static final int FETCH_STRATEGY_ASYNC = 1; // 0x1
+ field public static final int FETCH_STRATEGY_BLOCKING = 0; // 0x0
+ field public static final int INFINITE_TIMEOUT_VALUE = -1; // 0xffffffff
+ }
+
+ public static interface FontResourcesParserCompat.FamilyResourceEntry {
+ }
+
+ @IntDef({androidx.core.content.res.FontResourcesParserCompat.FETCH_STRATEGY_BLOCKING, androidx.core.content.res.FontResourcesParserCompat.FETCH_STRATEGY_ASYNC}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface FontResourcesParserCompat.FetchStrategy {
+ }
+
+ public static final class FontResourcesParserCompat.FontFamilyFilesResourceEntry implements androidx.core.content.res.FontResourcesParserCompat.FamilyResourceEntry {
+ ctor public FontResourcesParserCompat.FontFamilyFilesResourceEntry(androidx.core.content.res.FontResourcesParserCompat.FontFileResourceEntry![]);
+ method public androidx.core.content.res.FontResourcesParserCompat.FontFileResourceEntry![] getEntries();
+ }
+
+ public static final class FontResourcesParserCompat.FontFileResourceEntry {
+ ctor public FontResourcesParserCompat.FontFileResourceEntry(String, int, boolean, String?, int, int);
+ method public String getFileName();
+ method public int getResourceId();
+ method public int getTtcIndex();
+ method public String? getVariationSettings();
+ method public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static final class FontResourcesParserCompat.ProviderResourceEntry implements androidx.core.content.res.FontResourcesParserCompat.FamilyResourceEntry {
+ ctor public FontResourcesParserCompat.ProviderResourceEntry(androidx.core.provider.FontRequest, @androidx.core.content.res.FontResourcesParserCompat.FetchStrategy int, int);
+ method @androidx.core.content.res.FontResourcesParserCompat.FetchStrategy public int getFetchStrategy();
+ method public androidx.core.provider.FontRequest getRequest();
+ method public int getTimeout();
+ }
+
+ public final class ResourcesCompat {
+ method public static void clearCachesForTheme(android.content.res.Resources.Theme);
+ method public static android.graphics.Typeface? getCachedFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method @ColorInt public static int getColor(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.content.res.ColorStateList? getColorStateList(android.content.res.Resources, @ColorRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.res.Resources, @DrawableRes int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static android.graphics.drawable.Drawable? getDrawableForDensity(android.content.res.Resources, @DrawableRes int, int, android.content.res.Resources.Theme?) throws android.content.res.Resources.NotFoundException;
+ method public static float getFloat(android.content.res.Resources, @DimenRes int);
+ method public static android.graphics.Typeface? getFont(android.content.Context, @FontRes int) throws android.content.res.Resources.NotFoundException;
+ method public static void getFont(android.content.Context, @FontRes int, androidx.core.content.res.ResourcesCompat.FontCallback, android.os.Handler?) throws android.content.res.Resources.NotFoundException;
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface? getFont(android.content.Context, @FontRes int, android.util.TypedValue, int, androidx.core.content.res.ResourcesCompat.FontCallback?) throws android.content.res.Resources.NotFoundException;
+ field @AnyRes public static final int ID_NULL = 0; // 0x0
+ }
+
+ public abstract static class ResourcesCompat.FontCallback {
+ ctor public ResourcesCompat.FontCallback();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final void callbackFailAsync(@androidx.core.provider.FontsContractCompat.FontRequestCallback.FontRequestFailReason int, android.os.Handler?);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final void callbackSuccessAsync(android.graphics.Typeface, android.os.Handler?);
+ method public abstract void onFontRetrievalFailed(@androidx.core.provider.FontsContractCompat.FontRequestCallback.FontRequestFailReason int);
+ method public abstract void onFontRetrieved(android.graphics.Typeface);
+ }
+
+ public static final class ResourcesCompat.ThemeCompat {
+ method public static void rebase(android.content.res.Resources.Theme);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class TypedArrayUtils {
+ method public static int getAttr(android.content.Context, int, int);
+ method public static boolean getBoolean(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int, boolean);
+ method public static android.graphics.drawable.Drawable? getDrawable(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int);
+ method public static int getInt(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int, int);
+ method public static boolean getNamedBoolean(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int, boolean);
+ method @ColorInt public static int getNamedColor(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int, @ColorInt int);
+ method public static android.content.res.ColorStateList? getNamedColorStateList(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme?, String, @StyleableRes int);
+ method public static androidx.core.content.res.ComplexColorCompat! getNamedComplexColor(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme?, String, @StyleableRes int, @ColorInt int);
+ method public static float getNamedFloat(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int, float);
+ method public static int getNamedInt(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int, int);
+ method @AnyRes public static int getNamedResourceId(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int, @AnyRes int);
+ method public static String? getNamedString(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, @StyleableRes int);
+ method @AnyRes public static int getResourceId(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int, @AnyRes int);
+ method public static String? getString(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int);
+ method public static CharSequence? getText(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int);
+ method public static CharSequence![]? getTextArray(android.content.res.TypedArray, @StyleableRes int, @StyleableRes int);
+ method public static boolean hasAttribute(org.xmlpull.v1.XmlPullParser, String);
+ method public static android.content.res.TypedArray obtainAttributes(android.content.res.Resources, android.content.res.Resources.Theme?, android.util.AttributeSet, int[]);
+ method public static android.util.TypedValue? peekNamedValue(android.content.res.TypedArray, org.xmlpull.v1.XmlPullParser, String, int);
+ }
+
+}
+
+package androidx.core.database {
+
+ public final class CursorWindowCompat {
+ method public static android.database.CursorWindow create(String?, long);
+ }
+
+ @Deprecated public final class DatabaseUtilsCompat {
+ method @Deprecated public static String![]! appendSelectionArgs(String![]!, String![]!);
+ method @Deprecated public static String! concatenateWhere(String!, String!);
+ }
+
+}
+
+package androidx.core.database.sqlite {
+
+ public final class SQLiteCursorCompat {
+ method public static void setFillWindowForwardOnly(android.database.sqlite.SQLiteCursor, boolean);
+ }
+
+}
+
+package androidx.core.graphics {
+
+ public final class BitmapCompat {
+ method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, android.graphics.Rect?, boolean);
+ method public static int getAllocationByteCount(android.graphics.Bitmap);
+ method public static boolean hasMipMap(android.graphics.Bitmap);
+ method public static void setHasMipMap(android.graphics.Bitmap, boolean);
+ }
+
+ public class BlendModeColorFilterCompat {
+ method public static android.graphics.ColorFilter? createBlendModeColorFilterCompat(int, androidx.core.graphics.BlendModeCompat);
+ }
+
+ public enum BlendModeCompat {
+ enum_constant public static final androidx.core.graphics.BlendModeCompat CLEAR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_BURN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat COLOR_DODGE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DARKEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat DIFFERENCE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat DST_OVER;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat EXCLUSION;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HARD_LIGHT;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat HUE;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat LIGHTEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat LUMINOSITY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat MODULATE;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat MULTIPLY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat OVERLAY;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat PLUS;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SATURATION;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SCREEN;
+ enum_constant @RequiresApi(android.os.Build.VERSION_CODES.Q) public static final androidx.core.graphics.BlendModeCompat SOFT_LIGHT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_ATOP;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_IN;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OUT;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat SRC_OVER;
+ enum_constant public static final androidx.core.graphics.BlendModeCompat XOR;
+ }
+
+ public final class ColorUtils {
+ method @ColorInt public static int HSLToColor(float[]);
+ method @ColorInt public static int LABToColor(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double);
+ method public static void LABToXYZ(@FloatRange(from=0.0f, to=100) double, @FloatRange(from=0xffffff80, to=127) double, @FloatRange(from=0xffffff80, to=127) double, double[]);
+ method public static void RGBToHSL(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, float[]);
+ method public static void RGBToLAB(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method public static void RGBToXYZ(@IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, @IntRange(from=0, to=255) int, double[]);
+ method @ColorInt public static int XYZToColor(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double);
+ method public static void XYZToLAB(@FloatRange(from=0.0f, to=95.047) double, @FloatRange(from=0.0f, to=0x64) double, @FloatRange(from=0.0f, to=108.883) double, double[]);
+ method @ColorInt public static int blendARGB(@ColorInt int, @ColorInt int, @FloatRange(from=0.0, to=1.0) float);
+ method public static void blendHSL(float[], float[], @FloatRange(from=0.0, to=1.0) float, float[]);
+ method public static void blendLAB(double[], double[], @FloatRange(from=0.0, to=1.0) double, double[]);
+ method public static double calculateContrast(@ColorInt int, @ColorInt int);
+ method @FloatRange(from=0.0, to=1.0) public static double calculateLuminance(@ColorInt int);
+ method public static int calculateMinimumAlpha(@ColorInt int, @ColorInt int, float);
+ method public static void colorToHSL(@ColorInt int, float[]);
+ method public static void colorToLAB(@ColorInt int, double[]);
+ method public static void colorToXYZ(@ColorInt int, double[]);
+ method public static int compositeColors(@ColorInt int, @ColorInt int);
+ method @RequiresApi(26) public static android.graphics.Color compositeColors(android.graphics.Color, android.graphics.Color);
+ method public static double distanceEuclidean(double[], double[]);
+ method @ColorInt public static int setAlphaComponent(@ColorInt int, @IntRange(from=0, to=255) int);
+ }
+
+ public final class Insets {
+ method public static androidx.core.graphics.Insets add(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets max(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets min(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public static androidx.core.graphics.Insets of(int, int, int, int);
+ method public static androidx.core.graphics.Insets of(android.graphics.Rect);
+ method public static androidx.core.graphics.Insets subtract(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method @RequiresApi(api=29) public static androidx.core.graphics.Insets toCompatInsets(android.graphics.Insets);
+ method @RequiresApi(29) public android.graphics.Insets toPlatformInsets();
+ method @Deprecated @RequiresApi(api=29) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.graphics.Insets wrap(android.graphics.Insets);
+ field public static final androidx.core.graphics.Insets NONE;
+ field public final int bottom;
+ field public final int left;
+ field public final int right;
+ field public final int top;
+ }
+
+ public final class PaintCompat {
+ method public static boolean hasGlyph(android.graphics.Paint, String);
+ method public static boolean setBlendMode(android.graphics.Paint, androidx.core.graphics.BlendModeCompat?);
+ }
+
+ public final class PathSegment {
+ ctor public PathSegment(android.graphics.PointF, float, android.graphics.PointF, float);
+ method public android.graphics.PointF getEnd();
+ method public float getEndFraction();
+ method public android.graphics.PointF getStart();
+ method public float getStartFraction();
+ }
+
+ public final class PathUtils {
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path);
+ method @RequiresApi(26) public static java.util.Collection<androidx.core.graphics.PathSegment!> flatten(android.graphics.Path, @FloatRange(from=0) float);
+ }
+
+ public class TypefaceCompat {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @VisibleForTesting public static void clearCache();
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, int);
+ method public static android.graphics.Typeface create(android.content.Context, android.graphics.Typeface?, @IntRange(from=1, to=1000) int, boolean);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface? createFromFontInfo(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![], int);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface? createFromResourcesFamilyXml(android.content.Context, androidx.core.content.res.FontResourcesParserCompat.FamilyResourceEntry, android.content.res.Resources, int, int, androidx.core.content.res.ResourcesCompat.FontCallback?, android.os.Handler?, boolean);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface? createFromResourcesFontFile(android.content.Context, android.content.res.Resources, int, String!, int);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface? findFromCache(android.content.res.Resources, int, int);
+ }
+
+ @RequiresApi(26) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class TypefaceCompatApi26Impl {
+ ctor public TypefaceCompatApi26Impl();
+ method protected android.graphics.Typeface? createFromFamiliesWithDefault(Object!);
+ method public android.graphics.Typeface? createFromFontFamilyFilesResourceEntry(android.content.Context!, androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry!, android.content.res.Resources!, int);
+ method public android.graphics.Typeface? createFromFontInfo(android.content.Context!, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![], int);
+ method public android.graphics.Typeface? createFromResourcesFontFile(android.content.Context!, android.content.res.Resources!, int, String!, int);
+ method protected java.lang.reflect.Method! obtainAbortCreationMethod(Class<?>!) throws java.lang.NoSuchMethodException;
+ method protected java.lang.reflect.Method! obtainAddFontFromAssetManagerMethod(Class<?>!) throws java.lang.NoSuchMethodException;
+ method protected java.lang.reflect.Method! obtainAddFontFromBufferMethod(Class<?>!) throws java.lang.NoSuchMethodException;
+ method protected java.lang.reflect.Method! obtainCreateFromFamiliesWithDefaultMethod(Class<?>!) throws java.lang.NoSuchMethodException;
+ method protected Class<?>! obtainFontFamily() throws java.lang.ClassNotFoundException;
+ method protected java.lang.reflect.Constructor<?>! obtainFontFamilyCtor(Class<?>!) throws java.lang.NoSuchMethodException;
+ method protected java.lang.reflect.Method! obtainFreezeMethod(Class<?>!) throws java.lang.NoSuchMethodException;
+ field protected final java.lang.reflect.Method! mAbortCreation;
+ field protected final java.lang.reflect.Method! mAddFontFromAssetManager;
+ field protected final java.lang.reflect.Method! mAddFontFromBuffer;
+ field protected final java.lang.reflect.Method! mCreateFromFamiliesWithDefault;
+ field protected final Class<?>! mFontFamily;
+ field protected final java.lang.reflect.Constructor<?>! mFontFamilyCtor;
+ field protected final java.lang.reflect.Method! mFreeze;
+ }
+
+ @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class TypefaceCompatApi28Impl extends androidx.core.graphics.TypefaceCompatApi26Impl {
+ ctor public TypefaceCompatApi28Impl();
+ }
+
+ @RequiresApi(29) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public class TypefaceCompatApi29Impl {
+ ctor public TypefaceCompatApi29Impl();
+ method public android.graphics.Typeface? createFromFontFamilyFilesResourceEntry(android.content.Context!, androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry!, android.content.res.Resources!, int);
+ method public android.graphics.Typeface? createFromFontInfo(android.content.Context!, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![], int);
+ method protected android.graphics.Typeface! createFromInputStream(android.content.Context!, java.io.InputStream!);
+ method public android.graphics.Typeface? createFromResourcesFontFile(android.content.Context!, android.content.res.Resources!, int, String!, int);
+ method protected androidx.core.provider.FontsContractCompat.FontInfo! findBestInfo(androidx.core.provider.FontsContractCompat.FontInfo![]!, int);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class TypefaceCompatUtil {
+ method public static void closeQuietly(java.io.Closeable?);
+ method @RequiresApi(19) public static java.nio.ByteBuffer? copyToDirectBuffer(android.content.Context, android.content.res.Resources, int);
+ method public static boolean copyToFile(java.io.File, java.io.InputStream);
+ method public static boolean copyToFile(java.io.File, android.content.res.Resources, int);
+ method public static java.io.File? getTempFile(android.content.Context);
+ method @RequiresApi(19) public static java.nio.ByteBuffer? mmap(android.content.Context, android.os.CancellationSignal?, android.net.Uri);
+ }
+
+}
+
+package androidx.core.graphics.drawable {
+
+ public final class DrawableCompat {
+ method public static void applyTheme(android.graphics.drawable.Drawable, android.content.res.Resources.Theme);
+ method public static boolean canApplyTheme(android.graphics.drawable.Drawable);
+ method public static void clearColorFilter(android.graphics.drawable.Drawable);
+ method public static int getAlpha(android.graphics.drawable.Drawable);
+ method public static android.graphics.ColorFilter? getColorFilter(android.graphics.drawable.Drawable);
+ method public static int getLayoutDirection(android.graphics.drawable.Drawable);
+ method public static void inflate(android.graphics.drawable.Drawable, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
+ method @Deprecated public static void jumpToCurrentState(android.graphics.drawable.Drawable);
+ method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
+ method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
+ method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
+ method public static boolean setLayoutDirection(android.graphics.drawable.Drawable, int);
+ method public static void setTint(android.graphics.drawable.Drawable, @ColorInt int);
+ method public static void setTintList(android.graphics.drawable.Drawable, android.content.res.ColorStateList?);
+ method public static void setTintMode(android.graphics.drawable.Drawable, android.graphics.PorterDuff.Mode?);
+ method public static <T extends android.graphics.drawable.Drawable> T! unwrap(android.graphics.drawable.Drawable);
+ method public static android.graphics.drawable.Drawable wrap(android.graphics.drawable.Drawable);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(allowSerialization=true, ignoreParcelables=true, isCustom=true, jetifyAs="android.support.v4.graphics.drawable.IconCompat") public class IconCompat extends androidx.versionedparcelable.CustomVersionedParcelable {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void addToShortcutIntent(android.content.Intent, android.graphics.drawable.Drawable?, android.content.Context);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void checkResource(android.content.Context);
+ method public static androidx.core.graphics.drawable.IconCompat? createFromBundle(android.os.Bundle);
+ method @RequiresApi(23) public static androidx.core.graphics.drawable.IconCompat? createFromIcon(android.content.Context, android.graphics.drawable.Icon);
+ method @RequiresApi(23) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.graphics.drawable.IconCompat? createFromIcon(android.graphics.drawable.Icon);
+ method @RequiresApi(23) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.graphics.drawable.IconCompat? createFromIconOrNullIfZeroResId(android.graphics.drawable.Icon);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmapContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithBitmap(android.graphics.Bitmap);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(String);
+ method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
+ method public static androidx.core.graphics.drawable.IconCompat createWithData(byte[], int, int);
+ method public static androidx.core.graphics.drawable.IconCompat createWithResource(android.content.Context, @DrawableRes int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.graphics.drawable.IconCompat createWithResource(android.content.res.Resources?, String, @DrawableRes int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.Bitmap? getBitmap();
+ method @DrawableRes public int getResId();
+ method public String getResPackage();
+ method public int getType();
+ method public android.net.Uri getUri();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public java.io.InputStream? getUriInputStream(android.content.Context);
+ method public android.graphics.drawable.Drawable? loadDrawable(android.content.Context);
+ method public androidx.core.graphics.drawable.IconCompat setTint(@ColorInt int);
+ method public androidx.core.graphics.drawable.IconCompat setTintList(android.content.res.ColorStateList?);
+ method public androidx.core.graphics.drawable.IconCompat setTintMode(android.graphics.PorterDuff.Mode?);
+ method public android.os.Bundle toBundle();
+ method @Deprecated @RequiresApi(23) public android.graphics.drawable.Icon toIcon();
+ method @RequiresApi(23) public android.graphics.drawable.Icon toIcon(android.content.Context?);
+ field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5
+ field public static final int TYPE_BITMAP = 1; // 0x1
+ field public static final int TYPE_DATA = 3; // 0x3
+ field public static final int TYPE_RESOURCE = 2; // 0x2
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ field public static final int TYPE_URI = 4; // 0x4
+ field public static final int TYPE_URI_ADAPTIVE_BITMAP = 6; // 0x6
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.ParcelField(value=1, defaultValue="androidx.core.graphics.drawable.IconCompat.TYPE_UNKNOWN") public int mType;
+ }
+
+ public abstract class RoundedBitmapDrawable extends android.graphics.drawable.Drawable {
+ method public void draw(android.graphics.Canvas);
+ method public final android.graphics.Bitmap? getBitmap();
+ method public float getCornerRadius();
+ method public int getGravity();
+ method public int getOpacity();
+ method public final android.graphics.Paint getPaint();
+ method public boolean hasAntiAlias();
+ method public boolean hasMipMap();
+ method public boolean isCircular();
+ method public void setAlpha(int);
+ method public void setAntiAlias(boolean);
+ method public void setCircular(boolean);
+ method public void setColorFilter(android.graphics.ColorFilter!);
+ method public void setCornerRadius(float);
+ method public void setDither(boolean);
+ method public void setGravity(int);
+ method public void setMipMap(boolean);
+ method public void setTargetDensity(android.graphics.Canvas);
+ method public void setTargetDensity(android.util.DisplayMetrics);
+ method public void setTargetDensity(int);
+ }
+
+ public final class RoundedBitmapDrawableFactory {
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, android.graphics.Bitmap?);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, String);
+ method public static androidx.core.graphics.drawable.RoundedBitmapDrawable create(android.content.res.Resources, java.io.InputStream);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface TintAwareDrawable {
+ method public void setTint(@ColorInt int);
+ method public void setTintList(android.content.res.ColorStateList!);
+ method public void setTintMode(android.graphics.PorterDuff.Mode!);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface WrappedDrawable {
+ method public android.graphics.drawable.Drawable! getWrappedDrawable();
+ method public void setWrappedDrawable(android.graphics.drawable.Drawable!);
+ }
+
+}
+
+package androidx.core.hardware.display {
+
+ public final class DisplayManagerCompat {
+ method public android.view.Display? getDisplay(int);
+ method public android.view.Display![] getDisplays();
+ method public android.view.Display![] getDisplays(String?);
+ method public static androidx.core.hardware.display.DisplayManagerCompat getInstance(android.content.Context);
+ field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+ }
+
+}
+
+package androidx.core.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManagerCompat {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public void authenticate(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject?, int, androidx.core.os.CancellationSignal?, androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationCallback, android.os.Handler?);
+ method @Deprecated public static androidx.core.hardware.fingerprint.FingerprintManagerCompat from(android.content.Context);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected();
+ }
+
+ @Deprecated public abstract static class FingerprintManagerCompat.AuthenticationCallback {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationCallback();
+ method @Deprecated public void onAuthenticationError(int, CharSequence!);
+ method @Deprecated public void onAuthenticationFailed();
+ method @Deprecated public void onAuthenticationHelp(int, CharSequence!);
+ method @Deprecated public void onAuthenticationSucceeded(androidx.core.hardware.fingerprint.FingerprintManagerCompat.AuthenticationResult!);
+ }
+
+ @Deprecated public static final class FingerprintManagerCompat.AuthenticationResult {
+ ctor @Deprecated public FingerprintManagerCompat.AuthenticationResult(androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject!);
+ method @Deprecated public androidx.core.hardware.fingerprint.FingerprintManagerCompat.CryptoObject! getCryptoObject();
+ }
+
+ @Deprecated public static class FingerprintManagerCompat.CryptoObject {
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(java.security.Signature);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Cipher);
+ ctor @Deprecated public FingerprintManagerCompat.CryptoObject(javax.crypto.Mac);
+ method @Deprecated public javax.crypto.Cipher? getCipher();
+ method @Deprecated public javax.crypto.Mac? getMac();
+ method @Deprecated public java.security.Signature? getSignature();
+ }
+
+}
+
+package androidx.core.internal.view {
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface SupportMenu extends android.view.Menu {
+ method public void setGroupDividerEnabled(boolean);
+ field public static final int CATEGORY_MASK = -65536; // 0xffff0000
+ field public static final int CATEGORY_SHIFT = 16; // 0x10
+ field public static final int FLAG_KEEP_OPEN_ON_SUBMENU_OPENED = 4; // 0x4
+ field public static final int SUPPORTED_MODIFIERS_MASK = 69647; // 0x1100f
+ field public static final int USER_MASK = 65535; // 0xffff
+ field public static final int USER_SHIFT = 0; // 0x0
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface SupportMenuItem extends android.view.MenuItem {
+ method public int getAlphabeticModifiers();
+ method public CharSequence? getContentDescription();
+ method public android.content.res.ColorStateList? getIconTintList();
+ method public android.graphics.PorterDuff.Mode? getIconTintMode();
+ method public int getNumericModifiers();
+ method public androidx.core.view.ActionProvider? getSupportActionProvider();
+ method public CharSequence? getTooltipText();
+ method public boolean requiresActionButton();
+ method public boolean requiresOverflow();
+ method public android.view.MenuItem setAlphabeticShortcut(char, int);
+ method public androidx.core.internal.view.SupportMenuItem setContentDescription(CharSequence?);
+ method public android.view.MenuItem setIconTintList(android.content.res.ColorStateList?);
+ method public android.view.MenuItem setIconTintMode(android.graphics.PorterDuff.Mode?);
+ method public android.view.MenuItem setNumericShortcut(char, int);
+ method public android.view.MenuItem setShortcut(char, char, int, int);
+ method public androidx.core.internal.view.SupportMenuItem setSupportActionProvider(androidx.core.view.ActionProvider?);
+ method public androidx.core.internal.view.SupportMenuItem setTooltipText(CharSequence?);
+ field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+ field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
+ field public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
+ field public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
+ field public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface SupportSubMenu extends androidx.core.internal.view.SupportMenu android.view.SubMenu {
+ }
+
+}
+
+package androidx.core.location {
+
+ public abstract class GnssStatusCompat {
+ method @FloatRange(from=0, to=360) public abstract float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public abstract float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public abstract float getCn0DbHz(@IntRange(from=0) int);
+ method public abstract int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public abstract float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public abstract int getSatelliteCount();
+ method @IntRange(from=1, to=200) public abstract int getSvid(@IntRange(from=0) int);
+ method public abstract boolean hasAlmanacData(@IntRange(from=0) int);
+ method public abstract boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public abstract boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public abstract boolean hasEphemerisData(@IntRange(from=0) int);
+ method public abstract boolean usedInFix(@IntRange(from=0) int);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static androidx.core.location.GnssStatusCompat wrap(android.location.GnssStatus);
+ method public static androidx.core.location.GnssStatusCompat wrap(android.location.GpsStatus);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssStatusCompat.Callback {
+ ctor public GnssStatusCompat.Callback();
+ method public void onFirstFix(@IntRange(from=0) int);
+ method public void onSatelliteStatusChanged(androidx.core.location.GnssStatusCompat);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public final class LocationCompat {
+ method public static float getBearingAccuracyDegrees(android.location.Location);
+ method public static long getElapsedRealtimeMillis(android.location.Location);
+ method public static long getElapsedRealtimeNanos(android.location.Location);
+ method @FloatRange(from=0.0) public static float getMslAltitudeAccuracyMeters(android.location.Location);
+ method public static double getMslAltitudeMeters(android.location.Location);
+ method public static float getSpeedAccuracyMetersPerSecond(android.location.Location);
+ method public static float getVerticalAccuracyMeters(android.location.Location);
+ method public static boolean hasBearingAccuracy(android.location.Location);
+ method public static boolean hasMslAltitude(android.location.Location);
+ method public static boolean hasMslAltitudeAccuracy(android.location.Location);
+ method public static boolean hasSpeedAccuracy(android.location.Location);
+ method public static boolean hasVerticalAccuracy(android.location.Location);
+ method public static boolean isMock(android.location.Location);
+ method public static void removeMslAltitude(android.location.Location);
+ method public static void removeMslAltitudeAccuracy(android.location.Location);
+ method public static void setBearingAccuracyDegrees(android.location.Location, float);
+ method public static void setMock(android.location.Location, boolean);
+ method public static void setMslAltitudeAccuracyMeters(android.location.Location, @FloatRange(from=0.0) float);
+ method public static void setMslAltitudeMeters(android.location.Location, double);
+ method public static void setSpeedAccuracyMetersPerSecond(android.location.Location, float);
+ method public static void setVerticalAccuracyMeters(android.location.Location, float);
+ field public static final String EXTRA_BEARING_ACCURACY = "bearingAccuracy";
+ field public static final String EXTRA_IS_MOCK = "mockLocation";
+ field public static final String EXTRA_MSL_ALTITUDE = "androidx.core.location.extra.MSL_ALTITUDE";
+ field public static final String EXTRA_MSL_ALTITUDE_ACCURACY = "androidx.core.location.extra.MSL_ALTITUDE_ACCURACY";
+ field public static final String EXTRA_SPEED_ACCURACY = "speedAccuracy";
+ field public static final String EXTRA_VERTICAL_ACCURACY = "verticalAccuracy";
+ }
+
+ public interface LocationListenerCompat extends android.location.LocationListener {
+ method public default void onStatusChanged(String, int, android.os.Bundle?);
+ }
+
+ public final class LocationManagerCompat {
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void getCurrentLocation(android.location.LocationManager, String, androidx.core.os.CancellationSignal?, java.util.concurrent.Executor, androidx.core.util.Consumer<android.location.Location!>);
+ method public static String? getGnssHardwareModelName(android.location.LocationManager);
+ method public static int getGnssYearOfHardware(android.location.LocationManager);
+ method public static boolean hasProvider(android.location.LocationManager, String);
+ method public static boolean isLocationEnabled(android.location.LocationManager);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssMeasurementsCallback(android.location.LocationManager, java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback, android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static boolean registerGnssStatusCallback(android.location.LocationManager, java.util.concurrent.Executor, androidx.core.location.GnssStatusCompat.Callback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void removeUpdates(android.location.LocationManager, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, java.util.concurrent.Executor, androidx.core.location.LocationListenerCompat);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static void requestLocationUpdates(android.location.LocationManager, String, androidx.core.location.LocationRequestCompat, androidx.core.location.LocationListenerCompat, android.os.Looper);
+ method @RequiresApi(android.os.Build.VERSION_CODES.N) public static void unregisterGnssMeasurementsCallback(android.location.LocationManager, android.location.GnssMeasurementsEvent.Callback);
+ method public static void unregisterGnssStatusCallback(android.location.LocationManager, androidx.core.location.GnssStatusCompat.Callback);
+ }
+
+ public final class LocationRequestCompat {
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method @RequiresApi(31) public android.location.LocationRequest toLocationRequest();
+ method @RequiresApi(19) public android.location.LocationRequest? toLocationRequest(String);
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequestCompat.Builder {
+ ctor public LocationRequestCompat.Builder(long);
+ ctor public LocationRequestCompat.Builder(androidx.core.location.LocationRequestCompat);
+ method public androidx.core.location.LocationRequestCompat build();
+ method public androidx.core.location.LocationRequestCompat.Builder clearMinUpdateIntervalMillis();
+ method public androidx.core.location.LocationRequestCompat.Builder setDurationMillis(@IntRange(from=1) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method public androidx.core.location.LocationRequestCompat.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method public androidx.core.location.LocationRequestCompat.Builder setQuality(int);
+ }
+
+}
+
+package androidx.core.math {
+
+ public class MathUtils {
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
+ method public static float clamp(float, float, float);
+ method public static double clamp(double, double, double);
+ method public static int clamp(int, int, int);
+ method public static long clamp(long, long, long);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
+ method public static int toIntExact(long);
+ }
+
+}
+
+package androidx.core.net {
+
+ public final class ConnectivityManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static android.net.NetworkInfo? getNetworkInfoFromBroadcast(android.net.ConnectivityManager, android.content.Intent);
+ method @androidx.core.net.ConnectivityManagerCompat.RestrictBackgroundStatus public static int getRestrictBackgroundStatus(android.net.ConnectivityManager);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public static boolean isActiveNetworkMetered(android.net.ConnectivityManager);
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
+ }
+
+ @IntDef({androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED, androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED, androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ConnectivityManagerCompat.RestrictBackgroundStatus {
+ }
+
+ public final class MailTo {
+ method public String? getBcc();
+ method public String? getBody();
+ method public String? getCc();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getHeaders();
+ method public String? getSubject();
+ method public String? getTo();
+ method public static boolean isMailTo(String?);
+ method public static boolean isMailTo(android.net.Uri?);
+ method public static androidx.core.net.MailTo parse(String) throws androidx.core.net.ParseException;
+ method public static androidx.core.net.MailTo parse(android.net.Uri) throws androidx.core.net.ParseException;
+ field public static final String MAILTO_SCHEME = "mailto:";
+ }
+
+ public class ParseException extends java.lang.RuntimeException {
+ field public final String response;
+ }
+
+ public final class TrafficStatsCompat {
+ method @Deprecated public static void clearThreadStatsTag();
+ method @Deprecated public static int getThreadStatsTag();
+ method @Deprecated public static void incrementOperationCount(int);
+ method @Deprecated public static void incrementOperationCount(int, int);
+ method @Deprecated public static void setThreadStatsTag(int);
+ method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void tagSocket(java.net.Socket!) throws java.net.SocketException;
+ method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
+ method @Deprecated public static void untagSocket(java.net.Socket!) throws java.net.SocketException;
+ }
+
+ public final class UriCompat {
+ method public static String toSafeString(android.net.Uri);
+ }
+
+}
+
+package androidx.core.os {
+
+ public class BuildCompat {
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N) public static boolean isAtLeastN();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.N_MR1) public static boolean isAtLeastNMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O) public static boolean isAtLeastO();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.O_MR1) public static boolean isAtLeastOMR1();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.P) public static boolean isAtLeastP();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.Q) public static boolean isAtLeastQ();
+ method @Deprecated @ChecksSdkIntAtLeast(api=android.os.Build.VERSION_CODES.R) public static boolean isAtLeastR();
+ method @Deprecated @ChecksSdkIntAtLeast(api=31, codename="S") public static boolean isAtLeastS();
+ field @ChecksSdkIntAtLeast(extension=android.os.ext.SdkExtensions.AD_SERVICES) public static final int AD_SERVICES_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.R) public static final int R_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.S) public static final int S_EXTENSION_INT;
+ field @ChecksSdkIntAtLeast(extension=android.os.Build.VERSION_CODES.TIRAMISU) public static final int T_EXTENSION_INT;
+ }
+
+ public final class BundleCompat {
+ method public static <T> T? getParcelable(android.os.Bundle, String?, Class<T!>);
+ method public static android.os.Parcelable![]? getParcelableArray(android.os.Bundle, String?, Class<? extends android.os.Parcelable>);
+ method public static <T> java.util.ArrayList<T!>? getParcelableArrayList(android.os.Bundle, String?, Class<? extends T>);
+ method public static <T> android.util.SparseArray<T!>? getSparseParcelableArray(android.os.Bundle, String?, Class<? extends T>);
+ }
+
+ public final class CancellationSignal {
+ ctor public CancellationSignal();
+ method public void cancel();
+ method public Object? getCancellationSignalObject();
+ method public boolean isCanceled();
+ method public void setOnCancelListener(androidx.core.os.CancellationSignal.OnCancelListener?);
+ method public void throwIfCanceled();
+ }
+
+ public static interface CancellationSignal.OnCancelListener {
+ method public void onCancel();
+ }
+
+ public final class ConfigurationCompat {
+ method public static androidx.core.os.LocaleListCompat getLocales(android.content.res.Configuration);
+ }
+
+ public final class EnvironmentCompat {
+ method public static String getStorageState(java.io.File);
+ field public static final String MEDIA_UNKNOWN = "unknown";
+ }
+
+ public final class ExecutorCompat {
+ method public static java.util.concurrent.Executor create(android.os.Handler);
+ }
+
+ public final class HandlerCompat {
+ method public static android.os.Handler createAsync(android.os.Looper);
+ method public static android.os.Handler createAsync(android.os.Looper, android.os.Handler.Callback);
+ method @RequiresApi(16) public static boolean hasCallbacks(android.os.Handler, Runnable);
+ method public static boolean postDelayed(android.os.Handler, Runnable, Object?, long);
+ }
+
+ public final class LocaleListCompat {
+ method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
+ method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
+ method public java.util.Locale? get(int);
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
+ method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
+ method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
+ method public java.util.Locale? getFirstMatch(String![]);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
+ method public boolean isEmpty();
+ method @RequiresApi(21) public static boolean matchesLanguageAndScript(java.util.Locale, java.util.Locale);
+ method @IntRange(from=0) public int size();
+ method public String toLanguageTags();
+ method public Object? unwrap();
+ method @Deprecated @RequiresApi(24) public static androidx.core.os.LocaleListCompat! wrap(Object!);
+ method @RequiresApi(24) public static androidx.core.os.LocaleListCompat wrap(android.os.LocaleList);
+ }
+
+ public final class MessageCompat {
+ method public static boolean isAsynchronous(android.os.Message);
+ method public static void setAsynchronous(android.os.Message, boolean);
+ }
+
+ public class OperationCanceledException extends java.lang.RuntimeException {
+ ctor public OperationCanceledException();
+ ctor public OperationCanceledException(String?);
+ }
+
+ public final class ParcelCompat {
+ method public static <T> Object![]? readArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> java.util.ArrayList<T!>? readArrayList(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static boolean readBoolean(android.os.Parcel);
+ method public static <K, V> java.util.HashMap<K!,V!>? readHashMap(android.os.Parcel, ClassLoader?, Class<? extends K>, Class<? extends V>);
+ method public static <T> void readList(android.os.Parcel, java.util.List<? super T>, ClassLoader?, Class<T!>);
+ method public static <K, V> void readMap(android.os.Parcel, java.util.Map<? super K,? super V>, ClassLoader?, Class<K!>, Class<V!>);
+ method public static <T extends android.os.Parcelable> T? readParcelable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @Deprecated public static <T> T![]? readParcelableArray(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.os.Parcelable![]? readParcelableArrayTyped(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(30) public static <T> android.os.Parcelable.Creator<T!>? readParcelableCreator(android.os.Parcel, ClassLoader?, Class<T!>);
+ method @RequiresApi(api=android.os.Build.VERSION_CODES.Q) public static <T> java.util.List<T!> readParcelableList(android.os.Parcel, java.util.List<T!>, ClassLoader?, Class<T!>);
+ method public static <T extends java.io.Serializable> T? readSerializable(android.os.Parcel, ClassLoader?, Class<T!>);
+ method public static <T> android.util.SparseArray<T!>? readSparseArray(android.os.Parcel, ClassLoader?, Class<? extends T>);
+ method public static void writeBoolean(android.os.Parcel, boolean);
+ }
+
+ @Deprecated public final class ParcelableCompat {
+ method @Deprecated public static <T> android.os.Parcelable.Creator<T!>! newCreator(androidx.core.os.ParcelableCompatCreatorCallbacks<T!>!);
+ }
+
+ @Deprecated public interface ParcelableCompatCreatorCallbacks<T> {
+ method @Deprecated public T! createFromParcel(android.os.Parcel!, ClassLoader!);
+ method @Deprecated public T![]! newArray(int);
+ }
+
+ public final class ProcessCompat {
+ method public static boolean isApplicationUid(int);
+ }
+
+ @Deprecated public final class TraceCompat {
+ method @Deprecated public static void beginAsyncSection(String, int);
+ method @Deprecated public static void beginSection(String);
+ method @Deprecated public static void endAsyncSection(String, int);
+ method @Deprecated public static void endSection();
+ method @Deprecated public static boolean isEnabled();
+ method @Deprecated public static void setCounter(String, int);
+ }
+
+ @RequiresApi(17) public class UserHandleCompat {
+ method public static android.os.UserHandle getUserHandleForUid(int);
+ }
+
+ public class UserManagerCompat {
+ method public static boolean isUserUnlocked(android.content.Context);
+ }
+
+}
+
+package androidx.core.provider {
+
+ public final class DocumentsContractCompat {
+ method public static android.net.Uri? buildChildDocumentsUri(String, String?);
+ method public static android.net.Uri? buildChildDocumentsUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildDocumentUri(String, String);
+ method public static android.net.Uri? buildDocumentUriUsingTree(android.net.Uri, String);
+ method public static android.net.Uri? buildTreeDocumentUri(String, String);
+ method public static android.net.Uri? createDocument(android.content.ContentResolver, android.net.Uri, String, String) throws java.io.FileNotFoundException;
+ method public static String? getDocumentId(android.net.Uri);
+ method public static String? getTreeDocumentId(android.net.Uri);
+ method public static boolean isDocumentUri(android.content.Context, android.net.Uri?);
+ method public static boolean isTreeUri(android.net.Uri);
+ method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+ method public static android.net.Uri? renameDocument(android.content.ContentResolver, android.net.Uri, String) throws java.io.FileNotFoundException;
+ }
+
+ public static final class DocumentsContractCompat.DocumentCompat {
+ field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
+ }
+
+ public final class FontRequest {
+ ctor public FontRequest(String, String, String, java.util.List<java.util.List<byte[]!>!>);
+ ctor public FontRequest(String, String, String, @ArrayRes int);
+ method public java.util.List<java.util.List<byte[]!>!>? getCertificates();
+ method @ArrayRes public int getCertificatesArrayResId();
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public String! getIdentifier();
+ method public String getProviderAuthority();
+ method public String getProviderPackage();
+ method public String getQuery();
+ }
+
+ public class FontsContractCompat {
+ method public static android.graphics.Typeface? buildTypeface(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontsContractCompat.FontInfo![]);
+ method public static androidx.core.provider.FontsContractCompat.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal?, androidx.core.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.graphics.Typeface! getFontSync(android.content.Context!, androidx.core.provider.FontRequest!, androidx.core.content.res.ResourcesCompat.FontCallback?, android.os.Handler?, boolean, int, int);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @VisibleForTesting public static android.content.pm.ProviderInfo? getProvider(android.content.pm.PackageManager, androidx.core.provider.FontRequest, android.content.res.Resources?) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated @RequiresApi(19) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static java.util.Map<android.net.Uri!,java.nio.ByteBuffer!>! prepareFontData(android.content.Context!, androidx.core.provider.FontsContractCompat.FontInfo![]!, android.os.CancellationSignal!);
+ method public static void requestFont(android.content.Context, androidx.core.provider.FontRequest, androidx.core.provider.FontsContractCompat.FontRequestCallback, android.os.Handler);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void resetCache();
+ field @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final String PARCEL_FONT_RESULTS = "font_results";
+ }
+
+ public static final class FontsContractCompat.Columns implements android.provider.BaseColumns {
+ ctor public FontsContractCompat.Columns();
+ field public static final String FILE_ID = "file_id";
+ field public static final String ITALIC = "font_italic";
+ field public static final String RESULT_CODE = "result_code";
+ field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field public static final int RESULT_CODE_OK = 0; // 0x0
+ field public static final String TTC_INDEX = "font_ttc_index";
+ field public static final String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final String WEIGHT = "font_weight";
+ }
+
+ public static class FontsContractCompat.FontFamilyResult {
+ ctor @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public FontsContractCompat.FontFamilyResult(int, androidx.core.provider.FontsContractCompat.FontInfo![]?);
+ method public androidx.core.provider.FontsContractCompat.FontInfo![]! getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContractCompat.FontInfo {
+ ctor @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public FontsContractCompat.FontInfo(android.net.Uri, @IntRange(from=0) int, @IntRange(from=1, to=1000) int, boolean, int);
+ method public int getResultCode();
+ method @IntRange(from=0) public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method @IntRange(from=1, to=1000) public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContractCompat.FontRequestCallback {
+ ctor public FontsContractCompat.FontRequestCallback();
+ method public void onTypefaceRequestFailed(@androidx.core.provider.FontsContractCompat.FontRequestCallback.FontRequestFailReason int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface!);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_SECURITY_VIOLATION = -4; // 0xfffffffc
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ field @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final int RESULT_OK = 0; // 0x0
+ }
+
+ @IntDef({androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_UNAVAILABLE, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_MALFORMED_QUERY, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES, androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_SECURITY_VIOLATION, androidx.core.provider.FontsContractCompat.FontRequestCallback.RESULT_OK}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface FontsContractCompat.FontRequestCallback.FontRequestFailReason {
+ }
+
+ @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SelfDestructiveThread {
+ ctor @Deprecated public SelfDestructiveThread(String!, int, int);
+ method @Deprecated @VisibleForTesting public int getGeneration();
+ method @Deprecated @VisibleForTesting public boolean isRunning();
+ method @Deprecated public <T> void postAndReply(java.util.concurrent.Callable<T!>!, androidx.core.provider.SelfDestructiveThread.ReplyCallback<T!>!);
+ method @Deprecated public <T> T! postAndWait(java.util.concurrent.Callable<T!>!, int) throws java.lang.InterruptedException;
+ }
+
+ @Deprecated public static interface SelfDestructiveThread.ReplyCallback<T> {
+ method @Deprecated public void onReply(T!);
+ }
+
+}
+
+package androidx.core.telephony {
+
+ @RequiresApi(22) public class SubscriptionManagerCompat {
+ method public static int getSlotIndex(int);
+ }
+
+ public class TelephonyManagerCompat {
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static String? getImei(android.telephony.TelephonyManager);
+ method public static int getSubscriptionId(android.telephony.TelephonyManager);
+ }
+
+}
+
+package androidx.core.telephony.mbms {
+
+ public final class MbmsHelper {
+ method public static CharSequence? getBestNameForService(android.content.Context, android.telephony.mbms.ServiceInfo);
+ }
+
+}
+
+package androidx.core.text {
+
+ public final class BidiFormatter {
+ method public static androidx.core.text.BidiFormatter! getInstance();
+ method public static androidx.core.text.BidiFormatter! getInstance(boolean);
+ method public static androidx.core.text.BidiFormatter! getInstance(java.util.Locale!);
+ method public boolean getStereoReset();
+ method public boolean isRtl(String!);
+ method public boolean isRtl(CharSequence!);
+ method public boolean isRtlContext();
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!, boolean);
+ method public String! unicodeWrap(String!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public CharSequence! unicodeWrap(CharSequence!, androidx.core.text.TextDirectionHeuristicCompat!);
+ method public String! unicodeWrap(String!, boolean);
+ method public CharSequence! unicodeWrap(CharSequence!, boolean);
+ method public String! unicodeWrap(String!);
+ method public CharSequence! unicodeWrap(CharSequence!);
+ }
+
+ public static final class BidiFormatter.Builder {
+ ctor public BidiFormatter.Builder();
+ ctor public BidiFormatter.Builder(boolean);
+ ctor public BidiFormatter.Builder(java.util.Locale!);
+ method public androidx.core.text.BidiFormatter! build();
+ method public androidx.core.text.BidiFormatter.Builder! setTextDirectionHeuristic(androidx.core.text.TextDirectionHeuristicCompat!);
+ method public androidx.core.text.BidiFormatter.Builder! stereoReset(boolean);
+ }
+
+ public final class HtmlCompat {
+ method public static android.text.Spanned fromHtml(String, int);
+ method public static android.text.Spanned fromHtml(String, int, android.text.Html.ImageGetter?, android.text.Html.TagHandler?);
+ method public static String toHtml(android.text.Spanned, int);
+ field public static final int FROM_HTML_MODE_COMPACT = 63; // 0x3f
+ field public static final int FROM_HTML_MODE_LEGACY = 0; // 0x0
+ field public static final int FROM_HTML_OPTION_USE_CSS_COLORS = 256; // 0x100
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE = 32; // 0x20
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_DIV = 16; // 0x10
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_HEADING = 2; // 0x2
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST = 8; // 0x8
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM = 4; // 0x4
+ field public static final int FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH = 1; // 0x1
+ field public static final int TO_HTML_PARAGRAPH_LINES_CONSECUTIVE = 0; // 0x0
+ field public static final int TO_HTML_PARAGRAPH_LINES_INDIVIDUAL = 1; // 0x1
+ }
+
+ public final class ICUCompat {
+ method public static String? maximizeAndGetScript(java.util.Locale);
+ }
+
+ public class PrecomputedTextCompat implements android.text.Spannable {
+ method public char charAt(int);
+ method public static androidx.core.text.PrecomputedTextCompat! create(CharSequence, androidx.core.text.PrecomputedTextCompat.Params);
+ method @IntRange(from=0) public int getParagraphCount();
+ method @IntRange(from=0) public int getParagraphEnd(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getParagraphStart(@IntRange(from=0) int);
+ method public androidx.core.text.PrecomputedTextCompat.Params getParams();
+ method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.text.PrecomputedText? getPrecomputedText();
+ method public int getSpanEnd(Object!);
+ method public int getSpanFlags(Object!);
+ method public int getSpanStart(Object!);
+ method public <T> T![]! getSpans(int, int, Class<T!>!);
+ method @UiThread public static java.util.concurrent.Future<androidx.core.text.PrecomputedTextCompat!>! getTextFuture(CharSequence, androidx.core.text.PrecomputedTextCompat.Params, java.util.concurrent.Executor?);
+ method public int length();
+ method public int nextSpanTransition(int, int, Class!);
+ method public void removeSpan(Object!);
+ method public void setSpan(Object!, int, int, int);
+ method public CharSequence! subSequence(int, int);
+ }
+
+ public static final class PrecomputedTextCompat.Params {
+ ctor @RequiresApi(28) public PrecomputedTextCompat.Params(android.text.PrecomputedText.Params);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean equalsWithoutTextDirection(androidx.core.text.PrecomputedTextCompat.Params);
+ method @RequiresApi(23) public int getBreakStrategy();
+ method @RequiresApi(23) public int getHyphenationFrequency();
+ method @RequiresApi(18) public android.text.TextDirectionHeuristic? getTextDirection();
+ method public android.text.TextPaint getTextPaint();
+ }
+
+ public static class PrecomputedTextCompat.Params.Builder {
+ ctor public PrecomputedTextCompat.Params.Builder(android.text.TextPaint);
+ method public androidx.core.text.PrecomputedTextCompat.Params build();
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setBreakStrategy(int);
+ method @RequiresApi(23) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setHyphenationFrequency(int);
+ method @RequiresApi(18) public androidx.core.text.PrecomputedTextCompat.Params.Builder! setTextDirection(android.text.TextDirectionHeuristic);
+ }
+
+ public interface TextDirectionHeuristicCompat {
+ method public boolean isRtl(char[]!, int, int);
+ method public boolean isRtl(CharSequence!, int, int);
+ }
+
+ public final class TextDirectionHeuristicsCompat {
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! ANYRTL_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! FIRSTSTRONG_RTL;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LOCALE;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! LTR;
+ field public static final androidx.core.text.TextDirectionHeuristicCompat! RTL;
+ }
+
+ public final class TextUtilsCompat {
+ method public static int getLayoutDirectionFromLocale(java.util.Locale?);
+ method public static String htmlEncode(String);
+ }
+
+}
+
+package androidx.core.text.util {
+
+ public final class LinkifyCompat {
+ method public static boolean addLinks(android.text.Spannable, @androidx.core.text.util.LinkifyCompat.LinkifyMask int);
+ method public static boolean addLinks(android.widget.TextView, @androidx.core.text.util.LinkifyCompat.LinkifyMask int);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static void addLinks(android.widget.TextView, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ method public static boolean addLinks(android.text.Spannable, java.util.regex.Pattern, String?, String![]?, android.text.util.Linkify.MatchFilter?, android.text.util.Linkify.TransformFilter?);
+ }
+
+ @IntDef(flag=true, value={android.text.util.Linkify.WEB_URLS, android.text.util.Linkify.EMAIL_ADDRESSES, android.text.util.Linkify.PHONE_NUMBERS, android.text.util.Linkify.MAP_ADDRESSES, android.text.util.Linkify.ALL}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface LinkifyCompat.LinkifyMask {
+ }
+
+}
+
+package androidx.core.util {
+
+ public class AtomicFile {
+ ctor public AtomicFile(java.io.File);
+ method public void delete();
+ method public void failWrite(java.io.FileOutputStream?);
+ method public void finishWrite(java.io.FileOutputStream?);
+ method public java.io.File getBaseFile();
+ method public java.io.FileInputStream openRead() throws java.io.FileNotFoundException;
+ method public byte[] readFully() throws java.io.IOException;
+ method public java.io.FileOutputStream startWrite() throws java.io.IOException;
+ }
+
+ public interface Consumer<T> {
+ method public void accept(T!);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class DebugUtils {
+ method public static void buildShortClassTag(Object!, StringBuilder!);
+ }
+
+ @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class LogWriter extends java.io.Writer {
+ ctor @Deprecated public LogWriter(String!);
+ method @Deprecated public void close();
+ method @Deprecated public void flush();
+ method @Deprecated public void write(char[]!, int, int);
+ }
+
+ public class ObjectsCompat {
+ method public static boolean equals(Object?, Object?);
+ method public static int hash(java.lang.Object!...);
+ method public static int hashCode(Object?);
+ method public static <T> T requireNonNull(T?);
+ method public static <T> T requireNonNull(T?, String);
+ method public static String? toString(Object?, String?);
+ }
+
+ public class Pair<F, S> {
+ ctor public Pair(F!, S!);
+ method public static <A, B> androidx.core.util.Pair<A!,B!> create(A!, B!);
+ field public final F! first;
+ field public final S! second;
+ }
+
+ public final class PatternsCompat {
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_EMAIL_ADDRESS;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
+ }
+
+ public final class Pools {
+ }
+
+ public static interface Pools.Pool<T> {
+ method public T? acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SimplePool<T> implements androidx.core.util.Pools.Pool<T> {
+ ctor public Pools.SimplePool(int);
+ method public T! acquire();
+ method public boolean release(T);
+ }
+
+ public static class Pools.SynchronizedPool<T> extends androidx.core.util.Pools.SimplePool<T> {
+ ctor public Pools.SynchronizedPool(int);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class Preconditions {
+ method public static void checkArgument(boolean);
+ method public static void checkArgument(boolean, Object);
+ method public static void checkArgument(boolean, String, java.lang.Object!...);
+ method public static float checkArgumentFinite(float, String);
+ method public static int checkArgumentInRange(int, int, int, String);
+ method public static long checkArgumentInRange(long, long, long, String);
+ method public static float checkArgumentInRange(float, float, float, String);
+ method public static double checkArgumentInRange(double, double, double, String);
+ method @IntRange(from=0) public static int checkArgumentNonnegative(int, String?);
+ method @IntRange(from=0) public static int checkArgumentNonnegative(int);
+ method public static int checkFlagsArgument(int, int);
+ method public static <T> T checkNotNull(T?);
+ method public static <T> T checkNotNull(T?, Object);
+ method public static void checkState(boolean, String?);
+ method public static void checkState(boolean);
+ method public static <T extends java.lang.CharSequence> T checkStringNotEmpty(T?);
+ method public static <T extends java.lang.CharSequence> T checkStringNotEmpty(T?, Object);
+ method public static <T extends java.lang.CharSequence> T checkStringNotEmpty(T?, String, java.lang.Object!...);
+ }
+
+ public interface Predicate<T> {
+ method public default androidx.core.util.Predicate<T!>! and(androidx.core.util.Predicate<? super T>!);
+ method public static <T> androidx.core.util.Predicate<T!>! isEqual(Object!);
+ method public default androidx.core.util.Predicate<T!>! negate();
+ method public static <T> androidx.core.util.Predicate<T!>! not(androidx.core.util.Predicate<? super T>!);
+ method public default androidx.core.util.Predicate<T!>! or(androidx.core.util.Predicate<? super T>!);
+ method public boolean test(T!);
+ }
+
+ public final class SizeFCompat {
+ ctor public SizeFCompat(float, float);
+ method public float getHeight();
+ method public float getWidth();
+ method @RequiresApi(21) public android.util.SizeF toSizeF();
+ method @RequiresApi(21) public static androidx.core.util.SizeFCompat toSizeFCompat(android.util.SizeF);
+ }
+
+ public interface Supplier<T> {
+ method public T! get();
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class TimeUtils {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void formatDuration(long, StringBuilder!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void formatDuration(long, java.io.PrintWriter!, int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void formatDuration(long, java.io.PrintWriter!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void formatDuration(long, long, java.io.PrintWriter!);
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final int HUNDRED_DAY_FIELD_LEN = 19; // 0x13
+ }
+
+}
+
+package androidx.core.view {
+
+ public class AccessibilityDelegateCompat {
+ ctor public AccessibilityDelegateCompat();
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public AccessibilityDelegateCompat(android.view.View.AccessibilityDelegate);
+ method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+ method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public void sendAccessibilityEvent(android.view.View, int);
+ method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
+ }
+
+ public abstract class ActionProvider {
+ ctor public ActionProvider(android.content.Context);
+ method public android.content.Context getContext();
+ method public boolean hasSubMenu();
+ method public boolean isVisible();
+ method public abstract android.view.View onCreateActionView();
+ method public android.view.View onCreateActionView(android.view.MenuItem);
+ method public boolean onPerformDefaultAction();
+ method public void onPrepareSubMenu(android.view.SubMenu);
+ method public boolean overridesItemVisibility();
+ method public void refreshVisibility();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void reset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSubUiVisibilityListener(androidx.core.view.ActionProvider.SubUiVisibilityListener?);
+ method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void subUiVisibilityChanged(boolean);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static interface ActionProvider.SubUiVisibilityListener {
+ method public void onSubUiVisibilityChanged(boolean);
+ }
+
+ public static interface ActionProvider.VisibilityListener {
+ method public void onActionProviderVisibilityChanged(boolean);
+ }
+
+ public final class ContentInfoCompat {
+ method public android.content.ClipData getClip();
+ method public android.os.Bundle? getExtras();
+ method @androidx.core.view.ContentInfoCompat.Flags public int getFlags();
+ method public android.net.Uri? getLinkUri();
+ method @androidx.core.view.ContentInfoCompat.Source public int getSource();
+ method public android.util.Pair<androidx.core.view.ContentInfoCompat!,androidx.core.view.ContentInfoCompat!> partition(androidx.core.util.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public static android.util.Pair<android.view.ContentInfo!,android.view.ContentInfo!> partition(android.view.ContentInfo, java.util.function.Predicate<android.content.ClipData.Item!>);
+ method @RequiresApi(31) public android.view.ContentInfo toContentInfo();
+ method @RequiresApi(31) public static androidx.core.view.ContentInfoCompat toContentInfoCompat(android.view.ContentInfo);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_APP = 0; // 0x0
+ field public static final int SOURCE_AUTOFILL = 4; // 0x4
+ field public static final int SOURCE_CLIPBOARD = 1; // 0x1
+ field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3
+ field public static final int SOURCE_INPUT_METHOD = 2; // 0x2
+ field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5
+ }
+
+ public static final class ContentInfoCompat.Builder {
+ ctor public ContentInfoCompat.Builder(androidx.core.view.ContentInfoCompat);
+ ctor public ContentInfoCompat.Builder(android.content.ClipData, @androidx.core.view.ContentInfoCompat.Source int);
+ method public androidx.core.view.ContentInfoCompat build();
+ method public androidx.core.view.ContentInfoCompat.Builder setClip(android.content.ClipData);
+ method public androidx.core.view.ContentInfoCompat.Builder setExtras(android.os.Bundle?);
+ method public androidx.core.view.ContentInfoCompat.Builder setFlags(@androidx.core.view.ContentInfoCompat.Flags int);
+ method public androidx.core.view.ContentInfoCompat.Builder setLinkUri(android.net.Uri?);
+ method public androidx.core.view.ContentInfoCompat.Builder setSource(@androidx.core.view.ContentInfoCompat.Source int);
+ }
+
+ @IntDef(flag=true, value={androidx.core.view.ContentInfoCompat.FLAG_CONVERT_TO_PLAIN_TEXT}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ContentInfoCompat.Flags {
+ }
+
+ @IntDef({androidx.core.view.ContentInfoCompat.SOURCE_APP, androidx.core.view.ContentInfoCompat.SOURCE_CLIPBOARD, androidx.core.view.ContentInfoCompat.SOURCE_INPUT_METHOD, androidx.core.view.ContentInfoCompat.SOURCE_DRAG_AND_DROP, androidx.core.view.ContentInfoCompat.SOURCE_AUTOFILL, androidx.core.view.ContentInfoCompat.SOURCE_PROCESS_TEXT}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ContentInfoCompat.Source {
+ }
+
+ public final class DisplayCompat {
+ method public static androidx.core.view.DisplayCompat.ModeCompat getMode(android.content.Context, android.view.Display);
+ method public static androidx.core.view.DisplayCompat.ModeCompat![] getSupportedModes(android.content.Context, android.view.Display);
+ }
+
+ public static final class DisplayCompat.ModeCompat {
+ method public int getPhysicalHeight();
+ method public int getPhysicalWidth();
+ method @Deprecated public boolean isNative();
+ method @RequiresApi(android.os.Build.VERSION_CODES.M) public android.view.Display.Mode? toMode();
+ }
+
+ public final class DisplayCutoutCompat {
+ ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
+ ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
+ method public java.util.List<android.graphics.Rect!> getBoundingRects();
+ method public int getSafeInsetBottom();
+ method public int getSafeInsetLeft();
+ method public int getSafeInsetRight();
+ method public int getSafeInsetTop();
+ method public androidx.core.graphics.Insets getWaterfallInsets();
+ }
+
+ public final class DragAndDropPermissionsCompat {
+ method public void release();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.view.DragAndDropPermissionsCompat? request(android.app.Activity, android.view.DragEvent);
+ }
+
+ public class DragStartHelper {
+ ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
+ method public void attach();
+ method public void detach();
+ method public void getTouchPosition(android.graphics.Point);
+ method public boolean onLongClick(android.view.View);
+ method public boolean onTouch(android.view.View, android.view.MotionEvent);
+ }
+
+ public static interface DragStartHelper.OnDragStartListener {
+ method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
+ }
+
+ public final class GestureDetectorCompat {
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener);
+ ctor public GestureDetectorCompat(android.content.Context, android.view.GestureDetector.OnGestureListener, android.os.Handler?);
+ method public boolean isLongpressEnabled();
+ method public boolean onTouchEvent(android.view.MotionEvent);
+ method public void setIsLongpressEnabled(boolean);
+ method public void setOnDoubleTapListener(android.view.GestureDetector.OnDoubleTapListener?);
+ }
+
+ public final class GravityCompat {
+ method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
+ method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+ method public static int getAbsoluteGravity(int, int);
+ field public static final int END = 8388613; // 0x800005
+ field public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = 8388615; // 0x800007
+ field public static final int RELATIVE_LAYOUT_DIRECTION = 8388608; // 0x800000
+ field public static final int START = 8388611; // 0x800003
+ }
+
+ public final class InputDeviceCompat {
+ field public static final int SOURCE_ANY = -256; // 0xffffff00
+ field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
+ field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
+ field public static final int SOURCE_CLASS_MASK = 255; // 0xff
+ field public static final int SOURCE_CLASS_NONE = 0; // 0x0
+ field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
+ field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
+ field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
+ field public static final int SOURCE_DPAD = 513; // 0x201
+ field public static final int SOURCE_GAMEPAD = 1025; // 0x401
+ field public static final int SOURCE_HDMI = 33554433; // 0x2000001
+ field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
+ field public static final int SOURCE_KEYBOARD = 257; // 0x101
+ field public static final int SOURCE_MOUSE = 8194; // 0x2002
+ field public static final int SOURCE_ROTARY_ENCODER = 4194304; // 0x400000
+ field public static final int SOURCE_STYLUS = 16386; // 0x4002
+ field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
+ field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
+ field public static final int SOURCE_TOUCH_NAVIGATION = 2097152; // 0x200000
+ field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
+ field public static final int SOURCE_UNKNOWN = 0; // 0x0
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class KeyEventDispatcher {
+ method public static boolean dispatchBeforeHierarchy(android.view.View, android.view.KeyEvent);
+ method public static boolean dispatchKeyEvent(androidx.core.view.KeyEventDispatcher.Component, android.view.View?, android.view.Window.Callback?, android.view.KeyEvent);
+ }
+
+ public static interface KeyEventDispatcher.Component {
+ method public boolean superDispatchKeyEvent(android.view.KeyEvent);
+ }
+
+ public final class LayoutInflaterCompat {
+ method @Deprecated public static androidx.core.view.LayoutInflaterFactory! getFactory(android.view.LayoutInflater!);
+ method @Deprecated public static void setFactory(android.view.LayoutInflater, androidx.core.view.LayoutInflaterFactory);
+ method public static void setFactory2(android.view.LayoutInflater, android.view.LayoutInflater.Factory2);
+ }
+
+ @Deprecated public interface LayoutInflaterFactory {
+ method @Deprecated public android.view.View! onCreateView(android.view.View!, String!, android.content.Context!, android.util.AttributeSet!);
+ }
+
+ public final class MarginLayoutParamsCompat {
+ method public static int getLayoutDirection(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginEnd(android.view.ViewGroup.MarginLayoutParams);
+ method public static int getMarginStart(android.view.ViewGroup.MarginLayoutParams);
+ method public static boolean isMarginRelative(android.view.ViewGroup.MarginLayoutParams);
+ method public static void resolveLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setLayoutDirection(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginEnd(android.view.ViewGroup.MarginLayoutParams, int);
+ method public static void setMarginStart(android.view.ViewGroup.MarginLayoutParams, int);
+ }
+
+ public final class MenuCompat {
+ method public static void setGroupDividerEnabled(android.view.Menu, boolean);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ }
+
+ public interface MenuHost {
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void invalidateMenu();
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public class MenuHostHelper {
+ ctor public MenuHostHelper(Runnable);
+ method public void addMenuProvider(androidx.core.view.MenuProvider);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner);
+ method public void addMenuProvider(androidx.core.view.MenuProvider, androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State);
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public void onPrepareMenu(android.view.Menu);
+ method public void removeMenuProvider(androidx.core.view.MenuProvider);
+ }
+
+ public final class MenuItemCompat {
+ method @Deprecated public static boolean collapseActionView(android.view.MenuItem!);
+ method @Deprecated public static boolean expandActionView(android.view.MenuItem!);
+ method public static androidx.core.view.ActionProvider? getActionProvider(android.view.MenuItem);
+ method @Deprecated public static android.view.View! getActionView(android.view.MenuItem!);
+ method public static int getAlphabeticModifiers(android.view.MenuItem);
+ method public static CharSequence? getContentDescription(android.view.MenuItem);
+ method public static android.content.res.ColorStateList? getIconTintList(android.view.MenuItem);
+ method public static android.graphics.PorterDuff.Mode? getIconTintMode(android.view.MenuItem);
+ method public static int getNumericModifiers(android.view.MenuItem);
+ method public static CharSequence? getTooltipText(android.view.MenuItem);
+ method @Deprecated public static boolean isActionViewExpanded(android.view.MenuItem!);
+ method public static android.view.MenuItem? setActionProvider(android.view.MenuItem, androidx.core.view.ActionProvider?);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, android.view.View!);
+ method @Deprecated public static android.view.MenuItem! setActionView(android.view.MenuItem!, int);
+ method public static void setAlphabeticShortcut(android.view.MenuItem, char, int);
+ method public static void setContentDescription(android.view.MenuItem, CharSequence?);
+ method public static void setIconTintList(android.view.MenuItem, android.content.res.ColorStateList?);
+ method public static void setIconTintMode(android.view.MenuItem, android.graphics.PorterDuff.Mode?);
+ method public static void setNumericShortcut(android.view.MenuItem, char, int);
+ method @Deprecated public static android.view.MenuItem! setOnActionExpandListener(android.view.MenuItem!, androidx.core.view.MenuItemCompat.OnActionExpandListener!);
+ method public static void setShortcut(android.view.MenuItem, char, char, int, int);
+ method @Deprecated public static void setShowAsAction(android.view.MenuItem!, int);
+ method public static void setTooltipText(android.view.MenuItem, CharSequence?);
+ field @Deprecated public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+ field @Deprecated public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
+ field @Deprecated public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
+ field @Deprecated public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
+ field @Deprecated public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
+ }
+
+ @Deprecated public static interface MenuItemCompat.OnActionExpandListener {
+ method @Deprecated public boolean onMenuItemActionCollapse(android.view.MenuItem!);
+ method @Deprecated public boolean onMenuItemActionExpand(android.view.MenuItem!);
+ }
+
+ public interface MenuProvider {
+ method public void onCreateMenu(android.view.Menu, android.view.MenuInflater);
+ method public default void onMenuClosed(android.view.Menu);
+ method public boolean onMenuItemSelected(android.view.MenuItem);
+ method public default void onPrepareMenu(android.view.Menu);
+ }
+
+ public final class MotionEventCompat {
+ method @Deprecated public static int findPointerIndex(android.view.MotionEvent!, int);
+ method @Deprecated public static int getActionIndex(android.view.MotionEvent!);
+ method @Deprecated public static int getActionMasked(android.view.MotionEvent!);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int);
+ method @Deprecated public static float getAxisValue(android.view.MotionEvent!, int, int);
+ method @Deprecated public static int getButtonState(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerCount(android.view.MotionEvent!);
+ method @Deprecated public static int getPointerId(android.view.MotionEvent!, int);
+ method @Deprecated public static int getSource(android.view.MotionEvent!);
+ method @Deprecated public static float getX(android.view.MotionEvent!, int);
+ method @Deprecated public static float getY(android.view.MotionEvent!, int);
+ method public static boolean isFromSource(android.view.MotionEvent, int);
+ field @Deprecated public static final int ACTION_HOVER_ENTER = 9; // 0x9
+ field @Deprecated public static final int ACTION_HOVER_EXIT = 10; // 0xa
+ field @Deprecated public static final int ACTION_HOVER_MOVE = 7; // 0x7
+ field @Deprecated public static final int ACTION_MASK = 255; // 0xff
+ field @Deprecated public static final int ACTION_POINTER_DOWN = 5; // 0x5
+ field @Deprecated public static final int ACTION_POINTER_INDEX_MASK = 65280; // 0xff00
+ field @Deprecated public static final int ACTION_POINTER_INDEX_SHIFT = 8; // 0x8
+ field @Deprecated public static final int ACTION_POINTER_UP = 6; // 0x6
+ field @Deprecated public static final int ACTION_SCROLL = 8; // 0x8
+ field @Deprecated public static final int AXIS_BRAKE = 23; // 0x17
+ field @Deprecated public static final int AXIS_DISTANCE = 24; // 0x18
+ field @Deprecated public static final int AXIS_GAS = 22; // 0x16
+ field @Deprecated public static final int AXIS_GENERIC_1 = 32; // 0x20
+ field @Deprecated public static final int AXIS_GENERIC_10 = 41; // 0x29
+ field @Deprecated public static final int AXIS_GENERIC_11 = 42; // 0x2a
+ field @Deprecated public static final int AXIS_GENERIC_12 = 43; // 0x2b
+ field @Deprecated public static final int AXIS_GENERIC_13 = 44; // 0x2c
+ field @Deprecated public static final int AXIS_GENERIC_14 = 45; // 0x2d
+ field @Deprecated public static final int AXIS_GENERIC_15 = 46; // 0x2e
+ field @Deprecated public static final int AXIS_GENERIC_16 = 47; // 0x2f
+ field @Deprecated public static final int AXIS_GENERIC_2 = 33; // 0x21
+ field @Deprecated public static final int AXIS_GENERIC_3 = 34; // 0x22
+ field @Deprecated public static final int AXIS_GENERIC_4 = 35; // 0x23
+ field @Deprecated public static final int AXIS_GENERIC_5 = 36; // 0x24
+ field @Deprecated public static final int AXIS_GENERIC_6 = 37; // 0x25
+ field @Deprecated public static final int AXIS_GENERIC_7 = 38; // 0x26
+ field @Deprecated public static final int AXIS_GENERIC_8 = 39; // 0x27
+ field @Deprecated public static final int AXIS_GENERIC_9 = 40; // 0x28
+ field @Deprecated public static final int AXIS_HAT_X = 15; // 0xf
+ field @Deprecated public static final int AXIS_HAT_Y = 16; // 0x10
+ field @Deprecated public static final int AXIS_HSCROLL = 10; // 0xa
+ field @Deprecated public static final int AXIS_LTRIGGER = 17; // 0x11
+ field @Deprecated public static final int AXIS_ORIENTATION = 8; // 0x8
+ field @Deprecated public static final int AXIS_PRESSURE = 2; // 0x2
+ field public static final int AXIS_RELATIVE_X = 27; // 0x1b
+ field public static final int AXIS_RELATIVE_Y = 28; // 0x1c
+ field @Deprecated public static final int AXIS_RTRIGGER = 18; // 0x12
+ field @Deprecated public static final int AXIS_RUDDER = 20; // 0x14
+ field @Deprecated public static final int AXIS_RX = 12; // 0xc
+ field @Deprecated public static final int AXIS_RY = 13; // 0xd
+ field @Deprecated public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
+ field @Deprecated public static final int AXIS_SIZE = 3; // 0x3
+ field @Deprecated public static final int AXIS_THROTTLE = 19; // 0x13
+ field @Deprecated public static final int AXIS_TILT = 25; // 0x19
+ field @Deprecated public static final int AXIS_TOOL_MAJOR = 6; // 0x6
+ field @Deprecated public static final int AXIS_TOOL_MINOR = 7; // 0x7
+ field @Deprecated public static final int AXIS_TOUCH_MAJOR = 4; // 0x4
+ field @Deprecated public static final int AXIS_TOUCH_MINOR = 5; // 0x5
+ field @Deprecated public static final int AXIS_VSCROLL = 9; // 0x9
+ field @Deprecated public static final int AXIS_WHEEL = 21; // 0x15
+ field @Deprecated public static final int AXIS_X = 0; // 0x0
+ field @Deprecated public static final int AXIS_Y = 1; // 0x1
+ field @Deprecated public static final int AXIS_Z = 11; // 0xb
+ field @Deprecated public static final int BUTTON_PRIMARY = 1; // 0x1
+ }
+
+ public interface NestedScrollingChild {
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean isNestedScrollingEnabled();
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(@androidx.core.view.ViewCompat.ScrollAxis int);
+ method public void stopNestedScroll();
+ }
+
+ public interface NestedScrollingChild2 extends androidx.core.view.NestedScrollingChild {
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean hasNestedScrollingParent(@androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean startNestedScroll(@androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void stopNestedScroll(@androidx.core.view.ViewCompat.NestedScrollType int);
+ }
+
+ public interface NestedScrollingChild3 extends androidx.core.view.NestedScrollingChild2 {
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int, int[]);
+ }
+
+ public class NestedScrollingChildHelper {
+ ctor public NestedScrollingChildHelper(android.view.View);
+ method public boolean dispatchNestedFling(float, float, boolean);
+ method public boolean dispatchNestedPreFling(float, float);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?);
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int, int[]?);
+ method public boolean hasNestedScrollingParent();
+ method public boolean hasNestedScrollingParent(@androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean isNestedScrollingEnabled();
+ method public void onDetachedFromWindow();
+ method public void onStopNestedScroll(android.view.View);
+ method public void setNestedScrollingEnabled(boolean);
+ method public boolean startNestedScroll(@androidx.core.view.ViewCompat.ScrollAxis int);
+ method public boolean startNestedScroll(@androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void stopNestedScroll();
+ method public void stopNestedScroll(@androidx.core.view.ViewCompat.NestedScrollType int);
+ }
+
+ public interface NestedScrollingParent {
+ method @androidx.core.view.ViewCompat.ScrollAxis public int getNestedScrollAxes();
+ method public boolean onNestedFling(android.view.View, float, float, boolean);
+ method public boolean onNestedPreFling(android.view.View, float, float);
+ method public void onNestedPreScroll(android.view.View, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int);
+ method public void onStopNestedScroll(android.view.View);
+ }
+
+ public interface NestedScrollingParent2 extends androidx.core.view.NestedScrollingParent {
+ method public void onNestedPreScroll(android.view.View, int, int, int[], @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void onStopNestedScroll(android.view.View, @androidx.core.view.ViewCompat.NestedScrollType int);
+ }
+
+ public interface NestedScrollingParent3 extends androidx.core.view.NestedScrollingParent2 {
+ method public void onNestedScroll(android.view.View, int, int, int, int, @androidx.core.view.ViewCompat.NestedScrollType int, int[]);
+ }
+
+ public class NestedScrollingParentHelper {
+ ctor public NestedScrollingParentHelper(android.view.ViewGroup);
+ method @androidx.core.view.ViewCompat.ScrollAxis public int getNestedScrollAxes();
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public void onStopNestedScroll(android.view.View);
+ method public void onStopNestedScroll(android.view.View, @androidx.core.view.ViewCompat.NestedScrollType int);
+ }
+
+ public interface OnApplyWindowInsetsListener {
+ method public androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ }
+
+ public interface OnReceiveContentListener {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ }
+
+ public interface OnReceiveContentViewBehavior {
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(androidx.core.view.ContentInfoCompat);
+ }
+
+ public final class OneShotPreDrawListener implements android.view.View.OnAttachStateChangeListener android.view.ViewTreeObserver.OnPreDrawListener {
+ method public static androidx.core.view.OneShotPreDrawListener add(android.view.View, Runnable);
+ method public boolean onPreDraw();
+ method public void onViewAttachedToWindow(android.view.View);
+ method public void onViewDetachedFromWindow(android.view.View);
+ method public void removeListener();
+ }
+
+ public final class PointerIconCompat {
+ method public static androidx.core.view.PointerIconCompat create(android.graphics.Bitmap, float, float);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public Object? getPointerIcon();
+ method public static androidx.core.view.PointerIconCompat getSystemIcon(android.content.Context, int);
+ method public static androidx.core.view.PointerIconCompat load(android.content.res.Resources, int);
+ field public static final int TYPE_ALIAS = 1010; // 0x3f2
+ field public static final int TYPE_ALL_SCROLL = 1013; // 0x3f5
+ field public static final int TYPE_ARROW = 1000; // 0x3e8
+ field public static final int TYPE_CELL = 1006; // 0x3ee
+ field public static final int TYPE_CONTEXT_MENU = 1001; // 0x3e9
+ field public static final int TYPE_COPY = 1011; // 0x3f3
+ field public static final int TYPE_CROSSHAIR = 1007; // 0x3ef
+ field public static final int TYPE_DEFAULT = 1000; // 0x3e8
+ field public static final int TYPE_GRAB = 1020; // 0x3fc
+ field public static final int TYPE_GRABBING = 1021; // 0x3fd
+ field public static final int TYPE_HAND = 1002; // 0x3ea
+ field public static final int TYPE_HELP = 1003; // 0x3eb
+ field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+ field public static final int TYPE_NO_DROP = 1012; // 0x3f4
+ field public static final int TYPE_NULL = 0; // 0x0
+ field public static final int TYPE_TEXT = 1008; // 0x3f0
+ field public static final int TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+ field public static final int TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+ field public static final int TYPE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+ field public static final int TYPE_VERTICAL_TEXT = 1009; // 0x3f1
+ field public static final int TYPE_WAIT = 1004; // 0x3ec
+ field public static final int TYPE_ZOOM_IN = 1018; // 0x3fa
+ field public static final int TYPE_ZOOM_OUT = 1019; // 0x3fb
+ }
+
+ public final class ScaleGestureDetectorCompat {
+ method @Deprecated public static boolean isQuickScaleEnabled(Object!);
+ method public static boolean isQuickScaleEnabled(android.view.ScaleGestureDetector);
+ method @Deprecated public static void setQuickScaleEnabled(Object!, boolean);
+ method public static void setQuickScaleEnabled(android.view.ScaleGestureDetector, boolean);
+ }
+
+ public interface ScrollingView {
+ method public int computeHorizontalScrollExtent();
+ method public int computeHorizontalScrollOffset();
+ method public int computeHorizontalScrollRange();
+ method public int computeVerticalScrollExtent();
+ method public int computeVerticalScrollOffset();
+ method public int computeVerticalScrollRange();
+ }
+
+ public interface TintableBackgroundView {
+ method public android.content.res.ColorStateList? getSupportBackgroundTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
+ method public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
+ method public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ @Deprecated public final class VelocityTrackerCompat {
+ method @Deprecated public static float getXVelocity(android.view.VelocityTracker!, int);
+ method @Deprecated public static float getYVelocity(android.view.VelocityTracker!, int);
+ }
+
+ public class ViewCompat {
+ ctor @Deprecated protected ViewCompat();
+ method public static int addAccessibilityAction(android.view.View, CharSequence, androidx.core.view.accessibility.AccessibilityViewCommand);
+ method public static void addKeyboardNavigationClusters(android.view.View, java.util.Collection<android.view.View!>, int);
+ method public static void addOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static androidx.core.view.ViewPropertyAnimatorCompat animate(android.view.View);
+ method @Deprecated public static boolean canScrollHorizontally(android.view.View!, int);
+ method @Deprecated public static boolean canScrollVertically(android.view.View!, int);
+ method public static void cancelDragAndDrop(android.view.View);
+ method @Deprecated public static int combineMeasuredStates(int, int);
+ method public static androidx.core.view.WindowInsetsCompat computeSystemWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat, android.graphics.Rect);
+ method public static androidx.core.view.WindowInsetsCompat dispatchApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method public static void dispatchFinishTemporaryDetach(android.view.View);
+ method public static boolean dispatchNestedFling(android.view.View, float, float, boolean);
+ method public static boolean dispatchNestedPreFling(android.view.View, float, float);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?);
+ method public static boolean dispatchNestedPreScroll(android.view.View, int, int, int[]?, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?);
+ method public static void dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int, int[]);
+ method public static boolean dispatchNestedScroll(android.view.View, int, int, int, int, int[]?, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public static void dispatchStartTemporaryDetach(android.view.View);
+ method public static void enableAccessibleClickableSpanSupport(android.view.View);
+ method public static int generateViewId();
+ method public static androidx.core.view.AccessibilityDelegateCompat? getAccessibilityDelegate(android.view.View);
+ method public static int getAccessibilityLiveRegion(android.view.View);
+ method public static androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+ method @UiThread public static CharSequence? getAccessibilityPaneTitle(android.view.View);
+ method @Deprecated public static float getAlpha(android.view.View!);
+ method public static android.content.res.ColorStateList? getBackgroundTintList(android.view.View);
+ method public static android.graphics.PorterDuff.Mode? getBackgroundTintMode(android.view.View);
+ method public static android.graphics.Rect? getClipBounds(android.view.View);
+ method public static android.view.Display? getDisplay(android.view.View);
+ method public static float getElevation(android.view.View);
+ method public static boolean getFitsSystemWindows(android.view.View);
+ method public static int getImportantForAccessibility(android.view.View);
+ method public static int getImportantForAutofill(android.view.View);
+ method public static int getLabelFor(android.view.View);
+ method @Deprecated public static int getLayerType(android.view.View!);
+ method public static int getLayoutDirection(android.view.View);
+ method @Deprecated public static android.graphics.Matrix? getMatrix(android.view.View!);
+ method @Deprecated public static int getMeasuredHeightAndState(android.view.View!);
+ method @Deprecated public static int getMeasuredState(android.view.View!);
+ method @Deprecated public static int getMeasuredWidthAndState(android.view.View!);
+ method public static int getMinimumHeight(android.view.View);
+ method public static int getMinimumWidth(android.view.View);
+ method public static int getNextClusterForwardId(android.view.View);
+ method public static String![]? getOnReceiveContentMimeTypes(android.view.View);
+ method @Deprecated public static int getOverScrollMode(android.view.View!);
+ method @Px public static int getPaddingEnd(android.view.View);
+ method @Px public static int getPaddingStart(android.view.View);
+ method public static android.view.ViewParent? getParentForAccessibility(android.view.View);
+ method @Deprecated public static float getPivotX(android.view.View!);
+ method @Deprecated public static float getPivotY(android.view.View!);
+ method public static androidx.core.view.WindowInsetsCompat? getRootWindowInsets(android.view.View);
+ method @Deprecated public static float getRotation(android.view.View!);
+ method @Deprecated public static float getRotationX(android.view.View!);
+ method @Deprecated public static float getRotationY(android.view.View!);
+ method @Deprecated public static float getScaleX(android.view.View!);
+ method @Deprecated public static float getScaleY(android.view.View!);
+ method public static int getScrollIndicators(android.view.View);
+ method @UiThread public static CharSequence? getStateDescription(android.view.View);
+ method public static java.util.List<android.graphics.Rect!> getSystemGestureExclusionRects(android.view.View);
+ method public static String? getTransitionName(android.view.View);
+ method @Deprecated public static float getTranslationX(android.view.View!);
+ method @Deprecated public static float getTranslationY(android.view.View!);
+ method public static float getTranslationZ(android.view.View);
+ method @Deprecated public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
+ method @Deprecated public static int getWindowSystemUiVisibility(android.view.View);
+ method @Deprecated public static float getX(android.view.View!);
+ method @Deprecated public static float getY(android.view.View!);
+ method public static float getZ(android.view.View);
+ method public static boolean hasAccessibilityDelegate(android.view.View);
+ method public static boolean hasExplicitFocusable(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View);
+ method public static boolean hasNestedScrollingParent(android.view.View, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public static boolean hasOnClickListeners(android.view.View);
+ method public static boolean hasOverlappingRendering(android.view.View);
+ method public static boolean hasTransientState(android.view.View);
+ method @UiThread public static boolean isAccessibilityHeading(android.view.View);
+ method public static boolean isAttachedToWindow(android.view.View);
+ method public static boolean isFocusedByDefault(android.view.View);
+ method public static boolean isImportantForAccessibility(android.view.View);
+ method public static boolean isImportantForAutofill(android.view.View);
+ method public static boolean isInLayout(android.view.View);
+ method public static boolean isKeyboardNavigationCluster(android.view.View);
+ method public static boolean isLaidOut(android.view.View);
+ method public static boolean isLayoutDirectionResolved(android.view.View);
+ method public static boolean isNestedScrollingEnabled(android.view.View);
+ method @Deprecated public static boolean isOpaque(android.view.View!);
+ method public static boolean isPaddingRelative(android.view.View);
+ method @UiThread public static boolean isScreenReaderFocusable(android.view.View);
+ method @Deprecated public static void jumpDrawablesToCurrentState(android.view.View!);
+ method public static android.view.View? keyboardNavigationClusterSearch(android.view.View, android.view.View?, @androidx.core.view.ViewCompat.FocusDirection int);
+ method public static void offsetLeftAndRight(android.view.View, int);
+ method public static void offsetTopAndBottom(android.view.View, int);
+ method public static androidx.core.view.WindowInsetsCompat onApplyWindowInsets(android.view.View, androidx.core.view.WindowInsetsCompat);
+ method @Deprecated public static void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+ method @Deprecated public static void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static boolean performAccessibilityAction(android.view.View, int, android.os.Bundle?);
+ method public static androidx.core.view.ContentInfoCompat? performReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ method public static void postInvalidateOnAnimation(android.view.View);
+ method public static void postInvalidateOnAnimation(android.view.View, int, int, int, int);
+ method public static void postOnAnimation(android.view.View, Runnable);
+ method public static void postOnAnimationDelayed(android.view.View, Runnable, long);
+ method public static void removeAccessibilityAction(android.view.View, int);
+ method public static void removeOnUnhandledKeyEventListener(android.view.View, androidx.core.view.ViewCompat.OnUnhandledKeyEventListenerCompat);
+ method public static void replaceAccessibilityAction(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat, CharSequence?, androidx.core.view.accessibility.AccessibilityViewCommand?);
+ method public static void requestApplyInsets(android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.View, @IdRes int);
+ method @Deprecated public static int resolveSizeAndState(int, int, int);
+ method public static boolean restoreDefaultFocus(android.view.View);
+ method public static void saveAttributeDataForStyleable(android.view.View, android.content.Context, int[], android.util.AttributeSet?, android.content.res.TypedArray, int, int);
+ method public static void setAccessibilityDelegate(android.view.View, androidx.core.view.AccessibilityDelegateCompat?);
+ method @UiThread public static void setAccessibilityHeading(android.view.View, boolean);
+ method public static void setAccessibilityLiveRegion(android.view.View, int);
+ method @UiThread public static void setAccessibilityPaneTitle(android.view.View, CharSequence?);
+ method @Deprecated public static void setActivated(android.view.View!, boolean);
+ method @Deprecated public static void setAlpha(android.view.View!, @FloatRange(from=0.0, to=1.0) float);
+ method public static void setAutofillHints(android.view.View, java.lang.String!...);
+ method public static void setBackground(android.view.View, android.graphics.drawable.Drawable?);
+ method public static void setBackgroundTintList(android.view.View, android.content.res.ColorStateList?);
+ method public static void setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode?);
+ method @Deprecated public static void setChildrenDrawingOrderEnabled(android.view.ViewGroup!, boolean);
+ method public static void setClipBounds(android.view.View, android.graphics.Rect?);
+ method public static void setElevation(android.view.View, float);
+ method @Deprecated public static void setFitsSystemWindows(android.view.View!, boolean);
+ method public static void setFocusedByDefault(android.view.View, boolean);
+ method public static void setHasTransientState(android.view.View, boolean);
+ method @UiThread public static void setImportantForAccessibility(android.view.View, int);
+ method public static void setImportantForAutofill(android.view.View, int);
+ method public static void setKeyboardNavigationCluster(android.view.View, boolean);
+ method public static void setLabelFor(android.view.View, @IdRes int);
+ method public static void setLayerPaint(android.view.View, android.graphics.Paint?);
+ method @Deprecated public static void setLayerType(android.view.View!, int, android.graphics.Paint!);
+ method public static void setLayoutDirection(android.view.View, int);
+ method public static void setNestedScrollingEnabled(android.view.View, boolean);
+ method public static void setNextClusterForwardId(android.view.View, int);
+ method public static void setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener?);
+ method public static void setOnReceiveContentListener(android.view.View, String![]?, androidx.core.view.OnReceiveContentListener?);
+ method @Deprecated public static void setOverScrollMode(android.view.View!, int);
+ method public static void setPaddingRelative(android.view.View, @Px int, @Px int, @Px int, @Px int);
+ method @Deprecated public static void setPivotX(android.view.View!, float);
+ method @Deprecated public static void setPivotY(android.view.View!, float);
+ method public static void setPointerIcon(android.view.View, androidx.core.view.PointerIconCompat?);
+ method @Deprecated public static void setRotation(android.view.View!, float);
+ method @Deprecated public static void setRotationX(android.view.View!, float);
+ method @Deprecated public static void setRotationY(android.view.View!, float);
+ method @Deprecated public static void setSaveFromParentEnabled(android.view.View!, boolean);
+ method @Deprecated public static void setScaleX(android.view.View!, float);
+ method @Deprecated public static void setScaleY(android.view.View!, float);
+ method @UiThread public static void setScreenReaderFocusable(android.view.View, boolean);
+ method public static void setScrollIndicators(android.view.View, @androidx.core.view.ViewCompat.ScrollIndicators int);
+ method public static void setScrollIndicators(android.view.View, @androidx.core.view.ViewCompat.ScrollIndicators int, @androidx.core.view.ViewCompat.ScrollIndicators int);
+ method @UiThread public static void setStateDescription(android.view.View, CharSequence?);
+ method public static void setSystemGestureExclusionRects(android.view.View, java.util.List<android.graphics.Rect!>);
+ method public static void setTooltipText(android.view.View, CharSequence?);
+ method public static void setTransitionName(android.view.View, String?);
+ method @Deprecated public static void setTranslationX(android.view.View!, float);
+ method @Deprecated public static void setTranslationY(android.view.View!, float);
+ method public static void setTranslationZ(android.view.View, float);
+ method public static void setWindowInsetsAnimationCallback(android.view.View, androidx.core.view.WindowInsetsAnimationCompat.Callback?);
+ method @Deprecated public static void setX(android.view.View!, float);
+ method @Deprecated public static void setY(android.view.View!, float);
+ method public static void setZ(android.view.View, float);
+ method public static boolean startDragAndDrop(android.view.View, android.content.ClipData?, android.view.View.DragShadowBuilder, Object?, int);
+ method public static boolean startNestedScroll(android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int);
+ method public static boolean startNestedScroll(android.view.View, @androidx.core.view.ViewCompat.ScrollAxis int, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public static void stopNestedScroll(android.view.View);
+ method public static void stopNestedScroll(android.view.View, @androidx.core.view.ViewCompat.NestedScrollType int);
+ method public static void updateDragShadow(android.view.View, android.view.View.DragShadowBuilder);
+ field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
+ field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
+ field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+ field @Deprecated public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
+ field @Deprecated public static final int LAYER_TYPE_NONE = 0; // 0x0
+ field @Deprecated public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
+ field public static final int LAYOUT_DIRECTION_INHERIT = 2; // 0x2
+ field public static final int LAYOUT_DIRECTION_LOCALE = 3; // 0x3
+ field public static final int LAYOUT_DIRECTION_LTR = 0; // 0x0
+ field public static final int LAYOUT_DIRECTION_RTL = 1; // 0x1
+ field @Deprecated public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; // 0x10
+ field @Deprecated public static final int MEASURED_SIZE_MASK = 16777215; // 0xffffff
+ field @Deprecated public static final int MEASURED_STATE_MASK = -16777216; // 0xff000000
+ field @Deprecated public static final int MEASURED_STATE_TOO_SMALL = 16777216; // 0x1000000
+ field @Deprecated public static final int OVER_SCROLL_ALWAYS = 0; // 0x0
+ field @Deprecated public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; // 0x1
+ field @Deprecated public static final int OVER_SCROLL_NEVER = 2; // 0x2
+ field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
+ field public static final int SCROLL_AXIS_NONE = 0; // 0x0
+ field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+ field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+ field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+ field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+ field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
+ field public static final int TYPE_NON_TOUCH = 1; // 0x1
+ field public static final int TYPE_TOUCH = 0; // 0x0
+ }
+
+ @IntDef({android.view.View.FOCUS_LEFT, android.view.View.FOCUS_UP, android.view.View.FOCUS_RIGHT, android.view.View.FOCUS_DOWN, android.view.View.FOCUS_FORWARD, android.view.View.FOCUS_BACKWARD}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.FocusDirection {
+ }
+
+ @IntDef({android.view.View.FOCUS_LEFT, android.view.View.FOCUS_UP, android.view.View.FOCUS_RIGHT, android.view.View.FOCUS_DOWN}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.FocusRealDirection {
+ }
+
+ @IntDef({android.view.View.FOCUS_FORWARD, android.view.View.FOCUS_BACKWARD}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.FocusRelativeDirection {
+ }
+
+ @IntDef({androidx.core.view.ViewCompat.TYPE_TOUCH, androidx.core.view.ViewCompat.TYPE_NON_TOUCH}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.NestedScrollType {
+ }
+
+ public static interface ViewCompat.OnUnhandledKeyEventListenerCompat {
+ method public boolean onUnhandledKeyEvent(android.view.View, android.view.KeyEvent);
+ }
+
+ @IntDef(value={androidx.core.view.ViewCompat.SCROLL_AXIS_NONE, androidx.core.view.ViewCompat.SCROLL_AXIS_HORIZONTAL, androidx.core.view.ViewCompat.SCROLL_AXIS_VERTICAL}, flag=true) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.ScrollAxis {
+ }
+
+ @IntDef(flag=true, value={androidx.core.view.ViewCompat.SCROLL_INDICATOR_TOP, androidx.core.view.ViewCompat.SCROLL_INDICATOR_BOTTOM, androidx.core.view.ViewCompat.SCROLL_INDICATOR_LEFT, androidx.core.view.ViewCompat.SCROLL_INDICATOR_RIGHT, androidx.core.view.ViewCompat.SCROLL_INDICATOR_START, androidx.core.view.ViewCompat.SCROLL_INDICATOR_END}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ViewCompat.ScrollIndicators {
+ }
+
+ public final class ViewConfigurationCompat {
+ method public static float getScaledHorizontalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method public static int getScaledHoverSlop(android.view.ViewConfiguration);
+ method @Deprecated public static int getScaledPagingTouchSlop(android.view.ViewConfiguration!);
+ method public static float getScaledVerticalScrollFactor(android.view.ViewConfiguration, android.content.Context);
+ method @Deprecated public static boolean hasPermanentMenuKey(android.view.ViewConfiguration!);
+ method public static boolean shouldShowMenuShortcutsWhenKeyboardPresent(android.view.ViewConfiguration, android.content.Context);
+ }
+
+ public final class ViewGroupCompat {
+ method public static int getLayoutMode(android.view.ViewGroup);
+ method @androidx.core.view.ViewCompat.ScrollAxis public static int getNestedScrollAxes(android.view.ViewGroup);
+ method public static boolean isTransitionGroup(android.view.ViewGroup);
+ method @Deprecated public static boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ method public static void setLayoutMode(android.view.ViewGroup, int);
+ method @Deprecated public static void setMotionEventSplittingEnabled(android.view.ViewGroup!, boolean);
+ method public static void setTransitionGroup(android.view.ViewGroup, boolean);
+ field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
+ field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
+ }
+
+ public final class ViewParentCompat {
+ method public static void notifySubtreeAccessibilityStateChanged(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onNestedFling(android.view.ViewParent, android.view.View, float, float, boolean);
+ method public static boolean onNestedPreFling(android.view.ViewParent, android.view.View, float, float);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[]);
+ method public static void onNestedPreScroll(android.view.ViewParent, android.view.View, int, int, int[], int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int);
+ method public static void onNestedScroll(android.view.ViewParent, android.view.View, int, int, int, int, int, int[]);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static void onNestedScrollAccepted(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int);
+ method public static boolean onStartNestedScroll(android.view.ViewParent, android.view.View, android.view.View, int, int);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View);
+ method public static void onStopNestedScroll(android.view.ViewParent, android.view.View, int);
+ method @Deprecated public static boolean requestSendAccessibilityEvent(android.view.ViewParent!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
+ }
+
+ public final class ViewPropertyAnimatorCompat {
+ method public androidx.core.view.ViewPropertyAnimatorCompat alpha(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat alphaBy(float);
+ method public void cancel();
+ method public long getDuration();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method public long getStartDelay();
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotation(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat rotationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat scaleYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setDuration(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setInterpolator(android.view.animation.Interpolator?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setListener(androidx.core.view.ViewPropertyAnimatorListener?);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setStartDelay(long);
+ method public androidx.core.view.ViewPropertyAnimatorCompat setUpdateListener(androidx.core.view.ViewPropertyAnimatorUpdateListener?);
+ method public void start();
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationX(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationXBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationY(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationYBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZ(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat translationZBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withEndAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat withLayer();
+ method public androidx.core.view.ViewPropertyAnimatorCompat withStartAction(Runnable);
+ method public androidx.core.view.ViewPropertyAnimatorCompat x(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat xBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat y(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat yBy(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat z(float);
+ method public androidx.core.view.ViewPropertyAnimatorCompat zBy(float);
+ }
+
+ public interface ViewPropertyAnimatorListener {
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public class ViewPropertyAnimatorListenerAdapter implements androidx.core.view.ViewPropertyAnimatorListener {
+ ctor public ViewPropertyAnimatorListenerAdapter();
+ method public void onAnimationCancel(android.view.View);
+ method public void onAnimationEnd(android.view.View);
+ method public void onAnimationStart(android.view.View);
+ }
+
+ public interface ViewPropertyAnimatorUpdateListener {
+ method public void onAnimationUpdate(android.view.View);
+ }
+
+ public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat getInsetsController(android.view.Window, android.view.View);
+ method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
+ method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
+ field public static final int FEATURE_ACTION_BAR = 8; // 0x8
+ field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9
+ field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
+ }
+
+ public final class WindowInsetsAnimationCompat {
+ ctor public WindowInsetsAnimationCompat(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int, android.view.animation.Interpolator?, long);
+ method @FloatRange(from=0.0f, to=1.0f) public float getAlpha();
+ method public long getDurationMillis();
+ method @FloatRange(from=0.0f, to=1.0f) public float getFraction();
+ method public float getInterpolatedFraction();
+ method public android.view.animation.Interpolator? getInterpolator();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public int getTypeMask();
+ method public void setAlpha(@FloatRange(from=0.0f, to=1.0f) float);
+ method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public static final class WindowInsetsAnimationCompat.BoundsCompat {
+ ctor public WindowInsetsAnimationCompat.BoundsCompat(androidx.core.graphics.Insets, androidx.core.graphics.Insets);
+ method public androidx.core.graphics.Insets getLowerBound();
+ method public androidx.core.graphics.Insets getUpperBound();
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat inset(androidx.core.graphics.Insets);
+ method @RequiresApi(30) public android.view.WindowInsetsAnimation.Bounds toBounds();
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat toBoundsCompat(android.view.WindowInsetsAnimation.Bounds);
+ }
+
+ public abstract static class WindowInsetsAnimationCompat.Callback {
+ ctor public WindowInsetsAnimationCompat.Callback(@androidx.core.view.WindowInsetsAnimationCompat.Callback.DispatchMode int);
+ method @androidx.core.view.WindowInsetsAnimationCompat.Callback.DispatchMode public final int getDispatchMode();
+ method public void onEnd(androidx.core.view.WindowInsetsAnimationCompat);
+ method public void onPrepare(androidx.core.view.WindowInsetsAnimationCompat);
+ method public abstract androidx.core.view.WindowInsetsCompat onProgress(androidx.core.view.WindowInsetsCompat, java.util.List<androidx.core.view.WindowInsetsAnimationCompat!>);
+ method public androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat onStart(androidx.core.view.WindowInsetsAnimationCompat, androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat);
+ field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
+ field public static final int DISPATCH_MODE_STOP = 0; // 0x0
+ }
+
+ @IntDef({androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP, androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowInsetsAnimationCompat.Callback.DispatchMode {
+ }
+
+ public interface WindowInsetsAnimationControlListenerCompat {
+ method public void onCancelled(androidx.core.view.WindowInsetsAnimationControllerCompat?);
+ method public void onFinished(androidx.core.view.WindowInsetsAnimationControllerCompat);
+ method public void onReady(androidx.core.view.WindowInsetsAnimationControllerCompat, @androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ }
+
+ public final class WindowInsetsAnimationControllerCompat {
+ method public void finish(boolean);
+ method public float getCurrentAlpha();
+ method @FloatRange(from=0.0f, to=1.0f) public float getCurrentFraction();
+ method public androidx.core.graphics.Insets getCurrentInsets();
+ method public androidx.core.graphics.Insets getHiddenStateInsets();
+ method public androidx.core.graphics.Insets getShownStateInsets();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public int getTypes();
+ method public boolean isCancelled();
+ method public boolean isFinished();
+ method public boolean isReady();
+ method public void setInsetsAndAlpha(androidx.core.graphics.Insets?, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
+ }
+
+ public class WindowInsetsCompat {
+ ctor public WindowInsetsCompat(androidx.core.view.WindowInsetsCompat?);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeDisplayCutout();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeStableInsets();
+ method @Deprecated public androidx.core.view.WindowInsetsCompat consumeSystemWindowInsets();
+ method public androidx.core.view.DisplayCutoutCompat? getDisplayCutout();
+ method public androidx.core.graphics.Insets getInsets(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method public androidx.core.graphics.Insets getInsetsIgnoringVisibility(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method @Deprecated public androidx.core.graphics.Insets getMandatorySystemGestureInsets();
+ method @Deprecated public int getStableInsetBottom();
+ method @Deprecated public int getStableInsetLeft();
+ method @Deprecated public int getStableInsetRight();
+ method @Deprecated public int getStableInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getStableInsets();
+ method @Deprecated public androidx.core.graphics.Insets getSystemGestureInsets();
+ method @Deprecated public int getSystemWindowInsetBottom();
+ method @Deprecated public int getSystemWindowInsetLeft();
+ method @Deprecated public int getSystemWindowInsetRight();
+ method @Deprecated public int getSystemWindowInsetTop();
+ method @Deprecated public androidx.core.graphics.Insets getSystemWindowInsets();
+ method @Deprecated public androidx.core.graphics.Insets getTappableElementInsets();
+ method public boolean hasInsets();
+ method @Deprecated public boolean hasStableInsets();
+ method @Deprecated public boolean hasSystemWindowInsets();
+ method public androidx.core.view.WindowInsetsCompat inset(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat inset(@IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
+ method public boolean isConsumed();
+ method public boolean isRound();
+ method public boolean isVisible(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(int, int, int, int);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
+ method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
+ method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets, android.view.View?);
+ field public static final androidx.core.view.WindowInsetsCompat CONSUMED;
+ }
+
+ public static final class WindowInsetsCompat.Builder {
+ ctor public WindowInsetsCompat.Builder();
+ ctor public WindowInsetsCompat.Builder(androidx.core.view.WindowInsetsCompat);
+ method public androidx.core.view.WindowInsetsCompat build();
+ method public androidx.core.view.WindowInsetsCompat.Builder setDisplayCutout(androidx.core.view.DisplayCutoutCompat?);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsets(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int, androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setInsetsIgnoringVisibility(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int, androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setMandatorySystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setStableInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemGestureInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setSystemWindowInsets(androidx.core.graphics.Insets);
+ method @Deprecated public androidx.core.view.WindowInsetsCompat.Builder setTappableElementInsets(androidx.core.graphics.Insets);
+ method public androidx.core.view.WindowInsetsCompat.Builder setVisible(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int, boolean);
+ }
+
+ public static final class WindowInsetsCompat.Type {
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int captionBar();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int displayCutout();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int ime();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int mandatorySystemGestures();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int navigationBars();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int statusBars();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int systemBars();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int systemGestures();
+ method @androidx.core.view.WindowInsetsCompat.Type.InsetsType public static int tappableElement();
+ }
+
+ @IntDef(flag=true, value={0x1, 0x2, 0x4, 0x8, 0x100, 0x10, 0x20, 0x40, 0x80}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowInsetsCompat.Type.InsetsType {
+ }
+
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public void addOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void controlWindowInsetsAnimation(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int, long, android.view.animation.Interpolator?, android.os.CancellationSignal?, androidx.core.view.WindowInsetsAnimationControlListenerCompat);
+ method public int getSystemBarsBehavior();
+ method public void hide(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method public boolean isAppearanceLightNavigationBars();
+ method public boolean isAppearanceLightStatusBars();
+ method public void removeOnControllableInsetsChangedListener(androidx.core.view.WindowInsetsControllerCompat.OnControllableInsetsChangedListener);
+ method public void setAppearanceLightNavigationBars(boolean);
+ method public void setAppearanceLightStatusBars(boolean);
+ method public void setSystemBarsBehavior(int);
+ method public void show(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method @Deprecated @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_DEFAULT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
+ public static interface WindowInsetsControllerCompat.OnControllableInsetsChangedListener {
+ method public void onControllableInsetsChanged(androidx.core.view.WindowInsetsControllerCompat, @androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ }
+
+}
+
+package androidx.core.view.accessibility {
+
+ public final class AccessibilityClickableSpanCompat extends android.text.style.ClickableSpan {
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public AccessibilityClickableSpanCompat(int, androidx.core.view.accessibility.AccessibilityNodeInfoCompat, int);
+ method public void onClick(android.view.View);
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final String SPAN_ID = "ACCESSIBILITY_CLICKABLE_SPAN_ID";
+ }
+
+ public final class AccessibilityEventCompat {
+ method @Deprecated public static void appendRecord(android.view.accessibility.AccessibilityEvent!, androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! asRecord(android.view.accessibility.AccessibilityEvent!);
+ method public static int getAction(android.view.accessibility.AccessibilityEvent);
+ method @androidx.core.view.accessibility.AccessibilityEventCompat.ContentChangeType public static int getContentChangeTypes(android.view.accessibility.AccessibilityEvent);
+ method public static int getMovementGranularity(android.view.accessibility.AccessibilityEvent);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! getRecord(android.view.accessibility.AccessibilityEvent!, int);
+ method @Deprecated public static int getRecordCount(android.view.accessibility.AccessibilityEvent!);
+ method public static void setAction(android.view.accessibility.AccessibilityEvent, int);
+ method public static void setContentChangeTypes(android.view.accessibility.AccessibilityEvent, @androidx.core.view.accessibility.AccessibilityEventCompat.ContentChangeType int);
+ method public static void setMovementGranularity(android.view.accessibility.AccessibilityEvent, int);
+ field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 512; // 0x200
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 256; // 0x100
+ field public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 128; // 0x80
+ field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10
+ field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20
+ field public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 8; // 0x8
+ field public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 64; // 0x40
+ field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
+ field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
+ field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
+ field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+ field public static final int TYPE_ASSIST_READING_CONTEXT = 16777216; // 0x1000000
+ field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
+ field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
+ field @Deprecated public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
+ field public static final int TYPE_TOUCH_INTERACTION_END = 2097152; // 0x200000
+ field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
+ field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
+ field public static final int TYPE_VIEW_CONTEXT_CLICKED = 8388608; // 0x800000
+ field @Deprecated public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
+ field @Deprecated public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
+ field @Deprecated public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
+ field @Deprecated public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
+ field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
+ field public static final int TYPE_WINDOWS_CHANGED = 4194304; // 0x400000
+ field @Deprecated public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
+ }
+
+ @IntDef(flag=true, value={androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_SUBTREE, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_TEXT, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_UNDEFINED, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_DRAG_STARTED, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_DRAG_DROPPED, androidx.core.view.accessibility.AccessibilityEventCompat.CONTENT_CHANGE_TYPE_DRAG_CANCELLED}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AccessibilityEventCompat.ContentChangeType {
+ }
+
+ public final class AccessibilityManagerCompat {
+ method @Deprecated public static boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getEnabledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!, int);
+ method @Deprecated public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo!>! getInstalledAccessibilityServiceList(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean isTouchExplorationEnabled(android.view.accessibility.AccessibilityManager!);
+ method @Deprecated public static boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager!, androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener!);
+ method public static boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, androidx.core.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
+ }
+
+ @Deprecated public static interface AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ method @Deprecated public void onAccessibilityStateChanged(boolean);
+ }
+
+ @Deprecated public abstract static class AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat implements androidx.core.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener {
+ ctor @Deprecated public AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat();
+ }
+
+ public static interface AccessibilityManagerCompat.TouchExplorationStateChangeListener {
+ method public void onTouchExplorationStateChanged(boolean);
+ }
+
+ public class AccessibilityNodeInfoCompat {
+ ctor @Deprecated public AccessibilityNodeInfoCompat(Object!);
+ method public void addAction(int);
+ method public void addAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public void addChild(android.view.View!);
+ method public void addChild(android.view.View!, int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void addSpansToExtras(CharSequence!, android.view.View!);
+ method public boolean canOpenPopup();
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByText(String!);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>! findAccessibilityNodeInfosByViewId(String!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! findFocus(int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! focusSearch(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!>! getActionList();
+ method @Deprecated public int getActions();
+ method public java.util.List<java.lang.String!> getAvailableExtraData();
+ method @Deprecated public void getBoundsInParent(android.graphics.Rect!);
+ method public void getBoundsInScreen(android.graphics.Rect!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getChild(int);
+ method public int getChildCount();
+ method public CharSequence! getClassName();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.text.style.ClickableSpan![]! getClickableSpans(CharSequence!);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! getCollectionInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! getCollectionItemInfo();
+ method public CharSequence! getContentDescription();
+ method public int getDrawingOrder();
+ method public CharSequence! getError();
+ method public android.view.accessibility.AccessibilityNodeInfo.ExtraRenderingInfo? getExtraRenderingInfo();
+ method public android.os.Bundle! getExtras();
+ method public CharSequence? getHintText();
+ method @Deprecated public Object! getInfo();
+ method public int getInputType();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabelFor();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
+ method public int getLiveRegion();
+ method public int getMaxTextLength();
+ method public long getMinDurationBetweenContentChangesMillis();
+ method public int getMovementGranularities();
+ method public CharSequence! getPackageName();
+ method public CharSequence? getPaneTitle();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getParent();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! getRangeInfo();
+ method public CharSequence? getRoleDescription();
+ method public CharSequence? getStateDescription();
+ method public CharSequence! getText();
+ method public int getTextSelectionEnd();
+ method public int getTextSelectionStart();
+ method public CharSequence? getTooltipText();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat? getTouchDelegateInfo();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalAfter();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getTraversalBefore();
+ method public String? getUniqueId();
+ method public String! getViewIdResourceName();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat! getWindow();
+ method public int getWindowId();
+ method public boolean hasRequestInitialAccessibilityFocus();
+ method public boolean isAccessibilityFocused();
+ method public boolean isCheckable();
+ method public boolean isChecked();
+ method public boolean isClickable();
+ method public boolean isContentInvalid();
+ method public boolean isContextClickable();
+ method public boolean isDismissable();
+ method public boolean isEditable();
+ method public boolean isEnabled();
+ method public boolean isFocusable();
+ method public boolean isFocused();
+ method public boolean isHeading();
+ method public boolean isImportantForAccessibility();
+ method public boolean isLongClickable();
+ method public boolean isMultiLine();
+ method public boolean isPassword();
+ method public boolean isScreenReaderFocusable();
+ method public boolean isScrollable();
+ method public boolean isSelected();
+ method public boolean isShowingHintText();
+ method public boolean isTextEntryKey();
+ method public boolean isTextSelectable();
+ method public boolean isVisibleToUser();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(android.view.View!, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! obtain(androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
+ method public boolean performAction(int);
+ method public boolean performAction(int, android.os.Bundle!);
+ method @Deprecated public void recycle();
+ method public boolean refresh();
+ method public boolean removeAction(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat!);
+ method public boolean removeChild(android.view.View!);
+ method public boolean removeChild(android.view.View!, int);
+ method public void setAccessibilityFocused(boolean);
+ method public void setAvailableExtraData(java.util.List<java.lang.String!>);
+ method @Deprecated public void setBoundsInParent(android.graphics.Rect!);
+ method public void setBoundsInScreen(android.graphics.Rect!);
+ method public void setCanOpenPopup(boolean);
+ method public void setCheckable(boolean);
+ method public void setChecked(boolean);
+ method public void setClassName(CharSequence!);
+ method public void setClickable(boolean);
+ method public void setCollectionInfo(Object!);
+ method public void setCollectionItemInfo(Object!);
+ method public void setContentDescription(CharSequence!);
+ method public void setContentInvalid(boolean);
+ method public void setContextClickable(boolean);
+ method public void setDismissable(boolean);
+ method public void setDrawingOrder(int);
+ method public void setEditable(boolean);
+ method public void setEnabled(boolean);
+ method public void setError(CharSequence!);
+ method public void setFocusable(boolean);
+ method public void setFocused(boolean);
+ method public void setHeading(boolean);
+ method public void setHintText(CharSequence?);
+ method public void setImportantForAccessibility(boolean);
+ method public void setInputType(int);
+ method public void setLabelFor(android.view.View!);
+ method public void setLabelFor(android.view.View!, int);
+ method public void setLabeledBy(android.view.View!);
+ method public void setLabeledBy(android.view.View!, int);
+ method public void setLiveRegion(int);
+ method public void setLongClickable(boolean);
+ method public void setMaxTextLength(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
+ method public void setMovementGranularities(int);
+ method public void setMultiLine(boolean);
+ method public void setPackageName(CharSequence!);
+ method public void setPaneTitle(CharSequence?);
+ method public void setParent(android.view.View!);
+ method public void setParent(android.view.View!, int);
+ method public void setPassword(boolean);
+ method public void setRangeInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat!);
+ method public void setRequestInitialAccessibilityFocus(boolean);
+ method public void setRoleDescription(CharSequence?);
+ method public void setScreenReaderFocusable(boolean);
+ method public void setScrollable(boolean);
+ method public void setSelected(boolean);
+ method public void setShowingHintText(boolean);
+ method public void setSource(android.view.View!);
+ method public void setSource(android.view.View!, int);
+ method public void setStateDescription(CharSequence?);
+ method public void setText(CharSequence!);
+ method public void setTextEntryKey(boolean);
+ method public void setTextSelectable(boolean);
+ method public void setTextSelection(int, int);
+ method public void setTooltipText(CharSequence?);
+ method public void setTouchDelegateInfo(androidx.core.view.accessibility.AccessibilityNodeInfoCompat.TouchDelegateInfoCompat);
+ method public void setTraversalAfter(android.view.View!);
+ method public void setTraversalAfter(android.view.View!, int);
+ method public void setTraversalBefore(android.view.View!);
+ method public void setTraversalBefore(android.view.View!, int);
+ method public void setUniqueId(String?);
+ method public void setViewIdResourceName(String!);
+ method public void setVisibleToUser(boolean);
+ method public android.view.accessibility.AccessibilityNodeInfo! unwrap();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat! wrap(android.view.accessibility.AccessibilityNodeInfo);
+ field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+ field public static final String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
+ field public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
+ field public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
+ field public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_X = "ACTION_ARGUMENT_MOVE_WINDOW_X";
+ field public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y = "ACTION_ARGUMENT_MOVE_WINDOW_Y";
+ field public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT = "android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT";
+ field public static final String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
+ field public static final String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
+ field public static final String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
+ field public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
+ field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
+ field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
+ field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
+ field public static final int ACTION_CLICK = 16; // 0x10
+ field public static final int ACTION_COLLAPSE = 524288; // 0x80000
+ field public static final int ACTION_COPY = 16384; // 0x4000
+ field public static final int ACTION_CUT = 65536; // 0x10000
+ field public static final int ACTION_DISMISS = 1048576; // 0x100000
+ field public static final int ACTION_EXPAND = 262144; // 0x40000
+ field public static final int ACTION_FOCUS = 1; // 0x1
+ field public static final int ACTION_LONG_CLICK = 32; // 0x20
+ field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
+ field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
+ field public static final int ACTION_PASTE = 32768; // 0x8000
+ field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
+ field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
+ field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
+ field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
+ field public static final int ACTION_SELECT = 4; // 0x4
+ field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
+ field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+ field public static final int EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH = 20000; // 0x4e20
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+ field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.core.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
+ field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
+ field public static final int FOCUS_INPUT = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
+ field public static final int MOVEMENT_GRANULARITY_LINE = 4; // 0x4
+ field public static final int MOVEMENT_GRANULARITY_PAGE = 16; // 0x10
+ field public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 8; // 0x8
+ field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int mParentVirtualDescendantId;
+ }
+
+ public static class AccessibilityNodeInfoCompat.AccessibilityActionCompat {
+ ctor public AccessibilityNodeInfoCompat.AccessibilityActionCompat(int, CharSequence!);
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public AccessibilityNodeInfoCompat.AccessibilityActionCompat(int, CharSequence!, androidx.core.view.accessibility.AccessibilityViewCommand!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! createReplacementAction(CharSequence!, androidx.core.view.accessibility.AccessibilityViewCommand!);
+ method public int getId();
+ method public CharSequence! getLabel();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean perform(android.view.View!, android.os.Bundle!);
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLEAR_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COLLAPSE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CONTEXT_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_COPY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_CUT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_DISMISS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_CANCEL;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_DROP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_DRAG_START;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_EXPAND;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_FOCUS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_HIDE_TOOLTIP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_IME_ENTER;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_LONG_CLICK;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_MOVE_WINDOW;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_NEXT_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PAGE_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PASTE;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_PRESS_AND_HOLD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_PREVIOUS_HTML_ELEMENT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_BACKWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_DOWN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_FORWARD;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_LEFT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_RIGHT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_TO_POSITION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SCROLL_UP;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SELECT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_PROGRESS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_SELECTION;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SET_TEXT;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_ON_SCREEN;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat ACTION_SHOW_TEXT_SUGGESTIONS;
+ field public static final androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat! ACTION_SHOW_TOOLTIP;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected final androidx.core.view.accessibility.AccessibilityViewCommand! mCommand;
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionInfoCompat {
+ method public int getColumnCount();
+ method public int getRowCount();
+ method public int getSelectionMode();
+ method public boolean isHierarchical();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean, int);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat! obtain(int, int, boolean);
+ field public static final int SELECTION_MODE_MULTIPLE = 2; // 0x2
+ field public static final int SELECTION_MODE_NONE = 0; // 0x0
+ field public static final int SELECTION_MODE_SINGLE = 1; // 0x1
+ }
+
+ public static class AccessibilityNodeInfoCompat.CollectionItemInfoCompat {
+ method public int getColumnIndex();
+ method public int getColumnSpan();
+ method public int getRowIndex();
+ method public int getRowSpan();
+ method @Deprecated public boolean isHeading();
+ method public boolean isSelected();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean, boolean);
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat! obtain(int, int, int, int, boolean);
+ }
+
+ public static class AccessibilityNodeInfoCompat.RangeInfoCompat {
+ method public float getCurrent();
+ method public float getMax();
+ method public float getMin();
+ method public int getType();
+ method public static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat! obtain(int, float, float, float);
+ field public static final int RANGE_TYPE_FLOAT = 1; // 0x1
+ field public static final int RANGE_TYPE_INT = 0; // 0x0
+ field public static final int RANGE_TYPE_PERCENT = 2; // 0x2
+ }
+
+ public static final class AccessibilityNodeInfoCompat.TouchDelegateInfoCompat {
+ ctor public AccessibilityNodeInfoCompat.TouchDelegateInfoCompat(java.util.Map<android.graphics.Region!,android.view.View!>);
+ method public android.graphics.Region? getRegionAt(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getRegionCount();
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getTargetForRegion(android.graphics.Region);
+ }
+
+ public class AccessibilityNodeProviderCompat {
+ ctor public AccessibilityNodeProviderCompat();
+ ctor public AccessibilityNodeProviderCompat(Object?);
+ method public void addExtraDataToAccessibilityNodeInfo(int, androidx.core.view.accessibility.AccessibilityNodeInfoCompat, String, android.os.Bundle?);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? createAccessibilityNodeInfo(int);
+ method public java.util.List<androidx.core.view.accessibility.AccessibilityNodeInfoCompat!>? findAccessibilityNodeInfosByText(String, int);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? findFocus(int);
+ method public Object? getProvider();
+ method public boolean performAction(int, int, android.os.Bundle?);
+ field public static final int HOST_VIEW_ID = -1; // 0xffffffff
+ }
+
+ public class AccessibilityRecordCompat {
+ ctor @Deprecated public AccessibilityRecordCompat(Object!);
+ method @Deprecated public boolean equals(Object?);
+ method @Deprecated public int getAddedCount();
+ method @Deprecated public CharSequence! getBeforeText();
+ method @Deprecated public CharSequence! getClassName();
+ method @Deprecated public CharSequence! getContentDescription();
+ method @Deprecated public int getCurrentItemIndex();
+ method @Deprecated public int getFromIndex();
+ method @Deprecated public Object! getImpl();
+ method @Deprecated public int getItemCount();
+ method @Deprecated public int getMaxScrollX();
+ method public static int getMaxScrollX(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public int getMaxScrollY();
+ method public static int getMaxScrollY(android.view.accessibility.AccessibilityRecord);
+ method @Deprecated public android.os.Parcelable! getParcelableData();
+ method @Deprecated public int getRemovedCount();
+ method @Deprecated public int getScrollX();
+ method @Deprecated public int getScrollY();
+ method @Deprecated public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getSource();
+ method @Deprecated public java.util.List<java.lang.CharSequence!>! getText();
+ method @Deprecated public int getToIndex();
+ method @Deprecated public int getWindowId();
+ method @Deprecated public int hashCode();
+ method @Deprecated public boolean isChecked();
+ method @Deprecated public boolean isEnabled();
+ method @Deprecated public boolean isFullScreen();
+ method @Deprecated public boolean isPassword();
+ method @Deprecated public boolean isScrollable();
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain(androidx.core.view.accessibility.AccessibilityRecordCompat!);
+ method @Deprecated public static androidx.core.view.accessibility.AccessibilityRecordCompat! obtain();
+ method @Deprecated public void recycle();
+ method @Deprecated public void setAddedCount(int);
+ method @Deprecated public void setBeforeText(CharSequence!);
+ method @Deprecated public void setChecked(boolean);
+ method @Deprecated public void setClassName(CharSequence!);
+ method @Deprecated public void setContentDescription(CharSequence!);
+ method @Deprecated public void setCurrentItemIndex(int);
+ method @Deprecated public void setEnabled(boolean);
+ method @Deprecated public void setFromIndex(int);
+ method @Deprecated public void setFullScreen(boolean);
+ method @Deprecated public void setItemCount(int);
+ method @Deprecated public void setMaxScrollX(int);
+ method public static void setMaxScrollX(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setMaxScrollY(int);
+ method public static void setMaxScrollY(android.view.accessibility.AccessibilityRecord, int);
+ method @Deprecated public void setParcelableData(android.os.Parcelable!);
+ method @Deprecated public void setPassword(boolean);
+ method @Deprecated public void setRemovedCount(int);
+ method @Deprecated public void setScrollX(int);
+ method @Deprecated public void setScrollY(int);
+ method @Deprecated public void setScrollable(boolean);
+ method @Deprecated public void setSource(android.view.View!);
+ method @Deprecated public void setSource(android.view.View!, int);
+ method public static void setSource(android.view.accessibility.AccessibilityRecord, android.view.View?, int);
+ method @Deprecated public void setToIndex(int);
+ }
+
+ public interface AccessibilityViewCommand {
+ method public boolean perform(android.view.View, androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments?);
+ }
+
+ public abstract static class AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.CommandArguments();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setBundle(android.os.Bundle?);
+ }
+
+ public static final class AccessibilityViewCommand.MoveAtGranularityArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveAtGranularityArguments();
+ method public boolean getExtendSelection();
+ method public int getGranularity();
+ }
+
+ public static final class AccessibilityViewCommand.MoveHtmlArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveHtmlArguments();
+ method public String? getHTMLElement();
+ }
+
+ public static final class AccessibilityViewCommand.MoveWindowArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.MoveWindowArguments();
+ method public int getX();
+ method public int getY();
+ }
+
+ public static final class AccessibilityViewCommand.ScrollToPositionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.ScrollToPositionArguments();
+ method public int getColumn();
+ method public int getRow();
+ }
+
+ public static final class AccessibilityViewCommand.SetProgressArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetProgressArguments();
+ method public float getProgress();
+ }
+
+ public static final class AccessibilityViewCommand.SetSelectionArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetSelectionArguments();
+ method public int getEnd();
+ method public int getStart();
+ }
+
+ public static final class AccessibilityViewCommand.SetTextArguments extends androidx.core.view.accessibility.AccessibilityViewCommand.CommandArguments {
+ ctor public AccessibilityViewCommand.SetTextArguments();
+ method public CharSequence? getText();
+ }
+
+ public class AccessibilityWindowInfoCompat {
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getAnchor();
+ method public void getBoundsInScreen(android.graphics.Rect);
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getChild(int);
+ method public int getChildCount();
+ method public int getDisplayId();
+ method public int getId();
+ method public int getLayer();
+ method public androidx.core.view.accessibility.AccessibilityWindowInfoCompat? getParent();
+ method public void getRegionInScreen(android.graphics.Region);
+ method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat? getRoot();
+ method public CharSequence? getTitle();
+ method public int getType();
+ method public boolean isAccessibilityFocused();
+ method public boolean isActive();
+ method public boolean isFocused();
+ method public boolean isInPictureInPictureMode();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain();
+ method public static androidx.core.view.accessibility.AccessibilityWindowInfoCompat? obtain(androidx.core.view.accessibility.AccessibilityWindowInfoCompat?);
+ method @Deprecated public void recycle();
+ method public android.view.accessibility.AccessibilityWindowInfo? unwrap();
+ field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
+ field public static final int TYPE_APPLICATION = 1; // 0x1
+ field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
+ field public static final int TYPE_SYSTEM = 3; // 0x3
+ }
+
+}
+
+package androidx.core.view.animation {
+
+ public final class PathInterpolatorCompat {
+ method public static android.view.animation.Interpolator create(android.graphics.Path);
+ method public static android.view.animation.Interpolator create(float, float);
+ method public static android.view.animation.Interpolator create(float, float, float, float);
+ }
+
+}
+
+package androidx.core.view.inputmethod {
+
+ public final class EditorInfoCompat {
+ ctor @Deprecated public EditorInfoCompat();
+ method public static String![] getContentMimeTypes(android.view.inputmethod.EditorInfo);
+ method public static CharSequence? getInitialSelectedText(android.view.inputmethod.EditorInfo, int);
+ method public static CharSequence? getInitialTextAfterCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static CharSequence? getInitialTextBeforeCursor(android.view.inputmethod.EditorInfo, int, int);
+ method public static void setContentMimeTypes(android.view.inputmethod.EditorInfo, String![]?);
+ method public static void setInitialSurroundingSubText(android.view.inputmethod.EditorInfo, CharSequence, int);
+ method public static void setInitialSurroundingText(android.view.inputmethod.EditorInfo, CharSequence);
+ field public static final int IME_FLAG_FORCE_ASCII = -2147483648; // 0x80000000
+ field public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 16777216; // 0x1000000
+ }
+
+ public final class InputConnectionCompat {
+ ctor @Deprecated public InputConnectionCompat();
+ method public static boolean commitContent(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ method @Deprecated public static android.view.inputmethod.InputConnection createWrapper(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo, androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener);
+ method public static android.view.inputmethod.InputConnection createWrapper(android.view.View, android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
+ }
+
+ public static interface InputConnectionCompat.OnCommitContentListener {
+ method public boolean onCommitContent(androidx.core.view.inputmethod.InputContentInfoCompat, int, android.os.Bundle?);
+ }
+
+ public final class InputContentInfoCompat {
+ ctor public InputContentInfoCompat(android.net.Uri, android.content.ClipDescription, android.net.Uri?);
+ method public android.net.Uri getContentUri();
+ method public android.content.ClipDescription getDescription();
+ method public android.net.Uri? getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
+ method public Object? unwrap();
+ method public static androidx.core.view.inputmethod.InputContentInfoCompat? wrap(Object?);
+ }
+
+}
+
+package androidx.core.widget {
+
+ public abstract class AutoScrollHelper implements android.view.View.OnTouchListener {
+ ctor public AutoScrollHelper(android.view.View);
+ method public abstract boolean canTargetScrollHorizontally(int);
+ method public abstract boolean canTargetScrollVertically(int);
+ method public boolean isEnabled();
+ method public boolean isExclusive();
+ method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+ method public abstract void scrollTargetBy(int, int);
+ method public androidx.core.widget.AutoScrollHelper setActivationDelay(int);
+ method public androidx.core.widget.AutoScrollHelper setEdgeType(int);
+ method public androidx.core.widget.AutoScrollHelper! setEnabled(boolean);
+ method public androidx.core.widget.AutoScrollHelper! setExclusive(boolean);
+ method public androidx.core.widget.AutoScrollHelper setMaximumEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMaximumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setMinimumVelocity(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRampDownDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRampUpDuration(int);
+ method public androidx.core.widget.AutoScrollHelper setRelativeEdges(float, float);
+ method public androidx.core.widget.AutoScrollHelper setRelativeVelocity(float, float);
+ field public static final int EDGE_TYPE_INSIDE = 0; // 0x0
+ field public static final int EDGE_TYPE_INSIDE_EXTEND = 1; // 0x1
+ field public static final int EDGE_TYPE_OUTSIDE = 2; // 0x2
+ field public static final float NO_MAX = 3.4028235E38f;
+ field public static final float NO_MIN = 0.0f;
+ field public static final float RELATIVE_UNSPECIFIED = 0.0f;
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface AutoSizeableTextView {
+ method public int getAutoSizeMaxTextSize();
+ method public int getAutoSizeMinTextSize();
+ method public int getAutoSizeStepGranularity();
+ method public int[]! getAutoSizeTextAvailableSizes();
+ method @androidx.core.widget.TextViewCompat.AutoSizeTextType public int getAutoSizeTextType();
+ method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
+ method public void setAutoSizeTextTypeWithDefaults(@androidx.core.widget.TextViewCompat.AutoSizeTextType int);
+ field @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final boolean PLATFORM_SUPPORTS_AUTOSIZE;
+ }
+
+ public final class CheckedTextViewCompat {
+ method public static android.graphics.drawable.Drawable? getCheckMarkDrawable(android.widget.CheckedTextView);
+ method public static android.content.res.ColorStateList? getCheckMarkTintList(android.widget.CheckedTextView);
+ method public static android.graphics.PorterDuff.Mode? getCheckMarkTintMode(android.widget.CheckedTextView);
+ method public static void setCheckMarkTintList(android.widget.CheckedTextView, android.content.res.ColorStateList?);
+ method public static void setCheckMarkTintMode(android.widget.CheckedTextView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class CompoundButtonCompat {
+ method public static android.graphics.drawable.Drawable? getButtonDrawable(android.widget.CompoundButton);
+ method public static android.content.res.ColorStateList? getButtonTintList(android.widget.CompoundButton);
+ method public static android.graphics.PorterDuff.Mode? getButtonTintMode(android.widget.CompoundButton);
+ method public static void setButtonTintList(android.widget.CompoundButton, android.content.res.ColorStateList?);
+ method public static void setButtonTintMode(android.widget.CompoundButton, android.graphics.PorterDuff.Mode?);
+ }
+
+ public class ContentLoadingProgressBar extends android.widget.ProgressBar {
+ ctor public ContentLoadingProgressBar(android.content.Context);
+ ctor public ContentLoadingProgressBar(android.content.Context, android.util.AttributeSet?);
+ method public void hide();
+ method public void onAttachedToWindow();
+ method public void onDetachedFromWindow();
+ method public void show();
+ }
+
+ public final class EdgeEffectCompat {
+ ctor @Deprecated public EdgeEffectCompat(android.content.Context!);
+ method public static android.widget.EdgeEffect create(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public boolean draw(android.graphics.Canvas!);
+ method @Deprecated public void finish();
+ method public static float getDistance(android.widget.EdgeEffect);
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean onAbsorb(int);
+ method @Deprecated public boolean onPull(float);
+ method @Deprecated public boolean onPull(float, float);
+ method public static void onPull(android.widget.EdgeEffect, float, float);
+ method public static float onPullDistance(android.widget.EdgeEffect, float, float);
+ method @Deprecated public boolean onRelease();
+ method @Deprecated public void setSize(int, int);
+ }
+
+ public class ImageViewCompat {
+ method public static android.content.res.ColorStateList? getImageTintList(android.widget.ImageView);
+ method public static android.graphics.PorterDuff.Mode? getImageTintMode(android.widget.ImageView);
+ method public static void setImageTintList(android.widget.ImageView, android.content.res.ColorStateList?);
+ method public static void setImageTintMode(android.widget.ImageView, android.graphics.PorterDuff.Mode?);
+ }
+
+ public final class ListPopupWindowCompat {
+ method @Deprecated public static android.view.View.OnTouchListener! createDragToOpenListener(Object!, android.view.View!);
+ method public static android.view.View.OnTouchListener? createDragToOpenListener(android.widget.ListPopupWindow, android.view.View);
+ }
+
+ public class ListViewAutoScrollHelper extends androidx.core.widget.AutoScrollHelper {
+ ctor public ListViewAutoScrollHelper(android.widget.ListView);
+ method public boolean canTargetScrollHorizontally(int);
+ method public boolean canTargetScrollVertically(int);
+ method public void scrollTargetBy(int, int);
+ }
+
+ public final class ListViewCompat {
+ method public static boolean canScrollList(android.widget.ListView, int);
+ method public static void scrollListBy(android.widget.ListView, int);
+ }
+
+ public class NestedScrollView extends android.widget.FrameLayout implements androidx.core.view.NestedScrollingChild3 androidx.core.view.NestedScrollingParent3 androidx.core.view.ScrollingView {
+ ctor public NestedScrollView(android.content.Context);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?);
+ ctor public NestedScrollView(android.content.Context, android.util.AttributeSet?, int);
+ method public boolean arrowScroll(int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeHorizontalScrollRange();
+ method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect!);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollExtent();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollOffset();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int computeVerticalScrollRange();
+ method public boolean dispatchNestedPreScroll(int, int, int[]?, int[]?, int);
+ method public void dispatchNestedScroll(int, int, int, int, int[]?, int, int[]);
+ method public boolean dispatchNestedScroll(int, int, int, int, int[]?, int);
+ method public boolean executeKeyEvent(android.view.KeyEvent);
+ method public void fling(int);
+ method public boolean fullScroll(int);
+ method public int getMaxScrollAmount();
+ method public boolean hasNestedScrollingParent(int);
+ method public boolean isFillViewport();
+ method public boolean isSmoothScrollingEnabled();
+ method public void onAttachedToWindow();
+ method public void onNestedPreScroll(android.view.View, int, int, int[], int);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int, int[]);
+ method public void onNestedScroll(android.view.View, int, int, int, int, int);
+ method public void onNestedScrollAccepted(android.view.View, android.view.View, int, int);
+ method public boolean onStartNestedScroll(android.view.View, android.view.View, int, int);
+ method public void onStopNestedScroll(android.view.View, int);
+ method public boolean pageScroll(int);
+ method public void setFillViewport(boolean);
+ method public void setOnScrollChangeListener(androidx.core.widget.NestedScrollView.OnScrollChangeListener?);
+ method public void setSmoothScrollingEnabled(boolean);
+ method public final void smoothScrollBy(int, int);
+ method public final void smoothScrollBy(int, int, int);
+ method public final void smoothScrollTo(int, int);
+ method public final void smoothScrollTo(int, int, int);
+ method public boolean startNestedScroll(int, int);
+ method public void stopNestedScroll(int);
+ }
+
+ public static interface NestedScrollView.OnScrollChangeListener {
+ method public void onScrollChange(androidx.core.widget.NestedScrollView, int, int, int, int);
+ }
+
+ public final class PopupMenuCompat {
+ method public static android.view.View.OnTouchListener? getDragToOpenListener(Object);
+ }
+
+ public final class PopupWindowCompat {
+ method public static boolean getOverlapAnchor(android.widget.PopupWindow);
+ method public static int getWindowLayoutType(android.widget.PopupWindow);
+ method public static void setOverlapAnchor(android.widget.PopupWindow, boolean);
+ method public static void setWindowLayoutType(android.widget.PopupWindow, int);
+ method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
+ }
+
+ @Deprecated public final class ScrollerCompat {
+ method @Deprecated public void abortAnimation();
+ method @Deprecated public boolean computeScrollOffset();
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!);
+ method @Deprecated public static androidx.core.widget.ScrollerCompat! create(android.content.Context!, android.view.animation.Interpolator!);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int);
+ method @Deprecated public void fling(int, int, int, int, int, int, int, int, int, int);
+ method @Deprecated public float getCurrVelocity();
+ method @Deprecated public int getCurrX();
+ method @Deprecated public int getCurrY();
+ method @Deprecated public int getFinalX();
+ method @Deprecated public int getFinalY();
+ method @Deprecated public boolean isFinished();
+ method @Deprecated public boolean isOverScrolled();
+ method @Deprecated public void notifyHorizontalEdgeReached(int, int, int);
+ method @Deprecated public void notifyVerticalEdgeReached(int, int, int);
+ method @Deprecated public boolean springBack(int, int, int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int);
+ method @Deprecated public void startScroll(int, int, int, int, int);
+ }
+
+ public final class TextViewCompat {
+ method public static int getAutoSizeMaxTextSize(android.widget.TextView);
+ method public static int getAutoSizeMinTextSize(android.widget.TextView);
+ method public static int getAutoSizeStepGranularity(android.widget.TextView);
+ method public static int[] getAutoSizeTextAvailableSizes(android.widget.TextView);
+ method public static int getAutoSizeTextType(android.widget.TextView);
+ method public static android.content.res.ColorStateList? getCompoundDrawableTintList(android.widget.TextView);
+ method public static android.graphics.PorterDuff.Mode? getCompoundDrawableTintMode(android.widget.TextView);
+ method public static android.graphics.drawable.Drawable![] getCompoundDrawablesRelative(android.widget.TextView);
+ method public static int getFirstBaselineToTopHeight(android.widget.TextView);
+ method public static int getLastBaselineToBottomHeight(android.widget.TextView);
+ method public static int getMaxLines(android.widget.TextView);
+ method public static int getMinLines(android.widget.TextView);
+ method public static androidx.core.text.PrecomputedTextCompat.Params getTextMetricsParams(android.widget.TextView);
+ method public static void setAutoSizeTextTypeUniformWithConfiguration(android.widget.TextView, int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeUniformWithPresetSizes(android.widget.TextView, int[], int) throws java.lang.IllegalArgumentException;
+ method public static void setAutoSizeTextTypeWithDefaults(android.widget.TextView, int);
+ method public static void setCompoundDrawableTintList(android.widget.TextView, android.content.res.ColorStateList?);
+ method public static void setCompoundDrawableTintMode(android.widget.TextView, android.graphics.PorterDuff.Mode?);
+ method public static void setCompoundDrawablesRelative(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?, android.graphics.drawable.Drawable?);
+ method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, @DrawableRes int, @DrawableRes int, @DrawableRes int, @DrawableRes int);
+ method public static void setCustomSelectionActionModeCallback(android.widget.TextView, android.view.ActionMode.Callback);
+ method public static void setFirstBaselineToTopHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLastBaselineToBottomHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setLineHeight(android.widget.TextView, @IntRange(from=0) @Px int);
+ method public static void setPrecomputedText(android.widget.TextView, androidx.core.text.PrecomputedTextCompat);
+ method public static void setTextAppearance(android.widget.TextView, @StyleRes int);
+ method public static void setTextMetricsParams(android.widget.TextView, androidx.core.text.PrecomputedTextCompat.Params);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.view.ActionMode.Callback? unwrapCustomSelectionActionModeCallback(android.view.ActionMode.Callback?);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static android.view.ActionMode.Callback? wrapCustomSelectionActionModeCallback(android.widget.TextView, android.view.ActionMode.Callback?);
+ field public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0; // 0x0
+ field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
+ }
+
+ @IntDef({androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE, androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface TextViewCompat.AutoSizeTextType {
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class TextViewOnReceiveContentListener implements androidx.core.view.OnReceiveContentListener {
+ ctor public TextViewOnReceiveContentListener();
+ method public androidx.core.view.ContentInfoCompat? onReceiveContent(android.view.View, androidx.core.view.ContentInfoCompat);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface TintableCheckedTextView {
+ method public android.content.res.ColorStateList? getSupportCheckMarkTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportCheckMarkTintMode();
+ method public void setSupportCheckMarkTintList(android.content.res.ColorStateList?);
+ method public void setSupportCheckMarkTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ public interface TintableCompoundButton {
+ method public android.content.res.ColorStateList? getSupportButtonTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
+ method public void setSupportButtonTintList(android.content.res.ColorStateList?);
+ method public void setSupportButtonTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ public interface TintableCompoundDrawablesView {
+ method public android.content.res.ColorStateList? getSupportCompoundDrawablesTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportCompoundDrawablesTintMode();
+ method public void setSupportCompoundDrawablesTintList(android.content.res.ColorStateList?);
+ method public void setSupportCompoundDrawablesTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface TintableImageSourceView {
+ method public android.content.res.ColorStateList? getSupportImageTintList();
+ method public android.graphics.PorterDuff.Mode? getSupportImageTintMode();
+ method public void setSupportImageTintList(android.content.res.ColorStateList?);
+ method public void setSupportImageTintMode(android.graphics.PorterDuff.Mode?);
+ }
+
+}
+
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 9556806..07bd416 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -3720,7 +3720,7 @@
method public androidx.core.view.accessibility.AccessibilityNodeInfoCompat! getLabeledBy();
method public int getLiveRegion();
method public int getMaxTextLength();
- method public int getMinMillisBetweenContentChanges();
+ method public long getMinDurationBetweenContentChangesMillis();
method public int getMovementGranularities();
method public CharSequence! getPackageName();
method public CharSequence? getPaneTitle();
@@ -3806,7 +3806,7 @@
method public void setLiveRegion(int);
method public void setLongClickable(boolean);
method public void setMaxTextLength(int);
- method public void setMinMillisBetweenContentChanges(int);
+ method public void setMinDurationBetweenContentChangesMillis(long);
method public void setMovementGranularities(int);
method public void setMultiLine(boolean);
method public void setPackageName(CharSequence!);
diff --git a/core/core/build.gradle b/core/core/build.gradle
index 3f464c5..2f93e91 100644
--- a/core/core/build.gradle
+++ b/core/core/build.gradle
@@ -12,7 +12,7 @@
implementation(project(":core:core-ktx"))
}
- api(projectOrArtifact(":annotation:annotation"))
+ api("androidx.annotation:annotation:1.6.0")
api("androidx.annotation:annotation-experimental:1.3.0")
api("androidx.lifecycle:lifecycle-runtime:2.3.1")
api("androidx.versionedparcelable:versionedparcelable:1.1.1")
@@ -20,9 +20,6 @@
implementation("androidx.concurrent:concurrent-futures:1.0.0")
implementation("androidx.interpolator:interpolator:1.0.0")
- // Required for -Werror due to annotation-experimental use of Kotlin
- compileOnly(libs.kotlinStdlib)
-
// We don't ship this as a public artifact, so it must remain a project-type dependency.
annotationProcessor(projectOrArtifact(":versionedparcelable:versionedparcelable-compiler"))
diff --git a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
index 520a252..5ffca2f 100644
--- a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
@@ -304,6 +304,11 @@
// notification is built successfully (without throwing an exception).
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
+ Notification nDefault = builder.build();
+ if (Build.VERSION.SDK_INT >= 19) {
+ assertThat(NotificationCompat.getShowWhen(nDefault)).isTrue();
+ }
+
// test true
Notification nTrue = builder.setShowWhen(true).build();
if (Build.VERSION.SDK_INT >= 19) {
diff --git a/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java b/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
index 36ef9c7..9de302e 100644
--- a/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
@@ -45,7 +45,6 @@
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -486,7 +485,7 @@
/**
* Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
*/
- private static void closeQuietly(Closeable closeable) {
+ private static void closeQuietly(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
diff --git a/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
index 9df7bc0..805a399 100644
--- a/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
@@ -103,10 +103,10 @@
@SdkSuppress(minSdkVersion = 19)
@Test
- public void testGetSetMinMillisBetweenContentChanges() {
+ public void testGetSetMinDurationBetweenContentChanges() {
AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
- nodeCompat.setMinMillisBetweenContentChanges(200);
- assertThat(nodeCompat.getMinMillisBetweenContentChanges(), equalTo(200));
+ nodeCompat.setMinDurationBetweenContentChangesMillis(200L);
+ assertThat(nodeCompat.getMinDurationBetweenContentChangesMillis(), equalTo(200L));
}
@SdkSuppress(minSdkVersion = 19)
diff --git a/core/core/src/main/java/androidx/core/app/NotificationCompat.java b/core/core/src/main/java/androidx/core/app/NotificationCompat.java
index 679e8e0..d965579 100644
--- a/core/core/src/main/java/androidx/core/app/NotificationCompat.java
+++ b/core/core/src/main/java/androidx/core/app/NotificationCompat.java
@@ -1278,9 +1278,6 @@
/**
* Set the time that the event occurred. Notifications in the panel are
* sorted by this time.
- *
- * <p>For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is
- * not shown anymore by default and must be opted into using {@link #setShowWhen(boolean)}
*/
public @NonNull Builder setWhen(long when) {
mNotification.when = when;
@@ -1289,10 +1286,7 @@
/**
* Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown
- * in the content view.
- *
- * <p>For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this
- * defaults to {@code false}. For earlier apps, the default is {@code true}.
+ * in the content view. The default is {@code true}.
*/
public @NonNull Builder setShowWhen(boolean show) {
mShowWhen = show;
diff --git a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
index 3f54712a..7272616 100644
--- a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java
@@ -1314,9 +1314,9 @@
private static final String UNIQUE_ID_KEY =
"androidx.view.accessibility.AccessibilityNodeInfoCompat.UNIQUE_ID_KEY";
- private static final String MIN_MILLIS_BETWEEN_CONTENT_CHANGES_KEY =
+ private static final String MIN_DURATION_BETWEEN_CONTENT_CHANGES_KEY =
"androidx.view.accessibility.AccessibilityNodeInfoCompat."
- + "MIN_MILLIS_BETWEEN_CONTENT_CHANGES_KEY";
+ + "MIN_DURATION_BETWEEN_CONTENT_CHANGES_KEY";
// These don't line up with the internal framework constants, since they are independent
// and we might as well get all 32 bits of utility here.
@@ -2743,9 +2743,9 @@
/**
* Gets the minimum time duration between two content change events.
*/
- public int getMinMillisBetweenContentChanges() {
+ public long getMinDurationBetweenContentChangesMillis() {
if (Build.VERSION.SDK_INT >= 19) {
- return Api19Impl.getExtras(mInfo).getInt(MIN_MILLIS_BETWEEN_CONTENT_CHANGES_KEY);
+ return Api19Impl.getExtras(mInfo).getLong(MIN_DURATION_BETWEEN_CONTENT_CHANGES_KEY);
}
return 0;
}
@@ -2755,7 +2755,7 @@
* content change events in accessibility services.
*
* <p>
- * Example: An app can set MinMillisBetweenContentChanges as 1 min for a view which sends
+ * Example: An app can set MinDurationBetweenContentChanges as 1 min for a view which sends
* content change events to accessibility services one event per second.
* Accessibility service will throttle those content change events and only handle one event
* per minute for that view.
@@ -2764,9 +2764,9 @@
* @see AccessibilityEventCompat#getContentChangeTypes for all content change types.
* @param duration the minimum duration between content change events.
*/
- public void setMinMillisBetweenContentChanges(int duration) {
+ public void setMinDurationBetweenContentChangesMillis(long duration) {
if (Build.VERSION.SDK_INT >= 19) {
- Api19Impl.getExtras(mInfo).putInt(MIN_MILLIS_BETWEEN_CONTENT_CHANGES_KEY, duration);
+ Api19Impl.getExtras(mInfo).putLong(MIN_DURATION_BETWEEN_CONTENT_CHANGES_KEY, duration);
}
}
diff --git a/credentials/credentials-play-services-auth/build.gradle b/credentials/credentials-play-services-auth/build.gradle
index 4cbcb8c..f2ecf59 100644
--- a/credentials/credentials-play-services-auth/build.gradle
+++ b/credentials/credentials-play-services-auth/build.gradle
@@ -26,6 +26,10 @@
api(libs.kotlinStdlib)
api project(":credentials:credentials")
+ implementation("com.google.android.libraries.identity.googleid:googleid:0.0.2"){
+ exclude group: "androidx.credentials"
+ }
+
// Closed source dependencies
implementation(libs.playServicesAuth) {
exclude group: "androidx.loader"
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
index 5db9701..27c9b68 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerJavaTest.java
@@ -29,6 +29,7 @@
import androidx.test.filters.SmallTest;
import com.google.android.gms.auth.api.identity.BeginSignInRequest;
+import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,8 +41,7 @@
@SuppressWarnings("deprecation")
public class CredentialProviderBeginSignInControllerJavaTest {
@Test
- public void
- convertRequestToPlayServices_setPasswordOptionRequestAndFalseAutoSelect_success() {
+ public void convertRequestToPlayServices_setPasswordOptionRequestAndFalseAutoSelect_success() {
ActivityScenario<TestCredentialsActivity> activityScenario =
ActivityScenario.launch(TestCredentialsActivity.class);
activityScenario.onActivity(activity -> {
@@ -66,10 +66,10 @@
BeginSignInRequest actualResponse =
CredentialProviderBeginSignInController
- .getInstance(activity)
- .convertRequestToPlayServices(new GetCredentialRequest(List.of(
- new GetPasswordOption()
- ), true));
+ .getInstance(activity)
+ .convertRequestToPlayServices(new GetCredentialRequest(List.of(
+ new GetPasswordOption()
+ ), true));
assertThat(actualResponse.getPasswordRequestOptions().isSupported()).isTrue();
assertThat(actualResponse.isAutoSelectEnabled()).isTrue();
@@ -107,4 +107,44 @@
);
});
}
+
+ @Test
+ public void convertRequestToPlayServices_setGoogleIdOptionRequestAndTrueAutoSelect_success() {
+ ActivityScenario<TestCredentialsActivity> activityScenario =
+ ActivityScenario.launch(TestCredentialsActivity.class);
+
+ GetGoogleIdOption option = new GetGoogleIdOption.Builder()
+ .setServerClientId("server_client_id")
+ .setNonce("nonce")
+ .setFilterByAuthorizedAccounts(true)
+ .setRequestVerifiedPhoneNumber(false)
+ .associatedLinkedAccounts("link_service_id", List.of("a", "b", "c"))
+ .build();
+
+ activityScenario.onActivity(activity -> {
+
+ BeginSignInRequest actualRequest =
+ CredentialProviderBeginSignInController
+ .getInstance(activity)
+ .convertRequestToPlayServices(new GetCredentialRequest(List.of(
+ option
+ ), true));
+
+ assertThat(actualRequest.getGoogleIdTokenRequestOptions().isSupported()).isTrue();
+ assertThat(actualRequest.isAutoSelectEnabled()).isTrue();
+
+ BeginSignInRequest.GoogleIdTokenRequestOptions actualOption =
+ actualRequest.getGoogleIdTokenRequestOptions();
+ assertThat(actualOption.getServerClientId()).isEqualTo(option.getServerClientId());
+ assertThat(actualOption.getNonce()).isEqualTo(option.getNonce());
+ assertThat(actualOption.filterByAuthorizedAccounts()).isEqualTo(
+ option.getFilterByAuthorizedAccounts());
+ assertThat(actualOption.requestVerifiedPhoneNumber()).isEqualTo(
+ option.getRequestVerifiedPhoneNumber());
+ assertThat(actualOption.getLinkedServiceId()).isEqualTo(option.getLinkedServiceId());
+ assertThat(actualOption.getIdTokenDepositionScopes()).isEqualTo(
+ option.getIdTokenDepositionScopes());
+
+ });
+ }
}
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
index c648f28..461e8a3 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/beginsignin/CredentialProviderBeginSignInControllerTest.kt
@@ -25,6 +25,7 @@
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -75,4 +76,44 @@
assertThat(actualResponse.isAutoSelectEnabled).isTrue()
}
}
+
+ @Test
+ fun convertRequestToPlayServices_setGoogleIdOptionRequest_success() {
+ val activityScenario = ActivityScenario.launch(
+ TestCredentialsActivity::class.java
+ )
+
+ val option = GetGoogleIdOption.Builder()
+ .setServerClientId("server_client_id")
+ .setNonce("nonce")
+ .setFilterByAuthorizedAccounts(true)
+ .setRequestVerifiedPhoneNumber(false)
+ .associatedLinkedAccounts("link_service_id", listOf("a", "b", "c"))
+ .build()
+
+ activityScenario.onActivity { activity: TestCredentialsActivity? ->
+ val actualRequest = getInstance(activity!!)
+ .convertRequestToPlayServices(
+ GetCredentialRequest(
+ listOf(
+ option
+ ), true
+ )
+ )
+ assertThat(
+ actualRequest.googleIdTokenRequestOptions.isSupported
+ ).isTrue()
+ assertThat(actualRequest.isAutoSelectEnabled).isTrue()
+ val actualOption = actualRequest.googleIdTokenRequestOptions
+ assertThat(actualOption.serverClientId).isEqualTo(option.serverClientId)
+ assertThat(actualOption.nonce).isEqualTo(option.nonce)
+ assertThat(actualOption.filterByAuthorizedAccounts())
+ .isEqualTo(option.filterByAuthorizedAccounts)
+ assertThat(actualOption.requestVerifiedPhoneNumber())
+ .isEqualTo(option.requestVerifiedPhoneNumber)
+ assertThat(actualOption.linkedServiceId).isEqualTo(option.linkedServiceId)
+ assertThat(actualOption.idTokenDepositionScopes)
+ .isEqualTo(option.idTokenDepositionScopes)
+ }
+ }
}
\ No newline at end of file
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/BeginSignInControllerUtility.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/BeginSignInControllerUtility.kt
index 3f915a5..c842429 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/BeginSignInControllerUtility.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/BeginSignInControllerUtility.kt
@@ -37,6 +37,8 @@
import androidx.credentials.GetPublicKeyCredentialOption
import androidx.credentials.playservices.controllers.CreatePublicKeyCredential.PublicKeyCredentialControllerUtility.Companion.convertToPlayAuthPasskeyRequest
import com.google.android.gms.auth.api.identity.BeginSignInRequest
+import com.google.android.gms.auth.api.identity.BeginSignInRequest.GoogleIdTokenRequestOptions
+import com.google.android.libraries.identity.googleid.GetGoogleIdOption
/**
* A utility class to handle logic for the begin sign in controller.
@@ -65,12 +67,32 @@
)
isPublicKeyCredReqFound = true
// TODO("Confirm logic for single vs multiple options of the same type")
+ } else if (option is GetGoogleIdOption) {
+ requestBuilder.setGoogleIdTokenRequestOptions(
+ convertToGoogleIdTokenOption(option))
}
- // TODO("Add GoogleIDToken version")
}
return requestBuilder
.setAutoSelectEnabled(request.isAutoSelectAllowed)
.build()
}
+
+ private fun convertToGoogleIdTokenOption(option: GetGoogleIdOption):
+ GoogleIdTokenRequestOptions {
+ var idTokenOption =
+ GoogleIdTokenRequestOptions.builder()
+ .setFilterByAuthorizedAccounts(option.filterByAuthorizedAccounts)
+ .setNonce(option.nonce)
+ .setRequestVerifiedPhoneNumber(option.requestVerifiedPhoneNumber)
+ .setServerClientId(option.serverClientId)
+ .setSupported(true)
+ if (option.linkedServiceId != null) {
+ idTokenOption.associateLinkedAccounts(
+ option.linkedServiceId!!,
+ option.idTokenDepositionScopes
+ )
+ }
+ return idTokenOption.build()
+ }
}
-}
\ No newline at end of file
+}
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
index 4dbc5d5..e1ca866 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/BeginSignIn/CredentialProviderBeginSignInController.kt
@@ -46,6 +46,7 @@
import com.google.android.gms.auth.api.identity.SignInCredential
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.CommonStatusCodes
+import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import java.util.concurrent.Executor
/**
@@ -56,11 +57,11 @@
@Suppress("deprecation")
class CredentialProviderBeginSignInController(private val activity: Activity) :
CredentialProviderController<
- GetCredentialRequest,
- BeginSignInRequest,
- SignInCredential,
- GetCredentialResponse,
- GetCredentialException>(activity) {
+ GetCredentialRequest,
+ BeginSignInRequest,
+ SignInCredential,
+ GetCredentialResponse,
+ GetCredentialException>(activity) {
/**
* The callback object state, used in the protected handleResponse method.
@@ -68,6 +69,7 @@
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
lateinit var callback: CredentialManagerCallback<GetCredentialResponse,
GetCredentialException>
+
/**
* The callback requires an executor to invoke it.
*/
@@ -88,12 +90,17 @@
resultCode: Int,
resultData: Bundle
) {
- if (maybeReportErrorFromResultReceiver(resultData,
+ if (maybeReportErrorFromResultReceiver(
+ resultData,
CredentialProviderBaseController
.Companion::getCredentialExceptionTypeToException,
- executor = executor, callback = callback, cancellationSignal)) return
- handleResponse(resultData.getInt(ACTIVITY_REQUEST_CODE_TAG), resultCode,
- resultData.getParcelable(RESULT_DATA_TAG))
+ executor = executor, callback = callback, cancellationSignal
+ )
+ ) return
+ handleResponse(
+ resultData.getInt(ACTIVITY_REQUEST_CODE_TAG), resultCode,
+ resultData.getParcelable(RESULT_DATA_TAG)
+ )
}
}
@@ -107,7 +114,9 @@
this.callback = callback
this.executor = executor
- if (CredentialProviderPlayServicesImpl.cancellationReviewer(cancellationSignal)) { return }
+ if (CredentialProviderPlayServicesImpl.cancellationReviewer(cancellationSignal)) {
+ return
+ }
val convertedRequest: BeginSignInRequest = this.convertRequestToPlayServices(request)
val hiddenIntent = Intent(activity, HiddenActivity::class.java)
@@ -118,19 +127,30 @@
internal fun handleResponse(uniqueRequestCode: Int, resultCode: Int, data: Intent?) {
if (uniqueRequestCode != CONTROLLER_REQUEST_CODE) {
- Log.w(TAG, "Returned request code " +
- "$CONTROLLER_REQUEST_CODE which does not match what was given $uniqueRequestCode")
+ Log.w(
+ TAG,
+ "Returned request code $CONTROLLER_REQUEST_CODE which " +
+ " does not match what was given $uniqueRequestCode"
+ )
return
}
if (maybeReportErrorResultCodeGet(resultCode, TAG,
- { s, f -> cancelOrCallbackExceptionOrResult(s, f) }, { e -> this.executor.execute {
- this.callback.onError(e) } }, cancellationSignal)) return
+ { s, f -> cancelOrCallbackExceptionOrResult(s, f) }, { e ->
+ this.executor.execute {
+ this.callback.onError(e)
+ }
+ }, cancellationSignal
+ )
+ ) return
try {
val signInCredential = Identity.getSignInClient(activity)
.getSignInCredentialFromIntent(data)
val response = convertResponseToCredentialManager(signInCredential)
- cancelOrCallbackExceptionOrResult(cancellationSignal) { this.executor.execute {
- this.callback.onResult(response) } }
+ cancelOrCallbackExceptionOrResult(cancellationSignal) {
+ this.executor.execute {
+ this.callback.onResult(response)
+ }
+ }
} catch (e: ApiException) {
var exception: GetCredentialException = GetCredentialUnknownException(e.message)
if (e.statusCode == CommonStatusCodes.CANCELED) {
@@ -138,12 +158,18 @@
} else if (e.statusCode in retryables) {
exception = GetCredentialInterruptedException(e.message)
}
- cancelOrCallbackExceptionOrResult(cancellationSignal) { executor.execute {
- callback.onError(exception) } }
+ cancelOrCallbackExceptionOrResult(cancellationSignal) {
+ executor.execute {
+ callback.onError(exception)
+ }
+ }
return
} catch (e: GetCredentialException) {
- cancelOrCallbackExceptionOrResult(cancellationSignal) { executor.execute {
- callback.onError(e) } }
+ cancelOrCallbackExceptionOrResult(cancellationSignal) {
+ executor.execute {
+ callback.onError(e)
+ }
+ }
}
}
@@ -160,7 +186,7 @@
if (response.password != null) {
cred = PasswordCredential(response.id, response.password!!)
} else if (response.googleIdToken != null) {
- TODO(" Implement GoogleIdTokenVersion")
+ cred = createGoogleIdCredential(response)
} else if (response.publicKeyCredential != null) {
try {
cred = PublicKeyCredential(
@@ -173,16 +199,44 @@
Log.w(TAG, "Credential returned but no google Id or password or passkey found")
}
if (cred == null) {
- throw GetCredentialUnknownException("When attempting to convert get response, " +
- "null credential found")
+ throw GetCredentialUnknownException(
+ "When attempting to convert get response, " +
+ "null credential found"
+ )
}
return GetCredentialResponse(cred)
}
+ private fun createGoogleIdCredential(response: SignInCredential): GoogleIdTokenCredential {
+ var cred = GoogleIdTokenCredential.Builder().setId(response.id)
+ .setIdToken(response.googleIdToken!!)
+
+ if (response.displayName != null) {
+ cred.setDisplayName(response.displayName)
+ }
+
+ if (response.givenName != null) {
+ cred.setGivenName(response.givenName)
+ }
+
+ if (response.familyName != null) {
+ cred.setFamilyName(response.familyName)
+ }
+
+ if (response.phoneNumber != null) {
+ cred.setPhoneNumber(response.phoneNumber)
+ }
+
+ if (response.profilePictureUri != null) {
+ cred.setProfilePictureUri(response.profilePictureUri.toString())
+ }
+
+ return cred.build()
+ }
+
companion object {
private val TAG = CredentialProviderBeginSignInController::class.java.name
private var controller: CredentialProviderBeginSignInController? = null
- // TODO("Ensure this is tested for multiple calls")
/**
* This finds a past version of the [CredentialProviderBeginSignInController] if it exists,
@@ -200,4 +254,4 @@
return controller!!
}
}
-}
\ No newline at end of file
+}
diff --git a/development/auto-version-updater/update_versions_for_release.py b/development/auto-version-updater/update_versions_for_release.py
index 0cd1cd8..008f4846b 100755
--- a/development/auto-version-updater/update_versions_for_release.py
+++ b/development/auto-version-updater/update_versions_for_release.py
@@ -315,7 +315,10 @@
# Open file for writing and write toml back
with open(LIBRARY_VERSIONS_FP, 'w') as f:
- toml.dump(library_versions, f, encoder=toml.TomlPreserveInlineDictEncoder())
+ versions_toml_file_string = toml.dumps(library_versions, encoder=toml.TomlPreserveInlineDictEncoder())
+ versions_toml_file_string_new = re.sub(",]", " ]", versions_toml_file_string)
+ f.write(versions_toml_file_string_new)
+
return updated_version
@@ -471,7 +474,7 @@
msg = "Update versions for release id %s\n\nThis commit was generated from the command:\n%s\n\n%s" % (
release_date, " ".join(sys.argv), "Test: ./gradlew checkApi")
subprocess.check_call(["git", "commit", "-m", msg], cwd=dir, stderr=subprocess.STDOUT)
- subprocess.check_call(["repo", "upload", ".", "--cbr", "-t", "-y", "--label", "Presubmit-Ready+1"], cwd=dir,
+ subprocess.check_call(["repo", "upload", ".", "--cbr", "-t", "-y", "-o", "banned-words~skip", "--label", "Presubmit-Ready+1"], cwd=dir,
stderr=subprocess.STDOUT)
def main(args):
diff --git a/development/project-creator/create_project.py b/development/project-creator/create_project.py
index bc1db8e..8a121f8 100755
--- a/development/project-creator/create_project.py
+++ b/development/project-creator/create_project.py
@@ -25,6 +25,7 @@
from shutil import copyfile
from distutils.dir_util import copy_tree
from distutils.dir_util import DistutilsFileError
+import re
try:
# non-default python3 module, be helpful if it is missing
@@ -590,7 +591,9 @@
# Open file for writing and update toml
with open(LIBRARY_VERSIONS_FP, 'w') as f:
- toml.dump(library_versions, f, encoder=toml.TomlPreserveInlineDictEncoder())
+ versions_toml_file_string = toml.dumps(library_versions, encoder=toml.TomlPreserveInlineDictEncoder())
+ versions_toml_file_string_new = re.sub(",]", " ]", versions_toml_file_string)
+ f.write(versions_toml_file_string_new)
def is_group_id_atomic(group_id):
diff --git a/development/update_studio.sh b/development/update_studio.sh
index d394214..187a9d4 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -1,24 +1,9 @@
#!/bin/bash
-
-function echoAndDo() {
- echo "$@"
- eval "$@"
-}
-
# Get versions
-echo Getting Studio version and link
-AGP_VERSION=${1:-8.1.0-alpha03}
-STUDIO_VERSION_STRING=${2:-"Android Studio Giraffe | 2022.3.1 Canary 3"}
-STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
-echo iframe link $STUDIO_IFRAME_LINK
-STUDIO_IFRAME_REDIRECT=`curl -s $STUDIO_IFRAME_LINK | grep href | sed 's/.*href="\([^"]*\)".*/\1/g'`
-echo iframe redirect $STUDIO_IFRAME_REDIRECT
-STUDIO_LINK=`curl -s $STUDIO_IFRAME_REDIRECT | grep -C30 "$STUDIO_VERSION_STRING" | grep Linux | tail -n 1 | sed 's/.*a href="\(.*\).*"/\1/g' | sed 's/>.*//'`
-echo STUDIO_LINK: $STUDIO_LINK
-if [ "$STUDIO_LINK" == "" ]; then
- echo "Error: STUDIO_LINK must not be empty. Open this script and look for parsing errors. Does studio version '$STUDIO_VERSION_STRING' exist?"
- exit 1
-fi
+AGP_VERSION=${1:-8.0.0-alpha07}
+STUDIO_VERSION_STRING=${2:-"Android Studio Flamingo (2022.2.1) Canary 7"}
+STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep iframe | sed "s/.*src=\"\([a-zA-Z0-9\/\._]*\)\".*/https:\/\/android-dot-devsite-v2-prod.appspot.com\1/g"`
+STUDIO_LINK=`curl -s $STUDIO_IFRAME_LINK | grep -C30 "$STUDIO_VERSION_STRING" | grep Linux | tail -n 1 | sed 's/.*a href="\(.*\).*"/\1/g'`
STUDIO_VERSION=`echo $STUDIO_LINK | sed "s/.*ide-zips\/\(.*\)\/android-studio-.*/\1/g"`
# Update AGP
@@ -37,8 +22,7 @@
ARTIFACTS_TO_DOWNLOAD+="com.android.tools.lint:lint-gradle:$LINT_VERSION,"
ARTIFACTS_TO_DOWNLOAD+="com.android.tools:ninepatch:$LINT_VERSION,"
-# Update libs.versions.toml
-echo Updating dependency versions
+# Update studio_versions.properties
sed -i "s/androidGradlePlugin = .*/androidGradlePlugin = \"$AGP_VERSION\"/g" gradle/libs.versions.toml
sed -i "s/androidLint = \".*/androidLint = \"$LINT_VERSION\"/g" gradle/libs.versions.toml
sed -i "s/androidStudio = .*/androidStudio = \"$STUDIO_VERSION\"/g" gradle/libs.versions.toml
@@ -60,4 +44,4 @@
ARTIFACTS_TO_DOWNLOAD+="com.google.testing.platform:core:$ATP_VERSION"
# Download all the artifacts
-echoAndDo ./development/importMaven/importMaven.sh "$ARTIFACTS_TO_DOWNLOAD"
+./development/importMaven/importMaven.sh "$ARTIFACTS_TO_DOWNLOAD"
\ No newline at end of file
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index b040ec5..36bbd84 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -8,16 +8,16 @@
}
dependencies {
- docs("androidx.activity:activity:1.7.0-beta01")
- docs("androidx.activity:activity-compose:1.7.0-beta01")
- samples("androidx.activity:activity-compose-samples:1.7.0-beta01")
- docs("androidx.activity:activity-ktx:1.7.0-beta01")
+ docs("androidx.activity:activity:1.8.0-alpha01")
+ docs("androidx.activity:activity-compose:1.8.0-alpha01")
+ samples("androidx.activity:activity-compose-samples:1.8.0-alpha01")
+ docs("androidx.activity:activity-ktx:1.8.0-alpha01")
docs("androidx.ads:ads-identifier:1.0.0-alpha04")
docs("androidx.ads:ads-identifier-provider:1.0.0-alpha04")
- docs("androidx.annotation:annotation:1.6.0-alpha02")
+ docs("androidx.annotation:annotation:1.6.0-rc01")
docs("androidx.annotation:annotation-experimental:1.3.0")
- docs("androidx.appcompat:appcompat:1.7.0-alpha01")
- docs("androidx.appcompat:appcompat-resources:1.7.0-alpha01")
+ docs("androidx.appcompat:appcompat:1.7.0-alpha02")
+ docs("androidx.appcompat:appcompat-resources:1.7.0-alpha02")
docs("androidx.appsearch:appsearch:1.1.0-alpha02")
docs("androidx.appsearch:appsearch-builtin-types:1.1.0-alpha02")
docs("androidx.appsearch:appsearch-ktx:1.1.0-alpha02")
@@ -36,7 +36,7 @@
docs("androidx.biometric:biometric:1.2.0-alpha05")
docs("androidx.biometric:biometric-ktx:1.2.0-alpha05")
samples("androidx.biometric:biometric-ktx-samples:1.2.0-alpha05")
- docs("androidx.browser:browser:1.5.0-rc01")
+ docs("androidx.browser:browser:1.5.0")
docs("androidx.camera:camera-camera2:1.3.0-alpha03")
docs("androidx.camera:camera-core:1.3.0-alpha03")
docs("androidx.camera:camera-extensions:1.3.0-alpha03")
@@ -54,60 +54,60 @@
docs("androidx.cardview:cardview:1.0.0")
docs("androidx.collection:collection:1.3.0-alpha02")
docs("androidx.collection:collection-ktx:1.3.0-alpha02")
- docs("androidx.compose.animation:animation:1.4.0-alpha05")
- docs("androidx.compose.animation:animation-core:1.4.0-alpha05")
- docs("androidx.compose.animation:animation-graphics:1.4.0-alpha05")
- samples("androidx.compose.animation:animation-samples:1.4.0-alpha05")
- samples("androidx.compose.animation:animation-core-samples:1.4.0-alpha05")
- samples("androidx.compose.animation:animation-graphics-samples:1.4.0-alpha05")
- docs("androidx.compose.foundation:foundation:1.4.0-alpha05")
- docs("androidx.compose.foundation:foundation-layout:1.4.0-alpha05")
- samples("androidx.compose.foundation:foundation-layout-samples:1.4.0-alpha05")
- samples("androidx.compose.foundation:foundation-samples:1.4.0-alpha05")
- docs("androidx.compose.material3:material3:1.1.0-alpha05")
- samples("androidx.compose.material3:material3-samples:1.1.0-alpha05")
- docs("androidx.compose.material3:material3-window-size-class:1.1.0-alpha05")
- samples("androidx.compose.material3:material3-window-size-class-samples:1.1.0-alpha05")
- docs("androidx.compose.material:material:1.4.0-alpha05")
- docs("androidx.compose.material:material-icons-core:1.4.0-alpha05")
- samples("androidx.compose.material:material-icons-core-samples:1.4.0-alpha05")
- docs("androidx.compose.material:material-ripple:1.4.0-alpha05")
- samples("androidx.compose.material:material-samples:1.4.0-alpha05")
- docs("androidx.compose.runtime:runtime:1.4.0-alpha05")
- docs("androidx.compose.runtime:runtime-livedata:1.4.0-alpha05")
- samples("androidx.compose.runtime:runtime-livedata-samples:1.4.0-alpha05")
- docs("androidx.compose.runtime:runtime-rxjava2:1.4.0-alpha05")
- samples("androidx.compose.runtime:runtime-rxjava2-samples:1.4.0-alpha05")
- docs("androidx.compose.runtime:runtime-rxjava3:1.4.0-alpha05")
- samples("androidx.compose.runtime:runtime-rxjava3-samples:1.4.0-alpha05")
- docs("androidx.compose.runtime:runtime-saveable:1.4.0-alpha05")
- samples("androidx.compose.runtime:runtime-saveable-samples:1.4.0-alpha05")
- samples("androidx.compose.runtime:runtime-samples:1.4.0-alpha05")
+ docs("androidx.compose.animation:animation:1.4.0-beta01")
+ docs("androidx.compose.animation:animation-core:1.4.0-beta01")
+ docs("androidx.compose.animation:animation-graphics:1.4.0-beta01")
+ samples("androidx.compose.animation:animation-samples:1.4.0-beta01")
+ samples("androidx.compose.animation:animation-core-samples:1.4.0-beta01")
+ samples("androidx.compose.animation:animation-graphics-samples:1.4.0-beta01")
+ docs("androidx.compose.foundation:foundation:1.4.0-beta01")
+ docs("androidx.compose.foundation:foundation-layout:1.4.0-beta01")
+ samples("androidx.compose.foundation:foundation-layout-samples:1.4.0-beta01")
+ samples("androidx.compose.foundation:foundation-samples:1.4.0-beta01")
+ docs("androidx.compose.material3:material3:1.1.0-alpha06")
+ samples("androidx.compose.material3:material3-samples:1.1.0-alpha06")
+ docs("androidx.compose.material3:material3-window-size-class:1.1.0-alpha06")
+ samples("androidx.compose.material3:material3-window-size-class-samples:1.1.0-alpha06")
+ docs("androidx.compose.material:material:1.4.0-beta01")
+ docs("androidx.compose.material:material-icons-core:1.4.0-beta01")
+ samples("androidx.compose.material:material-icons-core-samples:1.4.0-beta01")
+ docs("androidx.compose.material:material-ripple:1.4.0-beta01")
+ samples("androidx.compose.material:material-samples:1.4.0-beta01")
+ docs("androidx.compose.runtime:runtime:1.4.0-beta01")
+ docs("androidx.compose.runtime:runtime-livedata:1.4.0-beta01")
+ samples("androidx.compose.runtime:runtime-livedata-samples:1.4.0-beta01")
+ docs("androidx.compose.runtime:runtime-rxjava2:1.4.0-beta01")
+ samples("androidx.compose.runtime:runtime-rxjava2-samples:1.4.0-beta01")
+ docs("androidx.compose.runtime:runtime-rxjava3:1.4.0-beta01")
+ samples("androidx.compose.runtime:runtime-rxjava3-samples:1.4.0-beta01")
+ docs("androidx.compose.runtime:runtime-saveable:1.4.0-beta01")
+ samples("androidx.compose.runtime:runtime-saveable-samples:1.4.0-beta01")
+ samples("androidx.compose.runtime:runtime-samples:1.4.0-beta01")
docs("androidx.compose.runtime:runtime-tracing:1.0.0-alpha02")
- docs("androidx.compose.ui:ui:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-geometry:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-graphics:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-graphics-samples:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-test:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-test-junit4:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-test-samples:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-text:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-text-google-fonts:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-text-samples:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-tooling:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-tooling-data:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-tooling-preview:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-unit:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-unit-samples:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-util:1.4.0-alpha05")
- docs("androidx.compose.ui:ui-viewbinding:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-viewbinding-samples:1.4.0-alpha05")
- samples("androidx.compose.ui:ui-samples:1.4.0-alpha05")
+ docs("androidx.compose.ui:ui:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-geometry:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-graphics:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-graphics-samples:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-test:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-test-junit4:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-test-samples:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-text:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-text-google-fonts:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-text-samples:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-tooling:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-tooling-data:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-tooling-preview:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-unit:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-unit-samples:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-util:1.4.0-beta01")
+ docs("androidx.compose.ui:ui-viewbinding:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-viewbinding-samples:1.4.0-beta01")
+ samples("androidx.compose.ui:ui-samples:1.4.0-beta01")
docs("androidx.concurrent:concurrent-futures:1.1.0")
docs("androidx.concurrent:concurrent-futures-ktx:1.1.0")
- docs("androidx.constraintlayout:constraintlayout:2.2.0-alpha06")
- docs("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha06")
- docs("androidx.constraintlayout:constraintlayout-core:1.1.0-alpha06")
+ docs("androidx.constraintlayout:constraintlayout:2.2.0-alpha07")
+ docs("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha07")
+ docs("androidx.constraintlayout:constraintlayout-core:1.1.0-alpha07")
docs("androidx.contentpager:contentpager:1.0.0")
docs("androidx.coordinatorlayout:coordinatorlayout:1.2.0")
docs("androidx.core.uwb:uwb:1.0.0-alpha04")
@@ -122,8 +122,9 @@
docs("androidx.core:core:1.10.0-alpha02")
docs("androidx.core:core-ktx:1.10.0-alpha02")
docs("androidx.core:core-splashscreen:1.1.0-alpha01")
- docs("androidx.credentials:credentials:1.0.0-alpha01")
- docs("androidx.credentials:credentials-play-services-auth:1.0.0-alpha01")
+ docs("androidx.credentials:credentials:1.0.0-alpha02")
+ docs("androidx.credentials:credentials-play-services-auth:1.0.0-alpha02")
+ docs("androidx.credentials:credentials-provider:1.0.0-alpha02")
docs("androidx.cursoradapter:cursoradapter:1.0.0")
docs("androidx.customview:customview:1.2.0-alpha02")
docs("androidx.customview:customview-poolingcontainer:1.0.0-rc01")
@@ -138,23 +139,23 @@
docs("androidx.datastore:datastore-rxjava3:1.1.0-alpha01")
docs("androidx.documentfile:documentfile:1.1.0-alpha01")
docs("androidx.draganddrop:draganddrop:1.0.0")
- docs("androidx.drawerlayout:drawerlayout:1.2.0-alpha01")
+ docs("androidx.drawerlayout:drawerlayout:1.2.0-beta01")
docs("androidx.dynamicanimation:dynamicanimation:1.1.0-alpha02")
docs("androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha03")
- docs("androidx.emoji2:emoji2:1.3.0-beta01")
- docs("androidx.emoji2:emoji2-bundled:1.3.0-beta01")
- docs("androidx.emoji2:emoji2-emojipicker:1.0.0-alpha01")
- docs("androidx.emoji2:emoji2-views:1.3.0-beta01")
- docs("androidx.emoji2:emoji2-views-helper:1.3.0-beta01")
+ docs("androidx.emoji2:emoji2:1.3.0-beta02")
+ docs("androidx.emoji2:emoji2-bundled:1.3.0-beta02")
+ docs("androidx.emoji2:emoji2-emojipicker:1.0.0-alpha02")
+ docs("androidx.emoji2:emoji2-views:1.3.0-beta02")
+ docs("androidx.emoji2:emoji2-views-helper:1.3.0-beta02")
docs("androidx.emoji:emoji:1.2.0-alpha03")
docs("androidx.emoji:emoji-appcompat:1.2.0-alpha03")
docs("androidx.emoji:emoji-bundled:1.2.0-alpha03")
docs("androidx.enterprise:enterprise-feedback:1.1.0")
docs("androidx.enterprise:enterprise-feedback-testing:1.1.0")
- docs("androidx.exifinterface:exifinterface:1.3.5")
- docs("androidx.fragment:fragment:1.6.0-alpha04")
- docs("androidx.fragment:fragment-ktx:1.6.0-alpha04")
- docs("androidx.fragment:fragment-testing:1.6.0-alpha04")
+ docs("androidx.exifinterface:exifinterface:1.3.6")
+ docs("androidx.fragment:fragment:1.6.0-alpha05")
+ docs("androidx.fragment:fragment-ktx:1.6.0-alpha05")
+ docs("androidx.fragment:fragment-testing:1.6.0-alpha05")
docs("androidx.glance:glance:1.0.0-alpha05")
docs("androidx.glance:glance-appwidget:1.0.0-alpha05")
docs("androidx.glance:glance-appwidget-preview:1.0.0-alpha05")
@@ -226,18 +227,18 @@
docs("androidx.navigation:navigation-testing:2.6.0-alpha05")
docs("androidx.navigation:navigation-ui:2.6.0-alpha05")
docs("androidx.navigation:navigation-ui-ktx:2.6.0-alpha05")
- docs("androidx.paging:paging-common:3.2.0-alpha03")
- docs("androidx.paging:paging-common-ktx:3.2.0-alpha03")
- docs("androidx.paging:paging-compose:1.0.0-alpha17")
+ docs("androidx.paging:paging-common:3.2.0-alpha04")
+ docs("androidx.paging:paging-common-ktx:3.2.0-alpha04")
+ docs("androidx.paging:paging-compose:1.0.0-alpha18")
samples("androidx.paging:paging-compose-samples:3.0.0-alpha08")
- docs("androidx.paging:paging-guava:3.2.0-alpha03")
- docs("androidx.paging:paging-runtime:3.2.0-alpha03")
- docs("androidx.paging:paging-runtime-ktx:3.2.0-alpha03")
- docs("androidx.paging:paging-rxjava2:3.2.0-alpha03")
- docs("androidx.paging:paging-rxjava2-ktx:3.2.0-alpha03")
- docs("androidx.paging:paging-rxjava3:3.2.0-alpha03")
- samples("androidx.paging:paging-samples:3.2.0-alpha03")
- docs("androidx.paging:paging-testing:3.2.0-alpha03")
+ docs("androidx.paging:paging-guava:3.2.0-alpha04")
+ docs("androidx.paging:paging-runtime:3.2.0-alpha04")
+ docs("androidx.paging:paging-runtime-ktx:3.2.0-alpha04")
+ docs("androidx.paging:paging-rxjava2:3.2.0-alpha04")
+ docs("androidx.paging:paging-rxjava2-ktx:3.2.0-alpha04")
+ docs("androidx.paging:paging-rxjava3:3.2.0-alpha04")
+ samples("androidx.paging:paging-samples:3.2.0-alpha04")
+ docs("androidx.paging:paging-testing:3.2.0-alpha04")
docs("androidx.palette:palette:1.0.0")
docs("androidx.palette:palette-ktx:1.0.0")
docs("androidx.percentlayout:percentlayout:1.0.1")
@@ -248,7 +249,7 @@
docs("androidx.privacysandbox.tools:tools-apigenerator:1.0.0-alpha02")
docs("androidx.privacysandbox.tools:tools-apipackager:1.0.0-alpha02")
docs("androidx.privacysandbox.tools:tools-core:1.0.0-alpha02")
- docs("androidx.profileinstaller:profileinstaller:1.3.0-alpha03")
+ docs("androidx.profileinstaller:profileinstaller:1.3.0-beta01")
docs("androidx.recommendation:recommendation:1.0.0")
docs("androidx.recyclerview:recyclerview:1.3.0-rc01")
docs("androidx.recyclerview:recyclerview-selection:2.0.0-alpha01")
@@ -308,12 +309,13 @@
docs("androidx.textclassifier:textclassifier:1.0.0-alpha04")
docs("androidx.tracing:tracing:1.2.0-alpha02")
docs("androidx.tracing:tracing-ktx:1.2.0-alpha02")
- docs("androidx.tracing:tracing-perfetto:1.0.0-alpha09")
- docs("androidx.tracing:tracing-perfetto-common:1.0.0-alpha09")
+ docs("androidx.tracing:tracing-perfetto:1.0.0-alpha10")
+ docs("androidx.tracing:tracing-perfetto-common:1.0.0-alpha10")
docs("androidx.transition:transition:1.4.1")
docs("androidx.transition:transition-ktx:1.4.1")
- docs("androidx.tv:tv-foundation:1.0.0-alpha03")
- docs("androidx.tv:tv-material:1.0.0-alpha03")
+ docs("androidx.tv:tv-foundation:1.0.0-alpha04")
+ docs("androidx.tv:tv-material:1.0.0-alpha04")
+ samples("androidx.tv:tv-samples:1.0.0-alpha04")
docs("androidx.tvprovider:tvprovider:1.1.0-alpha01")
docs("androidx.vectordrawable:vectordrawable:1.2.0-beta01")
docs("androidx.vectordrawable:vectordrawable-animated:1.2.0-alpha01")
@@ -321,19 +323,19 @@
docs("androidx.versionedparcelable:versionedparcelable:1.1.1")
docs("androidx.viewpager2:viewpager2:1.1.0-beta01")
docs("androidx.viewpager:viewpager:1.1.0-alpha01")
- docs("androidx.wear.compose:compose-foundation:1.2.0-alpha03")
- samples("androidx.wear.compose:compose-foundation-samples:1.2.0-alpha03")
- docs("androidx.wear.compose:compose-material:1.2.0-alpha03")
- docs("androidx.wear.compose:compose-material-core:1.2.0-alpha03")
- samples("androidx.wear.compose:compose-material-samples:1.2.0-alpha03")
+ docs("androidx.wear.compose:compose-foundation:1.2.0-alpha04")
+ samples("androidx.wear.compose:compose-foundation-samples:1.2.0-alpha04")
+ docs("androidx.wear.compose:compose-material:1.2.0-alpha04")
+ docs("androidx.wear.compose:compose-material-core:1.2.0-alpha04")
+ samples("androidx.wear.compose:compose-material-samples:1.2.0-alpha04")
docs("androidx.wear.compose:compose-material3:1.0.0-alpha01")
- samples("androidx.wear.compose:compose-material3-samples:1.2.0-alpha03")
- docs("androidx.wear.compose:compose-navigation:1.2.0-alpha03")
- samples("androidx.wear.compose:compose-navigation-samples:1.2.0-alpha03")
- docs("androidx.wear.protolayout:protolayout:1.0.0-alpha02")
- docs("androidx.wear.protolayout:protolayout-expression:1.0.0-alpha02")
- docs("androidx.wear.protolayout:protolayout-proto:1.0.0-alpha02")
- docs("androidx.wear.protolayout:protolayout-renderer:1.0.0-alpha02")
+ samples("androidx.wear.compose:compose-material3-samples:1.2.0-alpha04")
+ docs("androidx.wear.compose:compose-navigation:1.2.0-alpha04")
+ samples("androidx.wear.compose:compose-navigation-samples:1.2.0-alpha04")
+ docs("androidx.wear.protolayout:protolayout:1.0.0-alpha03")
+ docs("androidx.wear.protolayout:protolayout-expression:1.0.0-alpha03")
+ docs("androidx.wear.protolayout:protolayout-proto:1.0.0-alpha03")
+ docs("androidx.wear.protolayout:protolayout-renderer:1.0.0-alpha03")
docs("androidx.wear.tiles:tiles:1.1.0")
docs("androidx.wear.tiles:tiles-material:1.1.0")
docs("androidx.wear.tiles:tiles-proto:1.1.0")
@@ -363,7 +365,7 @@
docs("androidx.wear:wear-input:1.2.0-alpha02")
samples("androidx.wear:wear-input-samples:1.2.0-alpha01")
docs("androidx.wear:wear-input-testing:1.2.0-alpha02")
- docs("androidx.webkit:webkit:1.7.0-alpha01")
+ docs("androidx.webkit:webkit:1.7.0-alpha02")
docs("androidx.window:window:1.1.0-alpha04")
stubs(fileTree(dir: "../window/stubs/", include: ["window-sidecar-release-0.1.0-alpha01.aar"]))
docs("androidx.window:window-core:1.1.0-alpha04")
@@ -372,11 +374,11 @@
docs("androidx.window:window-rxjava2:1.1.0-alpha04")
docs("androidx.window:window-rxjava3:1.1.0-alpha04")
docs("androidx.window:window-testing:1.1.0-alpha04")
- docs("androidx.work:work-gcm:2.8.0-rc01")
- docs("androidx.work:work-multiprocess:2.8.0-rc01")
- docs("androidx.work:work-runtime:2.8.0-rc01")
- docs("androidx.work:work-runtime-ktx:2.8.0-rc01")
- docs("androidx.work:work-rxjava2:2.8.0-rc01")
- docs("androidx.work:work-rxjava3:2.8.0-rc01")
- docs("androidx.work:work-testing:2.8.0-rc01")
+ docs("androidx.work:work-gcm:2.8.0")
+ docs("androidx.work:work-multiprocess:2.8.0")
+ docs("androidx.work:work-runtime:2.8.0")
+ docs("androidx.work:work-runtime-ktx:2.8.0")
+ docs("androidx.work:work-rxjava2:2.8.0")
+ docs("androidx.work:work-rxjava3:2.8.0")
+ docs("androidx.work:work-testing:2.8.0")
}
diff --git a/dynamicanimation/dynamicanimation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java b/dynamicanimation/dynamicanimation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
index 64702c0..58b53c0 100644
--- a/dynamicanimation/dynamicanimation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
+++ b/dynamicanimation/dynamicanimation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
@@ -59,6 +59,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -874,6 +875,7 @@
}
+ @Ignore // b/268534501
@Test
@SdkSuppress(minSdkVersion = 33, maxSdkVersion = 33) // b/262909049: Failing on SDK 34
public void testDurationScaleChangeListener() throws InterruptedException {
diff --git a/emoji2/emoji2-emojipicker/samples/src/main/res/layout-land/main.xml b/emoji2/emoji2-emojipicker/samples/src/main/res/layout-land/main.xml
index 6f076ad..7c10005 100644
--- a/emoji2/emoji2-emojipicker/samples/src/main/res/layout-land/main.xml
+++ b/emoji2/emoji2-emojipicker/samples/src/main/res/layout-land/main.xml
@@ -46,6 +46,5 @@
android:id="@+id/emoji_picker"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:emojiGridColumns="20"
- app:emojiGridRows="5" />
+ app:emojiGridColumns="20" />
</LinearLayout>
diff --git a/emoji2/emoji2-emojipicker/samples/src/main/res/layout/main.xml b/emoji2/emoji2-emojipicker/samples/src/main/res/layout/main.xml
index 085f307..f79a375 100644
--- a/emoji2/emoji2-emojipicker/samples/src/main/res/layout/main.xml
+++ b/emoji2/emoji2-emojipicker/samples/src/main/res/layout/main.xml
@@ -46,6 +46,5 @@
android:id="@+id/emoji_picker"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:emojiGridRows="15"
app:emojiGridColumns="9" />
</LinearLayout>
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt
index 4f688fd..7f8fa6b9 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerBodyAdapter.kt
@@ -33,7 +33,7 @@
internal class EmojiPickerBodyAdapter(
private val context: Context,
private val emojiGridColumns: Int,
- private val emojiGridRows: Float,
+ private val emojiGridRows: Float?,
private val stickyVariantProvider: StickyVariantProvider,
private val emojiPickerItemsProvider: () -> EmojiPickerItems,
private val onEmojiPickedListener: EmojiPickerBodyAdapter.(EmojiViewItem) -> Unit,
@@ -43,25 +43,25 @@
private var emojiCellHeight: Int? = null
@UiThread
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
- when (viewType.toItemType()) {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ emojiCellWidth = emojiCellWidth ?: (getParentWidth(parent) / emojiGridColumns)
+ emojiCellHeight =
+ emojiCellHeight ?: emojiGridRows?.let { getEmojiCellTotalHeight(parent) / it }
+ ?.toInt() ?: emojiCellWidth
+
+ return when (viewType.toItemType()) {
ItemType.CATEGORY_TITLE -> createSimpleHolder(R.layout.category_text_view, parent)
ItemType.PLACEHOLDER_TEXT -> createSimpleHolder(
R.layout.empty_category_text_view, parent
) {
- minimumHeight =
- emojiCellHeight ?: (getEmojiCellTotalHeight(parent) / (emojiGridRows)).toInt()
- .also { emojiCellHeight = it }
+ minimumHeight = emojiCellHeight!!
}
ItemType.EMOJI -> {
EmojiViewHolder(context,
parent,
- emojiCellWidth ?: (getParentWidth(parent) / emojiGridColumns).also {
- emojiCellWidth = it
- },
- emojiCellHeight ?: (getEmojiCellTotalHeight(parent) / (emojiGridRows)).toInt()
- .also { emojiCellHeight = it },
+ emojiCellWidth!!,
+ emojiCellHeight!!,
layoutInflater,
stickyVariantProvider,
onEmojiPickedListener = { emojiViewItem ->
@@ -81,9 +81,8 @@
}
})
}
-
- ItemType.PLACEHOLDER_EMOJI -> object : ViewHolder(View(context)) {}
}
+ }
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val item = emojiPickerItemsProvider().getBodyItem(position)
@@ -99,8 +98,6 @@
ItemType.EMOJI -> {
(viewHolder as EmojiViewHolder).bindEmoji((item as EmojiViewData).emoji)
}
-
- ItemType.PLACEHOLDER_EMOJI -> {}
}
}
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt
index 479e1ff..0956f96 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerConstants.kt
@@ -22,9 +22,6 @@
// The default number of body columns.
const val DEFAULT_BODY_COLUMNS = 9
- // The default number of body rows.
- const val DEFAULT_BODY_ROWS = 7.5f
-
// The default number of rows of recent items held.
const val DEFAULT_MAX_RECENT_ITEM_ROWS = 3
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt
index 33ea012..7ac2aa6 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerItems.kt
@@ -24,8 +24,7 @@
* [titleItem] comes first.
* [contentItems] comes after [titleItem].
* [emptyPlaceholderItem] will be served after [titleItem] only if [contentItems] is empty.
- * [forceContentSize], if provided, will truncate [contentItems] to certain size or pad with
- * [PlaceholderEmoji]s.
+ * [maxContentItemCount], if provided, will truncate [contentItems] to certain size.
*
* [categoryIconId] is the corresponding category icon in emoji picker header.
*/
@@ -33,23 +32,24 @@
@DrawableRes internal val categoryIconId: Int,
internal val titleItem: CategoryTitle,
private val contentItems: List<EmojiViewData>,
- private val forceContentSize: Int? = null,
+ private val maxContentItemCount: Int? = null,
private val emptyPlaceholderItem: PlaceholderText? = null
) {
val size: Int
- get() = 1 /* title */ +
- (forceContentSize ?: maxOf(
- contentItems.size,
- if (emptyPlaceholderItem != null) 1 else 0
- ))
+ get() = 1 /* title */ + when {
+ contentItems.isEmpty() -> if (emptyPlaceholderItem != null) 1 else 0
+ maxContentItemCount != null && contentItems.size > maxContentItemCount ->
+ maxContentItemCount
+ else -> contentItems.size
+ }
operator fun get(index: Int): ItemViewData {
if (index == 0) return titleItem
val contentIndex = index - 1
if (contentIndex < contentItems.size) return contentItems[contentIndex]
if (contentIndex == 0 && emptyPlaceholderItem != null) return emptyPlaceholderItem
- return PlaceholderEmoji
+ throw IndexOutOfBoundsException()
}
fun getAll(): List<ItemViewData> = IntRange(0, size - 1).map { get(it) }
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt
index ca5569f..c7f1d07 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/EmojiPickerView.kt
@@ -50,19 +50,21 @@
internal var emojiCompatLoaded: Boolean = false
}
+ private var _emojiGridRows: Float? = null
/**
* The number of rows of the emoji picker.
*
- * Default value([EmojiPickerConstants.DEFAULT_BODY_ROWS]: 7.5) will be used if emojiGridRows
- * is set to non-positive value. Float value indicates that we will display partial of the last
- * row and have content down, so the users get the idea that they can scroll down for more
- * contents.
+ * Optional field. If not set, the value will be calculated based on parent view height and
+ * [emojiGridColumns].
+ * Float value indicates that the picker could display the last row partially, so the users get
+ * the idea that they can scroll down for more contents.
* @attr ref androidx.emoji2.emojipicker.R.styleable.EmojiPickerView_emojiGridRows
*/
- var emojiGridRows: Float = EmojiPickerConstants.DEFAULT_BODY_ROWS
+ var emojiGridRows: Float
+ get() = _emojiGridRows ?: -1F
set(value) {
- field = if (value > 0) value else EmojiPickerConstants.DEFAULT_BODY_ROWS
- // this step is to ensure the layout refresh when emojiGridRows is reset
+ _emojiGridRows = value.takeIf { it > 0 }
+ // Refresh when emojiGridRows is reset
if (isLaidOut) {
showEmojiPickerView()
}
@@ -77,8 +79,8 @@
*/
var emojiGridColumns: Int = EmojiPickerConstants.DEFAULT_BODY_COLUMNS
set(value) {
- field = if (value > 0) value else EmojiPickerConstants.DEFAULT_BODY_COLUMNS
- // this step is to ensure the layout refresh when emojiGridColumns is reset
+ field = value.takeIf { it > 0 } ?: EmojiPickerConstants.DEFAULT_BODY_COLUMNS
+ // Refresh when emojiGridColumns is reset
if (isLaidOut) {
showEmojiPickerView()
}
@@ -88,6 +90,7 @@
private val scope = CoroutineScope(EmptyCoroutineContext)
private var recentEmojiProvider: RecentEmojiProvider = DefaultRecentEmojiProvider(context)
+ private var recentNeedsRefreshing: Boolean = true
private val recentItems: MutableList<EmojiViewData> = mutableListOf()
private lateinit var recentItemGroup: ItemGroup
@@ -99,10 +102,11 @@
init {
val typedArray: TypedArray =
context.obtainStyledAttributes(attrs, R.styleable.EmojiPickerView, 0, 0)
- emojiGridRows = typedArray.getFloat(
- R.styleable.EmojiPickerView_emojiGridRows,
- EmojiPickerConstants.DEFAULT_BODY_ROWS
- )
+ _emojiGridRows = with(R.styleable.EmojiPickerView_emojiGridRows) {
+ if (typedArray.hasValue(this)) {
+ typedArray.getFloat(this, 0F)
+ } else null
+ }
emojiGridColumns = typedArray.getInt(
R.styleable.EmojiPickerView_emojiGridColumns,
EmojiPickerConstants.DEFAULT_BODY_COLUMNS
@@ -145,15 +149,13 @@
return EmojiPickerBodyAdapter(
context,
emojiGridColumns,
- emojiGridRows,
+ _emojiGridRows,
stickyVariantProvider,
emojiPickerItemsProvider = { emojiPickerItems },
onEmojiPickedListener = { emojiViewItem ->
onEmojiPickedListener?.accept(emojiViewItem)
-
- scope.launch {
- recentEmojiProvider.recordSelection(emojiViewItem.emoji)
- }
+ recentEmojiProvider.recordSelection(emojiViewItem.emoji)
+ recentNeedsRefreshing = true
}
)
}
@@ -163,7 +165,7 @@
R.drawable.quantum_gm_ic_access_time_filled_vd_theme_24,
CategoryTitle(context.getString(R.string.emoji_category_recent)),
recentItems,
- forceContentSize = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns,
+ maxContentItemCount = DEFAULT_MAX_RECENT_ITEM_ROWS * emojiGridColumns,
emptyPlaceholderItem = PlaceholderText(
context.getString(R.string.emoji_empty_recent_category)
)
@@ -194,7 +196,6 @@
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when (emojiPickerItems.getBodyItem(position).itemType) {
- ItemType.PLACEHOLDER_EMOJI -> 0
ItemType.CATEGORY_TITLE, ItemType.PLACEHOLDER_TEXT -> emojiGridColumns
else -> 1
}
@@ -243,11 +244,14 @@
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
- val position =
- bodyLayoutManager.findFirstCompletelyVisibleItemPosition()
headerAdapter.selectedGroupIndex =
- emojiPickerItems.groupIndexByItemPosition(position)
- if (position !in emojiPickerItems.groupRange(recentItemGroup)) {
+ emojiPickerItems.groupIndexByItemPosition(
+ bodyLayoutManager.findFirstCompletelyVisibleItemPosition()
+ )
+ if (recentNeedsRefreshing &&
+ bodyLayoutManager.findFirstVisibleItemPosition() !in
+ emojiPickerItems.groupRange(recentItemGroup)
+ ) {
scope.launch {
refreshRecent()
}
@@ -268,18 +272,37 @@
}
internal suspend fun refreshRecent() {
+ if (!recentNeedsRefreshing) {
+ return
+ }
+ val oldGroupSize = if (::recentItemGroup.isInitialized) recentItemGroup.size else 0
val recent = recentEmojiProvider.getRecentEmojiList()
- recentItems.clear()
- recentItems.addAll(recent.map {
- EmojiViewData(
- it,
- updateToSticky = false,
- )
- })
- if (isLaidOut) {
- val range = emojiPickerItems.groupRange(recentItemGroup)
- withContext(Dispatchers.Main) {
- bodyAdapter.notifyItemRangeChanged(range.first, range.last + 1)
+ withContext(Dispatchers.Main) {
+ recentItems.clear()
+ recentItems.addAll(recent.map {
+ EmojiViewData(
+ it,
+ updateToSticky = false,
+ )
+ })
+ if (::emojiPickerItems.isInitialized) {
+ val range = emojiPickerItems.groupRange(recentItemGroup)
+ if (recentItemGroup.size > oldGroupSize) {
+ bodyAdapter.notifyItemRangeInserted(
+ range.first + oldGroupSize,
+ recentItemGroup.size - oldGroupSize
+ )
+ } else if (recentItemGroup.size < oldGroupSize) {
+ bodyAdapter.notifyItemRangeRemoved(
+ range.first + recentItemGroup.size,
+ oldGroupSize - recentItemGroup.size
+ )
+ }
+ bodyAdapter.notifyItemRangeChanged(
+ range.first,
+ minOf(oldGroupSize, recentItemGroup.size)
+ )
+ recentNeedsRefreshing = false
}
}
}
@@ -295,6 +318,7 @@
fun setRecentEmojiProvider(recentEmojiProvider: RecentEmojiProvider) {
this.recentEmojiProvider = recentEmojiProvider
scope.launch {
+ recentNeedsRefreshing = true
refreshRecent()
}
}
@@ -406,4 +430,4 @@
override fun removeViewsInLayout(start: Int, count: Int) {
throw UnsupportedOperationException(EmojiPickerConstants.REMOVE_VIEW_EXCEPTION_MESSAGE)
}
-}
+}
\ No newline at end of file
diff --git a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt
index d71b573..73a1549 100644
--- a/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt
+++ b/emoji2/emoji2-emojipicker/src/main/java/androidx/emoji2/emojipicker/ItemViewData.kt
@@ -20,7 +20,6 @@
CATEGORY_TITLE,
PLACEHOLDER_TEXT,
EMOJI,
- PLACEHOLDER_EMOJI,
}
/**
@@ -50,8 +49,6 @@
val dataIndex: Int = 0
) : ItemViewData(ItemType.EMOJI)
-internal object PlaceholderEmoji : ItemViewData(ItemType.PLACEHOLDER_EMOJI)
-
internal object Extensions {
internal fun Int.toItemType() = ItemType.values()[this]
}
diff --git a/fragment/fragment-lint/src/main/java/androidx/fragment/lint/FragmentIssueRegistry.kt b/fragment/fragment-lint/src/main/java/androidx/fragment/lint/FragmentIssueRegistry.kt
index f44dbf7..3032c3a 100644
--- a/fragment/fragment-lint/src/main/java/androidx/fragment/lint/FragmentIssueRegistry.kt
+++ b/fragment/fragment-lint/src/main/java/androidx/fragment/lint/FragmentIssueRegistry.kt
@@ -26,7 +26,7 @@
@Suppress("UnstableApiUsage")
class FragmentIssueRegistry : IssueRegistry() {
// tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
FragmentTagDetector.ISSUE,
diff --git a/fragment/fragment-testing-lint/src/main/java/androidx/fragment/testing/lint/FragmentTestingIssueRegistry.kt b/fragment/fragment-testing-lint/src/main/java/androidx/fragment/testing/lint/FragmentTestingIssueRegistry.kt
index 304b578..3ba8a76 100644
--- a/fragment/fragment-testing-lint/src/main/java/androidx/fragment/testing/lint/FragmentTestingIssueRegistry.kt
+++ b/fragment/fragment-testing-lint/src/main/java/androidx/fragment/testing/lint/FragmentTestingIssueRegistry.kt
@@ -22,7 +22,7 @@
@Suppress("UnstableApiUsage")
class FragmentTestingIssueRegistry : IssueRegistry() {
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(GradleConfigurationDetector.ISSUE)
override val vendor = Vendor(
diff --git a/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt
index 41a082b..7ce1350 100644
--- a/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt
+++ b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt
@@ -22,7 +22,7 @@
@Suppress("UnstableApiUsage")
class FragmentTestingManifestIssueRegistry : IssueRegistry() {
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(GradleConfigurationDetector.ISSUE)
override val vendor = Vendor(
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
index e941ddc..a57500f 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
@@ -31,6 +31,7 @@
import androidx.glance.action.clickable
import androidx.glance.appwidget.lazy.LazyColumn
import androidx.glance.appwidget.lazy.ReservedItemIdRangeEnd
+import androidx.glance.appwidget.lazy.items
import androidx.glance.layout.Alignment
import androidx.glance.layout.padding
import androidx.glance.text.Text
@@ -38,6 +39,13 @@
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertIs
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test
@@ -341,6 +349,41 @@
}
}
+ @OptIn(FlowPreview::class)
+ @Test
+ fun clickTriggersOnlyOneLambda() = runBlocking {
+ val received = MutableStateFlow(-1)
+ TestGlanceAppWidget.uiDefinition = {
+ LazyColumn {
+ items((0..4).toList()) {
+ Button(
+ "$it",
+ onClick = {
+ launch { received.emit(it) }
+ }
+ )
+ }
+ }
+ }
+
+ mHostRule.startHost()
+
+ val buttons = arrayOfNulls<FrameLayout>(5)
+ waitForListViewChildren { list ->
+ for (it in 0..4) {
+ val button = list.getUnboxedListItem<FrameLayout>(it)
+ buttons[it] = assertIs<FrameLayout>(button)
+ }
+ }
+ (0..4).shuffled().forEach { index ->
+ mHostRule.onHostActivity {
+ buttons[index]!!.performClick()
+ }
+ val lastClicked = received.debounce(500.milliseconds).first()
+ assertThat(lastClicked).isEqualTo(index)
+ }
+ }
+
private fun waitForListViewChildren(action: (list: ListView) -> Unit = {}) {
mHostRule.onHostView { }
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt
index a9286e32..5e4d046 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt
@@ -17,6 +17,7 @@
package androidx.glance.appwidget.lazy
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.key
import androidx.glance.Emittable
import androidx.glance.EmittableWithChildren
import androidx.glance.GlanceModifier
@@ -99,14 +100,18 @@
alignment: Alignment,
content: @Composable () -> Unit
) {
- GlanceNode(
- factory = ::EmittableLazyListItem,
- update = {
- this.set(itemId) { this.itemId = it }
- this.set(alignment) { this.alignment = it }
- },
- content = content
- )
+ // We wrap LazyListItem in the key composable to ensure that lambda actions declared within each
+ // item's scope will get a unique ID based on the currentCompositeKeyHash.
+ key(itemId) {
+ GlanceNode(
+ factory = ::EmittableLazyListItem,
+ update = {
+ this.set(itemId) { this.itemId = it }
+ this.set(alignment) { this.alignment = it }
+ },
+ content = content
+ )
+ }
}
/**
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
index 79ace6f..c0d1f50 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
@@ -23,6 +23,7 @@
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.wrapContentHeight
import androidx.annotation.RequiresApi
+import androidx.compose.runtime.key
import androidx.compose.ui.unit.Dp
import androidx.glance.Emittable
@@ -105,14 +106,18 @@
alignment: Alignment,
content: @Composable () -> Unit
) {
- GlanceNode(
- factory = ::EmittableLazyVerticalGridListItem,
- update = {
- this.set(itemId) { this.itemId = it }
- this.set(alignment) { this.alignment = it }
- },
- content = content
- )
+ // We wrap LazyVerticalGridItem in the key composable to ensure that lambda actions declared
+ // within each item's scope will get a unique ID based on the currentCompositeKeyHash.
+ key(itemId) {
+ GlanceNode(
+ factory = ::EmittableLazyVerticalGridListItem,
+ update = {
+ this.set(itemId) { this.itemId = it }
+ this.set(alignment) { this.alignment = it }
+ },
+ content = content
+ )
+ }
}
@JvmDefaultWithCompatibility
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 3a0ccb7..8407295 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
# -----------------------------------------------------------------------------
# All of the following should be updated in sync.
# -----------------------------------------------------------------------------
-androidGradlePlugin = "8.1.0-alpha03"
+androidGradlePlugin = "8.0.0-alpha07"
# NOTE: When updating the lint version we also need to update the `api` version
# supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.1.0-alpha03"
+androidLint = "31.0.0-alpha07"
# Once you have a chosen version of AGP to upgrade to, go to
# https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2022.3.1.3"
+androidStudio = "2022.2.1.7"
# -----------------------------------------------------------------------------
androidGradlePluginMin = "7.0.4"
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 22a9b26..49b6a25 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -29,20 +29,15 @@
<trust group="^com[.]android($|([.].*))" regex="true" reason="b/215430394"/>
</trusted-artifacts>
<trusted-keys>
- <trusted-key id="00089ee8c3afa95a854d0f1df800dd0933ecf7f7" group="com.google.guava" name="guava"/>
- <trusted-key id="012579464d01c06a" group="org.apache"/>
- <trusted-key id="019082bc00e0324e2aef4cf00d3b328562a119a7" group="org.openjdk.jmh"/>
- <trusted-key id="02216ed811210daa" group="io.github.detekt.sarif4k"/>
- <trusted-key id="0315bfb7970a144f">
- <trusting group="com.sun.istack"/>
- <trusting group="com.sun.xml.bind.mvn"/>
- <trusting group="com.sun.xml.fastinfoset"/>
- <trusting group="javax.xml.bind"/>
- <trusting group="org.glassfish.jaxb"/>
- <trusting group="org.jvnet.staxex"/>
+ <trusted-key id="00089ee8c3afa95a854d0f1df800dd0933ecf7f7">
+ <trusting group="com.google.guava"/>
+ <trusting group="com.google.guava" name="guava"/>
</trusted-key>
- <trusted-key id="0374cf2e8dd1bdfd" group="org.sonatype.oss"/>
- <trusted-key id="042b29e928995b9db963c636c7ca19b7b620d787" group="org.apache.maven" name="maven-ant-tasks"/>
+ <trusted-key id="019082bc00e0324e2aef4cf00d3b328562a119a7" group="org.openjdk.jmh"/>
+ <trusted-key id="042b29e928995b9db963c636c7ca19b7b620d787">
+ <trusting group="org.apache.maven"/>
+ <trusting group="org.apache.maven" name="maven-ant-tasks"/>
+ </trusted-key>
<trusted-key id="04543577d6a9cc626239c50c7ecbd740ff06aeb5">
<trusting group="com.sun.activation"/>
<trusting group="com.sun.istack"/>
@@ -51,22 +46,25 @@
<trusting group="org.jvnet.staxex"/>
<trusting group="^com[.]sun($|([.].*))" regex="true"/>
</trusted-key>
- <trusted-key id="04e9b2e1f06ecbbe0ed0aac562ba9c275d14234e" group="^com[.]squareup($|([.].*))" regex="true"/>
+ <trusted-key id="04e9b2e1f06ecbbe0ed0aac562ba9c275d14234e">
+ <trusting group="com.squareup.curtains"/>
+ <trusting group="com.squareup.leakcanary"/>
+ <trusting group="^com[.]squareup($|([.].*))" regex="true"/>
+ </trusted-key>
<trusted-key id="06a228aab83a18a8df7b84b08614d6ab265b4c63" group="org.apache.ant"/>
<trusted-key id="0785b3eff60b1b1bea94e0bb7c25280eae63ebe5" group="org.apache.httpcomponents"/>
<trusted-key id="08f0aab4d0c1a4bdde340765b341ddb020fcb6ab" group="org.bouncycastle"/>
- <trusted-key id="09a79e1e15a04694" group="org.vafer"/>
<trusted-key id="0cc641c3a62453ab390066c4a41f13c999945293" group="commons-logging"/>
+ <trusted-key id="0cde80149711eb46dff17ae421a24b3f8b0f594a" group="org.apache"/>
<trusted-key id="0d35d3f60078655126908e8af3d1600878e85a3d" group="io.netty"/>
<trusted-key id="0d5d634755737a19abbe2930d4da5eab3cd7e958" group="com.google.devtools.ksp"/>
- <trusted-key id="0d8f8561aa7a5dd20bae27043c0a8f4744f37328" group="com.github.ben-manes.caffeine" name="caffeine"/>
- <trusted-key id="0e91c2de43b72bb1" group="org.ec4j.core"/>
+ <trusted-key id="0d8f8561aa7a5dd20bae27043c0a8f4744f37328">
+ <trusting group="com.github.ben-manes.caffeine"/>
+ <trusting group="com.github.ben-manes.caffeine" name="caffeine"/>
+ </trusted-key>
<trusted-key id="0eb9d7c468f97e44051d650ad73c68ee4152c255" group="com.google.dagger"/>
<trusted-key id="0f07d1201bddab67cfb84eb479752db6c966f0b8" group="com.google.android"/>
- <trusted-key id="10066a9707090cf9" group="org.javassist"/>
- <trusted-key id="10ae8966a146e8be" group="com.google.crypto.tink"/>
<trusted-key id="10f3c7a02eca55e502badcf3991efb94db91127d" group="org.ow2"/>
- <trusted-key id="1188b69f6d6259ca" group="com.google.accompanist"/>
<trusted-key id="11b581967f079a30a3e93140d57506cd188fd842" group="com.google.api.grpc"/>
<trusted-key id="120d6f34e627ed3a772ebbfe55c7e5e701832382">
<trusting group="org.snakeyaml"/>
@@ -75,17 +73,27 @@
<trusted-key id="12d16069219c90212a974d119ae296fd02e9f65b" group="org.apache.commons" name="commons-math3"/>
<trusted-key id="13ac2213964abe1d1c147c0e1939a2520bab1d90" group="org.freemarker" name="freemarker"/>
<trusted-key id="147b691a19097624902f4ea9689cbe64f4bc997f" group="^org[.]mockito($|([.].*))" regex="true"/>
- <trusted-key id="151ba00a46886a5f95441a0f5d67bffcba1f9a39" group="com.google.gradle" name="osdetector-gradle-plugin"/>
+ <trusted-key id="151ba00a46886a5f95441a0f5d67bffcba1f9a39" group="com.google.gradle"/>
<trusted-key id="1597ab231b7add7e14b1d9c43f00db67ae236e2e" group="org.conscrypt"/>
- <trusted-key id="160a7a9cf46221a56b06ad64461a804f2609fd89" group="com.github.shyiko.klob" name="klob"/>
- <trusted-key id="1861c322c56014b2" group="commons-lang"/>
+ <trusted-key id="160a7a9cf46221a56b06ad64461a804f2609fd89">
+ <trusting group="com.github.shyiko.klob"/>
+ <trusting group="com.github.shyiko.klob" name="klob"/>
+ </trusted-key>
<trusted-key id="187366a3ffe6bf8f94b9136a9987b20c8f6a3064" group="com.google.protobuf"/>
- <trusted-key id="190d5a957ff22273e601f7a7c92c5fec70161c62" group="org.codehaus.mojo"/>
+ <trusted-key id="190d5a957ff22273e601f7a7c92c5fec70161c62">
+ <trusting group="org.apache"/>
+ <trusting group="org.codehaus.mojo"/>
+ </trusted-key>
<trusted-key id="19beab2d799c020f17c69126b16698a4adf4d638" group="org.checkerframework"/>
- <trusted-key id="1b2718089ce964b8" group="com.thoughtworks.qdox"/>
- <trusted-key id="1bc86444bbd2a24c3a40904a438e9634a2319637" group="co.nstant.in" name="cbor"/>
+ <trusted-key id="1bc86444bbd2a24c3a40904a438e9634a2319637">
+ <trusting group="co.nstant.in"/>
+ <trusting group="co.nstant.in" name="cbor"/>
+ </trusted-key>
<trusted-key id="1cb7a3dbc99b562d69bfdfedae7af7ae095eb290" group="net.saff.checkmark"/>
- <trusted-key id="1d0a8b5e77c678a7c724445abf984b4145ea13f7" group="com.squareup"/>
+ <trusted-key id="1d0a8b5e77c678a7c724445abf984b4145ea13f7">
+ <trusting group="com.squareup"/>
+ <trusting group="com.squareup" name="javapoet"/>
+ </trusted-key>
<trusted-key id="1d9aa7f9e1e2824728b8cd1794b291aef984a085">
<trusting group="io.reactivex"/>
<trusting group="io.reactivex.rxjava2"/>
@@ -93,48 +101,50 @@
</trusted-key>
<trusted-key id="1dbb44e80f61493d6369b5fb95c15058a5eda4f1">
<trusting group="com.google.gradle"/>
+ <trusting group="com.google.protobuf"/>
<trusting group="com.google.protobuf" name="protobuf-gradle-plugin"/>
</trusted-key>
- <trusted-key id="1f47744c9b6e14f2049c2857f1f111af65925306" group="io.github.classgraph" name="classgraph"/>
- <trusted-key id="1f8cf885d537a431" group="com.nhaarman.mockitokotlin2"/>
+ <trusted-key id="1f47744c9b6e14f2049c2857f1f111af65925306">
+ <trusting group="io.github.classgraph"/>
+ <trusting group="io.github.classgraph" name="classgraph"/>
+ </trusted-key>
<trusted-key id="1fa37fbe4453c1073e7ef61d6449005f96bc97a3" group="de.undercouch"/>
- <trusted-key id="205c8673dc742c7c" group="org.apache"/>
<trusted-key id="20723a6399bc060154283b37cfae163b64ac9189" group="org.jetbrains.skiko"/>
- <trusted-key id="21200d723f53ce38" group="com.squareup.leakcanary"/>
- <trusted-key id="218fa0f6a941a037" group="com.github.kevinstern"/>
- <trusted-key id="21939ff0ca2a6567" group="commons-codec"/>
- <trusted-key id="21a24b3f8b0f594a" group="org.apache"/>
- <trusted-key id="22b79f456b06f4e75b8b579db57bd58ef6d0a713" group="com.google.protobuf" name="protoc"/>
- <trusted-key id="22e44ac0622b91c3" group="com.beust"/>
- <trusted-key id="2383163bc40844fd" group="org.reactivestreams"/>
+ <trusted-key id="22b79f456b06f4e75b8b579db57bd58ef6d0a713">
+ <trusting group="com.google.protobuf"/>
+ <trusting group="com.google.protobuf" name="protoc"/>
+ </trusted-key>
<trusted-key id="24d04176586361fda94ee0315f7786df73e61f56" group="com.google.devtools.ksp"/>
<trusted-key id="26063b04869f7d235ccc057447586a1b75ef0de5" group="com.squareup.wire"/>
<trusted-key id="263923711ef4fe3f3f0c28af11509ed50ec155e6" group="org.reactivestreams"/>
- <trusted-key id="2a4f55d9cda5877731fbe7466eff5ef5523052d4" group="com.github.tschuchortdev" name="kotlin-compile-testing"/>
- <trusted-key id="2bab4466b44f54f8f99bbbdd5ed22f661bbf0acc" group="com.almworks.sqlite4java" name="sqlite4java"/>
+ <trusted-key id="2a4f55d9cda5877731fbe7466eff5ef5523052d4">
+ <trusting group="com.github.tschuchortdev"/>
+ <trusting group="com.github.tschuchortdev" name="kotlin-compile-testing"/>
+ </trusted-key>
+ <trusted-key id="2bab4466b44f54f8f99bbbdd5ed22f661bbf0acc">
+ <trusting group="com.almworks.sqlite4java"/>
+ <trusting group="com.almworks.sqlite4java" name="sqlite4java"/>
+ </trusted-key>
<trusted-key id="2bcbdd0f23ea1cafcc11d4860374cf2e8dd1bdfd">
<trusting group="net.java"/>
<trusting group="org.codehaus"/>
+ <trusting group="org.sonatype.oss"/>
</trusted-key>
- <trusted-key id="2be5d98f751f4136" group="org.pcollections"/>
<trusted-key id="2db4f1ef0fa761ecc4ea935c86fdc7e2a11262cb">
<trusting group="commons-codec"/>
<trusting group="commons-io"/>
<trusting group="org.apache.commons"/>
<trusting group="xml-apis"/>
</trusted-key>
- <trusted-key id="2e2010f8a7ff4a41" group="org.apache"/>
<trusted-key id="2e3a1affe42b5f53af19f780bcf4173966770193" group="org.jetbrains"/>
<trusted-key id="2e92113263fc31c74ccbaab20e91c2de43b72bb1" group="org.ec4j.core"/>
- <trusted-key id="2f566d4221d3ec52" group="com.ryanharter.auto.value"/>
<trusted-key id="3051d45031e13516a6e8faff280d66a55f5316c5" group="org.bitbucket.b_c"/>
- <trusted-key id="30e6f80434a72a7f">
- <trusting group="org.apache.maven"/>
- <trusting group="org.apache.maven.wagon"/>
- </trusted-key>
<trusted-key id="314fe82e5a4c5377bca2edec5208812e1e4a6db0" group="com.gradle"/>
<trusted-key id="31bae2e51d95e0f8ad9b7bcc40a3c4432bd7308c" group="com.googlecode.juniversalchardet"/>
- <trusted-key id="31fae244a81d64507b47182e1b2718089ce964b8" group="com.thoughtworks.qdox" name="qdox"/>
+ <trusted-key id="31fae244a81d64507b47182e1b2718089ce964b8">
+ <trusting group="com.thoughtworks.qdox"/>
+ <trusting group="com.thoughtworks.qdox" name="qdox"/>
+ </trusted-key>
<trusted-key id="3288b8be8512d6c0ca185268c51e6cbc7ff46f0b">
<trusting group="com.google.auto"/>
<trusting group="com.google.auto.service"/>
@@ -142,27 +152,16 @@
<trusted-key id="32b92f2ff75fdf37dc811c3c2f566d4221d3ec52" group="com.ryanharter.auto.value"/>
<trusted-key id="33fd4bfd33554634053d73c0c2148900bcd3c2af" group="org.jetbrains.trove4j" name="trove4j"/>
<trusted-key id="34441e504a937f43eb0daef96a65176a0fb1cd0b" group="org.codehaus.groovy"/>
- <trusted-key id="353a436e043e3145" group="com.google.code.findbugs"/>
<trusted-key id="3872ed7d5904493d23d78fa2c4c8cb73b1435348" group="com.android.tools.build"/>
- <trusted-key id="3ad93c3c677a106e" group="io.perfmark"/>
- <trusted-key id="3c0a8f4744f37328" group="com.github.ben-manes.caffeine"/>
- <trusted-key id="3c27d97b0c83a85c" group="com.google.errorprone"/>
<trusted-key id="3d11126ea77e4e07fbabb38614a84c976d265b25" group="com.google.protobuf"/>
<trusted-key id="3dbc5d7dc2fb8dd68aa429bd353a436e043e3145" group="com.google.code.findbugs"/>
<trusted-key id="3eb3846b3dc004c13883753ceef9ecc7d5d90518" group="com.google.dagger"/>
- <trusted-key id="3f36885c24df4b75" group="org.mozilla"/>
- <trusted-key id="3faad2cd5ecbb314" group="org.apache.commons"/>
- <trusted-key id="41321490758aad6f" group="org.codehaus.groovy"/>
<trusted-key id="41a1a08c62fca78b79d3081164a16faaec16a4be" group="org.apache.commons" name="commons-math3"/>
<trusted-key id="41cd49b4ef5876f9e9f691dabac30622339994c4">
<trusting group="com.google.testing.compile"/>
<trusting group="com.google.truth"/>
</trusted-key>
- <trusted-key id="42575e0ccd6ba16a" group="org.xerial"/>
- <trusted-key id="429c8816dea04cdb" group="org.xerial"/>
- <trusted-key id="438e9634a2319637" group="co.nstant.in"/>
- <trusted-key id="44ce7bf2825ea2cd" group="com.ibm.icu"/>
- <trusted-key id="461a804f2609fd89" group="com.github.shyiko.klob"/>
+ <trusted-key id="44fbdbbc1a00fe414f1c1873586654072ead6677" group="org.sonatype.oss"/>
<trusted-key id="47504b76cf89c15c0512d9afe16ab52d79fd224f">
<trusting group="com.google.api"/>
<trusting group="com.google.api-client"/>
@@ -173,24 +172,18 @@
<trusting group="com.google.http-client"/>
<trusting group="com.google.oauth-client"/>
</trusted-key>
- <trusted-key id="47586a1b75ef0de5" group="com.squareup.wire"/>
<trusted-key id="475f3b8e59e6e63aa78067482c7b12f2a511e325">
<trusting group="ch.qos.logback"/>
<trusting group="org.slf4j"/>
</trusted-key>
- <trusted-key id="476634a4694e716a" group="com.googlecode.java-diff-utils"/>
<trusted-key id="4791825bdea86eb9286a2ace88bb19a33a18445f" group="net.ltgt.gradle.incap"/>
<trusted-key id="47bf592261cd1a8a69b703b4e0cb7823cfd00fbf">
+ <trusting group="com.jakewharton.android.repackaged"/>
<trusting group="com.jakewharton.dex"/>
<trusting group="com.squareup.retrofit2"/>
<trusting group="^com[.]jakewharton($|([.].*))" regex="true"/>
</trusted-key>
- <trusted-key id="47dcfc2a59f59b5b" group="io.outfoxx"/>
<trusted-key id="47eb6836245d2d40e89dfb4136d4e9618f3adab5" group="io.github.microutils" name="kotlin-logging-jvm"/>
- <trusted-key id="4896f7312a5ace4d">
- <trusting group="com.google.gradle"/>
- <trusting group="com.google.protobuf"/>
- </trusted-key>
<trusted-key id="4bf79b8259007b566d2fce82296cd27f60eed12c" group="com.google.crypto.tink"/>
<trusted-key id="4daded739cdf2cd0e48e0ec44044edf1bb73efea" group="jaxen" name="jaxen"/>
<trusted-key id="4db1a49729b053caf015cee9a6adfc93ef34893e" group="org.hamcrest"/>
@@ -203,20 +196,20 @@
<trusted-key id="4f8fec6785f611d9a712ea2734918b7d3969d2f5" group="com.google.dagger"/>
<trusted-key id="517b94f8d0a46317a28d8ab30da8a5ec02d11ead" group="net.sf.jopt-simple"/>
<trusted-key id="51b52dc5dd452f92be342cc2858fc4c4f43856a3" group="xerces"/>
- <trusted-key id="5208812e1e4a6db0" group="com.gradle"/>
- <trusted-key id="55c7e5e701832382" group="org.snakeyaml"/>
- <trusted-key id="56b505dc8a29c69138a430b9429c8816dea04cdb" group="org.xerial" name="sqlite-jdbc"/>
+ <trusted-key id="55e770230e69cc6de143fb5b62c82e50836eb3ee" group="com.github.gundy"/>
+ <trusted-key id="56b505dc8a29c69138a430b9429c8816dea04cdb">
+ <trusting group="org.xerial"/>
+ <trusting group="org.xerial" name="sqlite-jdbc"/>
+ </trusted-key>
<trusted-key id="5719e50eac5a4b1dd390b72c2a742740e08e7f8d" group="org.antlr"/>
- <trusted-key id="571a5291e827e1c7" group="net.java"/>
<trusted-key id="5767f9cde920750621875079a40e24b5b408dbd5" group="org.robolectric"/>
- <trusted-key id="586654072ead6677" group="org.sonatype.oss"/>
<trusted-key id="5897253bea3046aeea95a067e93671c7272b7b3f" group="org.jdom"/>
+ <trusted-key id="58e79b6abc762159dc0b1591164bd2247b936711" group="junit"/>
<trusted-key id="5ce325996a35213326ae2c68912d2c0eccda55c0" group="com.google.errorprone"/>
- <trusted-key id="5d67bffcba1f9a39" group="com.google.gradle"/>
- <trusted-key id="5dceb296690bd5101756f2441f8cf885d537a431" group="com.nhaarman.mockitokotlin2" name="mockito-kotlin"/>
- <trusted-key id="5e1f79a7c298661e" group="com.google.auto.value"/>
- <trusted-key id="5ed22f661bbf0acc" group="com.almworks.sqlite4java"/>
- <trusted-key id="5f7786df73e61f56" group="com.google.devtools.ksp"/>
+ <trusted-key id="5dceb296690bd5101756f2441f8cf885d537a431">
+ <trusting group="com.nhaarman.mockitokotlin2"/>
+ <trusting group="com.nhaarman.mockitokotlin2" name="mockito-kotlin"/>
+ </trusted-key>
<trusted-key id="5fa41c402006eac55d72aafd99ce9d9f22dc5c99" group="org.json"/>
<trusted-key id="600ea202b1ec682f4a788e5aac7a514bc9f9bb70" group="io.opencensus"/>
<trusted-key id="6214760097dc5cfad0175ac2c9fbaa83a8753994">
@@ -228,15 +221,16 @@
<trusting group="com.fasterxml.woodstox"/>
<trusting group="org.codehaus.woodstox"/>
</trusted-key>
- <trusted-key id="628462a5eaba59d57e99ae5a840b2bf6da8ed8c8" group="com.google.android.apps.common.testing.accessibility.framework" name="accessibility-test-framework"/>
- <trusted-key id="62ba9c275d14234e">
- <trusting group="com.squareup.curtains"/>
- <trusting group="com.squareup.leakcanary"/>
+ <trusted-key id="628462a5eaba59d57e99ae5a840b2bf6da8ed8c8">
+ <trusting group="com.google.android.apps.common.testing.accessibility.framework"/>
+ <trusting group="com.google.android.apps.common.testing.accessibility.framework" name="accessibility-test-framework"/>
</trusted-key>
- <trusted-key id="62c82e50836eb3ee" group="com.github.gundy"/>
<trusted-key id="635ee627345f3c1dd422b2e207d3516820bcf6b1" group="com.github.ben-manes.caffeine"/>
- <trusted-key id="6525fd70cc303655" group="org.codehaus.mojo"/>
- <trusted-key id="666a4692ce11b7b3f4eb7b3410066a9707090cf9" group="org.javassist" name="javassist"/>
+ <trusted-key id="64b9b09f164aa0bf88742eb61188b69f6d6259ca" group="com.google.accompanist"/>
+ <trusted-key id="666a4692ce11b7b3f4eb7b3410066a9707090cf9">
+ <trusting group="org.javassist"/>
+ <trusting group="org.javassist" name="javassist"/>
+ </trusted-key>
<trusted-key id="682f765eea718d250bbdb2f1685c46769dbb5e5d" group="com.squareup" name="kotlinpoet"/>
<trusted-key id="694621a7227d8d5289699830abe9f3126bb741c1">
<trusting group="com.google.guava"/>
@@ -244,13 +238,11 @@
<trusting group="^com[.]google($|([.].*))" regex="true"/>
</trusted-key>
<trusted-key id="696b6199a2a9d8c29ce78cc0d041cad2e452550f" group="com.google.protobuf"/>
- <trusted-key id="6a65176a0fb1cd0b" group="org.codehaus.groovy"/>
- <trusted-key id="6ccc36cc6c69fc17" group="com.google"/>
+ <trusted-key id="6bdaca2c0493cca133b372d09c4f7e9d98b1cc53" group="org.apache"/>
<trusted-key id="6dd3b8c64ef75253beb2c53ad908a43fb7ec07ac">
<trusting group="com.sun.activation"/>
<trusting group="jakarta.activation"/>
</trusted-key>
- <trusted-key id="6eff5ef5523052d4" group="com.github.tschuchortdev"/>
<trusted-key id="6f538074ccebf35f28af9b066a0975f8b1127b83">
<trusting group="org.jetbrains.kotlin"/>
<trusting group="org.jetbrains.kotlin.jvm"/>
@@ -259,41 +251,52 @@
<trusted-key id="6f656b7f6bfb238d38acf81f3c27d97b0c83a85c" group="com.google.errorprone"/>
<trusted-key id="6f7e5acbcd02db60dfd232e45e1f79a7c298661e">
<trusting group="com.google.auto"/>
+ <trusting group="com.google.auto.value"/>
<trusting group="com.google.auto.value" name="auto-value"/>
</trusted-key>
<trusted-key id="70731c2ffb496dc4e8105aa3604f437c1682dde5" group="app.cash.paparazzi"/>
<trusted-key id="70cd19bfd9f6c330027d6f260315bfb7970a144f">
+ <trusting group="com.sun.istack"/>
<trusting group="com.sun.xml.bind"/>
+ <trusting group="com.sun.xml.bind.mvn"/>
+ <trusting group="com.sun.xml.fastinfoset"/>
<trusting group="javax.xml.bind"/>
<trusting group="org.glassfish"/>
<trusting group="org.glassfish.jaxb"/>
<trusting group="org.jvnet.staxex"/>
<trusting group="^com[.]sun($|([.].*))" regex="true"/>
</trusted-key>
- <trusted-key id="72385ff0af338d52" group="org.threeten"/>
+ <trusted-key id="720746177725a89207a7075bfd5dea07fcb690a8" group="org.codehaus.mojo"/>
+ <trusted-key id="748f15b2cf9ba8f024155e6ed7c92b70fa1c814d" group="org.apache.logging.log4j"/>
<trusted-key id="7615ad56144df2376f49d98b1669c4bb543e0445" group="com.google.errorprone"/>
<trusted-key id="7616eb882daf57a11477aaf559a252fb1199d873" group="com.google.code.findbugs"/>
<trusted-key id="78ab011fa6e5907950ea3e2747dcfc2a59f59b5b" group="io.outfoxx"/>
- <trusted-key id="79156e0351af8604de9b186b09a79e1e15a04694" group="org.vafer" name="jdependency"/>
- <trusted-key id="7999befba1039e8b" group="net.bytebuddy"/>
- <trusted-key id="7a8860944fad5f62" group="org.apache.commons"/>
+ <trusted-key id="79156e0351af8604de9b186b09a79e1e15a04694">
+ <trusting group="org.vafer"/>
+ <trusting group="org.vafer" name="jdependency"/>
+ </trusted-key>
<trusted-key id="7c669810892cbd3148fa92995b05ccde140c2876" group="org.eclipse.jgit"/>
- <trusted-key id="7c7d8456294423ba" group="org.objenesis"/>
<trusted-key id="7cb548acfe3d47e92afa566dc29b11246382a4d7" group="com.charleskorn.kaml"/>
- <trusted-key id="7cd52b5a8295137c88fb5748dddafa7674e54418" group="org.testng" name="testng"/>
+ <trusted-key id="7cd52b5a8295137c88fb5748dddafa7674e54418">
+ <trusting group="org.testng"/>
+ <trusting group="org.testng" name="testng"/>
+ </trusted-key>
<trusted-key id="7e22d50a7ebd9d2cd269b2d4056aca74d46000bf" group="io.netty"/>
<trusted-key id="7f36e793ae3252e5d9e9b98fee9e7dc9d92fc896" group="com.google.errorprone"/>
<trusted-key id="7faa0f2206de228f0db01ad741321490758aad6f" group="org.codehaus.groovy"/>
- <trusted-key id="80f6d6b0d90c6747753344cab5a9e81b565e89e0" group="org.tomlj" name="tomlj"/>
+ <trusted-key id="808d78b17a5a2d7c3668e31fbffc9b54721244ad" group="org.apache.commons"/>
+ <trusted-key id="80f6d6b0d90c6747753344cab5a9e81b565e89e0">
+ <trusting group="org.tomlj"/>
+ <trusting group="org.tomlj" name="tomlj"/>
+ </trusted-key>
<trusted-key id="8254180bfc943b816e0b5e2e5e2f2b3d474efe6b" group="it.unimi.dsi"/>
- <trusted-key id="82b5574242c20d6f" group="org.antlr"/>
<trusted-key id="82f833963889d7ed06f1e4dc6525fd70cc303655" group="org.codehaus.mojo"/>
<trusted-key id="835a685c8c6f49c54980e5caf406f31bc1468eba" group="org.jcodec"/>
- <trusted-key id="840b2bf6da8ed8c8" group="com.google.android.apps.common.testing.accessibility.framework"/>
<trusted-key id="842afb86375d805422835bfd82b5574242c20d6f" group="org.antlr"/>
- <trusted-key id="8569c95cadc508b09fe90f3002216ed811210daa" group="io.github.detekt.sarif4k" name="sarif4k"/>
- <trusted-key id="85911f425ec61b51" group="org.junit"/>
- <trusted-key id="8614d6ab265b4c63" group="org.apache.ant"/>
+ <trusted-key id="8569c95cadc508b09fe90f3002216ed811210daa">
+ <trusting group="io.github.detekt.sarif4k"/>
+ <trusting group="io.github.detekt.sarif4k" name="sarif4k"/>
+ </trusted-key>
<trusted-key id="8756c4f765c9ac3cb6b85d62379ce192d401ab61">
<trusting group="com.github.ajalt"/>
<trusting group="com.github.javaparser"/>
@@ -302,7 +305,7 @@
<trusting group="^org[.]jetbrains($|([.].*))" regex="true"/>
</trusted-key>
<trusted-key id="8858d45be9b276802318155b96fb9db219f3338d" group="kr.motd.maven"/>
- <trusted-key id="88bb19a33a18445f" group="net.ltgt.gradle.incap"/>
+ <trusted-key id="88cd390855df292e2172da9742575e0ccd6ba16a " group="org.xerial"/>
<trusted-key id="8a10792983023d5d14c93b488d7f1bec1e2ecae7">
<trusting group="com.fasterxml"/>
<trusting group="com.fasterxml.jackson"/>
@@ -312,116 +315,133 @@
<trusted-key id="8df3b0aa23ed78be5233f6c2dea3d207428ef16d" group="com.linkedin.dexmaker"/>
<trusted-key id="8e3a02905a1ae67e7b0f9acd3967d4eda591b991" group="org.jetbrains.kotlinx" name="kotlinx-html-jvm"/>
<trusted-key id="8f9a3c6d105b9f57844a721d79e193516be7998f" group="org.dom4j" name="dom4j"/>
- <trusted-key id="908366594e746bf3c449f5622be5d98f751f4136" group="org.pcollections" name="pcollections"/>
+ <trusted-key id="908366594e746bf3c449f5622be5d98f751f4136">
+ <trusting group="org.pcollections"/>
+ <trusting group="org.pcollections" name="pcollections"/>
+ </trusted-key>
<trusted-key id="90ee19787a7bcf6fd37a1e9180c08b1c29100955">
<trusting group="com.jakewharton.android.repackaged"/>
<trusting group="com.squareup" name="javawriter"/>
</trusted-key>
<trusted-key id="95115197c5227c0887299d000f9fe62f88e938d8" group="com.google.dagger"/>
- <trusted-key id="95c15058a5eda4f1" group="com.google.protobuf"/>
- <trusted-key id="96fb9db219f3338d" group="kr.motd.maven"/>
- <trusted-key id="971b04f56669b805" group="com.google.jsilver"/>
<trusted-key id="98465301a4939c0279f2e847d89d05374952262b" group="org.jetbrains.dokka"/>
- <trusted-key id="995efbf4a3d20beb">
- <trusting group="com.pinterest"/>
- <trusting group="com.pinterest.ktlint"/>
+ <trusted-key id="998af0e2b935996f5cebd56b9b1fda9f3c062231">
+ <trusting group="org.apache"/>
+ <trusting group="org.apache.maven"/>
</trusted-key>
- <trusted-key id="998af0e2b935996f5cebd56b9b1fda9f3c062231" group="org.apache.maven"/>
- <trusted-key id="9a259c7ee636c5ed" group="com.google.errorprone"/>
- <trusted-key id="9b1fda9f3c062231" group="org.apache"/>
<trusted-key id="9bbc1c3e408ca09cf76d1a029c538d5a79281639" group="com.squareup.sqldelight"/>
- <trusted-key id="9c4f7e9d98b1cc53" group="org.apache"/>
- <trusted-key id="9c538d5a79281639" group="com.squareup.sqldelight"/>
<trusted-key id="9d0a56aaa0d60e0c0c7dccc0b4c70893b62babe8">
<trusting group="org.apache.logging"/>
<trusting group="org.apache.logging.log4j"/>
</trusted-key>
- <trusted-key id="9daadc1c9fcc82d0" group="commons-cli"/>
<trusted-key id="9e84765a7aa3e3d3d5598a408e3f0de7ae354651">
<trusting group="com.google.code.gson"/>
<trusting group="com.squareup"/>
<trusting group="org.reactivestreams"/>
</trusted-key>
- <trusted-key id="9ffed7a118d45a44e4a1e47130e6f80434a72a7f" group="^org[.]apache[.]maven($|([.].*))" regex="true"/>
+ <trusted-key id="9ffed7a118d45a44e4a1e47130e6f80434a72a7f">
+ <trusting group="org.apache.maven"/>
+ <trusting group="org.apache.maven.wagon"/>
+ <trusting group="^org[.]apache[.]maven($|([.].*))" regex="true"/>
+ </trusted-key>
<trusted-key id="a0e7010544c02bd4c072b1803e3d777c909a447c" group="io.opencensus"/>
- <trusted-key id="a1b4460d8ba7b9af" group="org.mockito"/>
<trusted-key id="a33a0b49a4c1ab590b0a4ddc1364c5e2df3e99c5" group="org.reactivestreams"/>
- <trusted-key id="a40e24b5b408dbd5" group="org.robolectric"/>
<trusted-key id="a413f67d71beec23add0ce0acb43338e060cf9fa">
<trusting group="com.google.code.findbugs" name="jsr305"/>
<trusting group="org.jacoco"/>
</trusted-key>
- <trusted-key id="a4fd709cc4b0515f2e6af04e218fa0f6a941a037" group="com.github.kevinstern" name="software-and-algorithms"/>
- <trusted-key id="a5b2dde7843e7ca3e8caabd02383163bc40844fd" group="org.reactivestreams" name="reactive-streams"/>
+ <trusted-key id="a4fd709cc4b0515f2e6af04e218fa0f6a941a037">
+ <trusting group="com.github.kevinstern"/>
+ <trusting group="com.github.kevinstern" name="software-and-algorithms"/>
+ </trusted-key>
+ <trusted-key id="a5b2dde7843e7ca3e8caabd02383163bc40844fd">
+ <trusting group="org.reactivestreams"/>
+ <trusting group="org.reactivestreams" name="reactive-streams"/>
+ </trusted-key>
<trusted-key id="a5bd02b93e7a40482eb1d66a5f69ad087600b22c" group="org.ow2.asm"/>
- <trusted-key id="a6adfc93ef34893e" group="org.hamcrest"/>
<trusted-key id="a6d6c97108b8585f91b158748671a8df71296252" group="^com[.]squareup($|([.].*))" regex="true"/>
- <trusted-key id="a730529ca355a63e" group="org.ccil.cowan.tagsoup"/>
- <trusted-key id="a7764f502a938c99" group="com.google.protobuf"/>
<trusted-key id="a7892505cf1a58076453e52d7999befba1039e8b" group="net.bytebuddy"/>
<trusted-key id="aa417737bd805456db3cbdde6601e5c08dccbb96" group="info.picocli" name="picocli"/>
<trusted-key id="aa70c7c433d501636392ec02153e7a3c2b4e5118" group="org.eclipse.ee4j"/>
- <trusted-key id="ac5ec74981f9cda6">
- <trusting group="com.beust"/>
- <trusting group="org.testng"/>
+ <trusted-key id="adbc987d1a7b91db6b0aaa81995efbf4a3d20beb">
+ <trusting group="com.pinterest"/>
+ <trusting group="com.pinterest.ktlint"/>
+ <trusting group="^com[.]pinterest($|([.].*))" regex="true"/>
</trusted-key>
- <trusted-key id="adbc987d1a7b91db6b0aaa81995efbf4a3d20beb" group="^com[.]pinterest($|([.].*))" regex="true"/>
- <trusted-key id="ae2b18e836c5f30687f37efdcc6346f2ce3872d9" group="com.google.protobuf" name="protobuf-java"/>
+ <trusted-key id="ae2b18e836c5f30687f37efdcc6346f2ce3872d9">
+ <trusting group="com.google.protobuf"/>
+ <trusting group="com.google.protobuf" name="protobuf-java"/>
+ </trusted-key>
+ <trusted-key id="ae9e53fc28ff2ab1012273d0bf1518e0160788a2" group="org.apache" name="apache"/>
<trusted-key id="afa2b1823fc021bfd08c211fd5f4c07a434ab3da" group="com.squareup"/>
<trusted-key id="afcc4c7594d09e2182c60e0f7a01b0f236e5430f" group="com.google.code.gson"/>
<trusted-key id="b02335aa54ccf21e52bbf9abd9c565aa72ba2fdd" group="io.grpc"/>
- <trusted-key id="b252e5789636134a311e4463971b04f56669b805" group="com.google.jsilver" name="jsilver"/>
+ <trusted-key id="b252e5789636134a311e4463971b04f56669b805">
+ <trusting group="com.google.jsilver"/>
+ <trusting group="com.google.jsilver" name="jsilver"/>
+ </trusted-key>
<trusted-key id="b41089a2da79b0fa5810252872385ff0af338d52">
+ <trusting group="org.threeten"/>
<trusting group="org.threeten" name="threeten-extra"/>
<trusting group="org.threeten" name="threetenbp"/>
</trusted-key>
- <trusted-key id="b47034c19c9b1f3dc3702f8d476634a4694e716a" group="com.googlecode.java-diff-utils" name="diffutils"/>
- <trusted-key id="b4c70893b62babe8" group="org.apache.logging.log4j"/>
- <trusted-key id="b57bd58ef6d0a713" group="com.google.protobuf"/>
- <trusted-key id="b5a9e81b565e89e0" group="org.tomlj"/>
- <trusted-key id="b6e73d84ea4fcc47166087253faad2cd5ecbb314" group="org.apache.commons" name="commons-parent"/>
- <trusted-key id="b7c3b43d18eaa8b7" group="org.codehaus.mojo"/>
+ <trusted-key id="b46dc71e03feeb7f89d1f2491f7a8f87b9d8f501" group="org.jetbrains.trove4j"/>
+ <trusted-key id="b47034c19c9b1f3dc3702f8d476634a4694e716a">
+ <trusting group="com.googlecode.java-diff-utils"/>
+ <trusting group="com.googlecode.java-diff-utils" name="diffutils"/>
+ </trusted-key>
+ <trusted-key id="b4ac8cdc141af0ae468d16921da784ccb5c46dd5" group="net.bytebuddy"/>
+ <trusted-key id="b6e73d84ea4fcc47166087253faad2cd5ecbb314">
+ <trusting group="org.apache.commons"/>
+ <trusting group="org.apache.commons" name="commons-parent"/>
+ </trusted-key>
<trusted-key id="b801e2f8ef035068ec1139cc29579f18fa8fd93b" group="com.google.j2objc"/>
- <trusted-key id="bac30622339994c4" group="com.google.truth"/>
+ <trusted-key id="b9cca13c59f21c6ce841a8d1a4b1a03fb9c2ce23" group="com.squareup.leakcanary"/>
+ <trusted-key id="ba926f64ca647b6d853a38672e2010f8a7ff4a41" group="org.apache"/>
<trusted-key id="bae5c184e3b70cb15617700598fe03a974ce0a0b" group="org.jetbrains.kotlin"/>
- <trusted-key id="bb2914c1fa0811c3" group="net.bytebuddy"/>
- <trusted-key id="bc87a3fd0a54480f0badbebd21939ff0ca2a6567" group="commons-codec" name="commons-codec"/>
+ <trusted-key id="bc87a3fd0a54480f0badbebd21939ff0ca2a6567">
+ <trusting group="commons-codec"/>
+ <trusting group="commons-codec" name="commons-codec"/>
+ </trusted-key>
<trusted-key id="bcc135fc7ed8214f823d73e97fe9900f412d622e" group="com.google.flatbuffers"/>
<trusted-key id="bdb5fa4fe719d787fb3d3197f6d4a1d411e9d1ae" group="com.google.guava"/>
- <trusted-key id="be096e29edb8d141" group="net.sf.proguard"/>
<trusted-key id="be685132afd2740d9095f9040cc0b712fee75827" group="org.assertj"/>
- <trusted-key id="beabcfbee059e4e5" group="com.github.siom79.japicmp"/>
- <trusted-key id="bede11eaf1164480" group="org.hamcrest"/>
- <trusted-key id="bf1518e0160788a2" group="org.apache" name="apache"/>
- <trusted-key id="bf984b4145ea13f7" group="com.squareup" name="javapoet"/>
- <trusted-key id="bffc9b54721244ad" group="org.apache.commons"/>
- <trusted-key id="c1b12a5d99c0729d" group="org.jetbrains"/>
- <trusted-key id="c2148900bcd3c2af" group="org.jetbrains.trove4j"/>
- <trusted-key id="c29b11246382a4d7" group="com.charleskorn.kaml"/>
- <trusted-key id="c51e6cbc7ff46f0b" group="com.google.auto.service"/>
<trusted-key id="c5aa57f4a38eba7b7f9156ddab2da4527f6ffc0b">
<trusting group="com.squareup" name="kotlinpoet"/>
<trusting group="com.squareup" name="kotlinpoet-javapoet"/>
</trusted-key>
- <trusted-key id="c6f7d1c804c821f49af3bfc13ad93c3c677a106e" group="io.perfmark" name="perfmark-api"/>
- <trusted-key id="c70b844f002f21f6d2b9c87522e44ac0622b91c3" group="com.beust" name="jcommander"/>
+ <trusted-key id="c6f7d1c804c821f49af3bfc13ad93c3c677a106e">
+ <trusting group="io.perfmark"/>
+ <trusting group="io.perfmark" name="perfmark-api"/>
+ </trusted-key>
+ <trusted-key id="c70b844f002f21f6d2b9c87522e44ac0622b91c3">
+ <trusting group="com.beust"/>
+ <trusting group="com.beust" name="jcommander"/>
+ </trusted-key>
<trusted-key id="c7be5bcc9fec15518cfda882b0f3710fa64900e7">
<trusting group="com.google.auto"/>
<trusting group="com.google.auto.service"/>
<trusting group="com.google.auto.value"/>
<trusting group="com.google.code.gson"/>
</trusted-key>
- <trusted-key id="c7ca19b7b620d787" group="org.apache.maven"/>
- <trusted-key id="c8741082ff1b0ee96bcabeec10ae8966a146e8be" group="com.google.crypto.tink" name="tink-android"/>
- <trusted-key id="c888b9955815ea83b48531784896f7312a5ace4d" group="^com[.]google($|([.].*))" regex="true"/>
- <trusted-key id="c92c5fec70161c62" group="org.apache"/>
+ <trusted-key id="c8741082ff1b0ee96bcabeec10ae8966a146e8be">
+ <trusting group="com.google.crypto.tink"/>
+ <trusting group="com.google.crypto.tink" name="tink-android"/>
+ </trusted-key>
+ <trusted-key id="c888b9955815ea83b48531784896f7312a5ace4d">
+ <trusting group="com.google.gradle"/>
+ <trusting group="com.google.protobuf"/>
+ <trusting group="^com[.]google($|([.].*))" regex="true"/>
+ </trusted-key>
<trusted-key id="c9a503282182ec4ecdb914ea102e05d8da6c286d" group="javax.xml.bind" name="jaxb-api"/>
<trusted-key id="cacfbd4755a2fc78709bdd92be096e29edb8d141" group="net.sf.proguard"/>
- <trusted-key id="cb3190ca7842439e57f3712e44ce7bf2825ea2cd" group="com.ibm.icu" name="icu4j"/>
- <trusted-key id="cb43338e060cf9fa" group="org.jacoco"/>
+ <trusted-key id="cb3190ca7842439e57f3712e44ce7bf2825ea2cd">
+ <trusting group="com.ibm.icu"/>
+ <trusting group="com.ibm.icu" name="icu4j"/>
+ </trusted-key>
<trusted-key id="cc4483cd6a3eb2939b948667a1b4460d8ba7b9af" group="org.mockito"/>
- <trusted-key id="cc6346f2ce3872d9" group="com.google.protobuf"/>
<trusted-key id="cd5464315f0b98c77e6e8ecd9daadc1c9fcc82d0">
+ <trusting group="commons-cli"/>
<trusting group="commons-cli" name="commons-cli"/>
<trusting group="org.apache.commons"/>
</trusted-key>
@@ -429,31 +449,38 @@
<trusting group="org.apache.ant"/>
<trusting group="org.apache.commons"/>
</trusted-key>
- <trusted-key id="cf9f3090ce4cb752" group="org.abego.treelayout"/>
- <trusted-key id="cfae163b64ac9189" group="org.jetbrains.skiko"/>
- <trusted-key id="d041cad2e452550f" group="com.google.protobuf"/>
<trusted-key id="d196a5e3e70732eeb2e5007f1861c322c56014b2" group="commons-lang"/>
+ <trusted-key id="d433f9c895710db8ab087fa6b7c3b43d18eaa8b7" group="org.codehaus.mojo"/>
<trusted-key id="d477d51812e692011db11e66a6ea2e2bf22e0543" group="io.github.java-diff-utils"/>
<trusted-key id="d4c89ea4aaf455fd88b22087efe8086f9e93774e" group="junit"/>
- <trusted-key id="d4da5eab3cd7e958" group="com.google.devtools.ksp"/>
- <trusted-key id="d4fb0b7b5e8c18c993a8a386eb9d04a9a679fe18" group="com.uber.nullaway" name="nullaway"/>
+ <trusted-key id="d4fb0b7b5e8c18c993a8a386eb9d04a9a679fe18">
+ <trusting group="com.uber.nullaway"/>
+ <trusting group="com.uber.nullaway" name="nullaway"/>
+ </trusted-key>
<trusted-key id="d54a395b5cf3f86eb45f6e426b1b008864323b92" group="org.antlr"/>
- <trusted-key id="d5f4c07a434ab3da" group="com.squareup"/>
- <trusted-key id="d6f1bc78607808ec8e9f69437a8860944fad5f62" group="org.apache.commons" name="commons-parent"/>
- <trusted-key id="d73c68ee4152c255" group="com.google.dagger"/>
+ <trusted-key id="d6f1bc78607808ec8e9f69437a8860944fad5f62">
+ <trusting group="org.apache.commons"/>
+ <trusting group="org.apache.commons" name="commons-parent"/>
+ </trusted-key>
<trusted-key id="d75e25b78ebb19e47c0a99bca7764f502a938c99" group="com.google.protobuf"/>
- <trusted-key id="d790f72ea8fd39551012b62dcf9f3090ce4cb752" group="org.abego.treelayout" name="org.abego.treelayout.core"/>
- <trusted-key id="da7a1bb85b19e4fb05073431205c8673dc742c7c" group="org.apache.maven"/>
+ <trusted-key id="d790f72ea8fd39551012b62dcf9f3090ce4cb752">
+ <trusting group="org.abego.treelayout"/>
+ <trusting group="org.abego.treelayout" name="org.abego.treelayout.core"/>
+ </trusted-key>
+ <trusted-key id="da7a1bb85b19e4fb05073431205c8673dc742c7c">
+ <trusting group="org.apache"/>
+ <trusting group="org.apache.maven"/>
+ </trusted-key>
<trusted-key id="db0597e3144342256bc81e3ec727d053c4481cf5" group="org.tensorflow"/>
<trusted-key id="dbd744ace7ade6aa50dd591f66b50994442d2d40">
<trusting group="com.squareup.okio"/>
<trusting group="com.squareup.wire"/>
</trusted-key>
- <trusted-key id="dddafa7674e54418" group="org.testng"/>
- <trusted-key id="e0130a3ed5a2079e" group="org.webjars"/>
- <trusted-key id="e0cb7823cfd00fbf" group="com.jakewharton.android.repackaged"/>
+ <trusted-key id="dcba03381ef6c89096acd985ac5ec74981f9cda6">
+ <trusting group="com.beust"/>
+ <trusting group="org.testng"/>
+ </trusted-key>
<trusted-key id="e0d98c5fd55a8af232290e58dee12b9896f97e34" group="org.pcollections"/>
- <trusted-key id="e16ab52d79fd224f" group="com.google.api.grpc"/>
<trusted-key id="e3a9f95079e84ce201f7cf60bede11eaf1164480" group="org.hamcrest"/>
<trusted-key id="e62231331bca7e1f292c9b88c1b12a5d99c0729d" group="org.jetbrains"/>
<trusted-key id="e77417ac194160a3fabd04969a259c7ee636c5ed">
@@ -461,20 +488,24 @@
<trusting group="com.google.googlejavaformat"/>
</trusted-key>
<trusted-key id="e7dc75fc24fb3c8dfe8086ad3d5839a2262cbbfb" group="org.jetbrains.kotlinx"/>
+ <trusted-key id="e82d2eaf2e83830ce1f7f6be571a5291e827e1c7" group="net.java"/>
<trusted-key id="e85aed155021af8a6c6b7a4a7c7d8456294423ba" group="org.objenesis"/>
<trusted-key id="e8bf633b386b7ddcf1e1a9b3358a4abae72947c2" group="com.google.testparameterinjector"/>
- <trusted-key id="ea0b70b5050192c98cfa7e4f3f36885c24df4b75" group="org.mozilla" name="rhino"/>
- <trusted-key id="ea23db1360d9029481e7f2efecdfea3cb4493b94" group="jline" name="jline"/>
- <trusted-key id="eaa526b91dd83ba3e1b9636fa730529ca355a63e" group="org.ccil.cowan.tagsoup" name="tagsoup"/>
- <trusted-key id="eb380dc13c39f675" group="com.intellij"/>
- <trusted-key id="eb9d04a9a679fe18" group="com.uber.nullaway"/>
- <trusted-key id="ecdfea3cb4493b94" group="jline"/>
+ <trusted-key id="ea0b70b5050192c98cfa7e4f3f36885c24df4b75">
+ <trusting group="org.mozilla"/>
+ <trusting group="org.mozilla" name="rhino"/>
+ </trusted-key>
+ <trusted-key id="ea23db1360d9029481e7f2efecdfea3cb4493b94">
+ <trusting group="jline"/>
+ <trusting group="jline" name="jline"/>
+ </trusted-key>
+ <trusted-key id="eaa526b91dd83ba3e1b9636fa730529ca355a63e">
+ <trusting group="org.ccil.cowan.tagsoup"/>
+ <trusting group="org.ccil.cowan.tagsoup" name="tagsoup"/>
+ </trusted-key>
+ <trusted-key id="ec86f41279f2ec8ffd2f54906ccc36cc6c69fc17" group="com.google"/>
<trusted-key id="ee0ca873074092f806f59b65d364abaa39a47320" group="com.google.errorprone"/>
- <trusted-key id="ee9e7dc9d92fc896" group="com.google.errorprone"/>
- <trusted-key id="eef9ecc7d5d90518" group="com.google.dagger"/>
- <trusted-key id="efe8086f9e93774e" group="junit"/>
<trusted-key id="f1a51e051f527e0c8e24d54d4b1e11d5a4b91e89" group="com.google.protobuf"/>
- <trusted-key id="f1f111af65925306" group="io.github.classgraph"/>
<trusted-key id="f254b35617dc255d9344bcfa873a8e86b4372146">
<trusting group="org.apache"/>
<trusting group="org.codehaus.mojo"/>
@@ -482,19 +513,25 @@
</trusted-key>
<trusted-key id="f3184bcd55f4d016e30d4c9bf42e87f9665015c9" group="org.jsoup"/>
<trusted-key id="f42b96b8648b5c4a1c43a62fbb2914c1fa0811c3" group="net.bytebuddy"/>
- <trusted-key id="f800dd0933ecf7f7" group="com.google.guava"/>
- <trusted-key id="fa1703b1d287caea3a60f931e0130a3ed5a2079e" group="org.webjars" name="jquery"/>
+ <trusted-key id="fa1703b1d287caea3a60f931e0130a3ed5a2079e">
+ <trusting group="org.webjars"/>
+ <trusting group="org.webjars" name="jquery"/>
+ </trusted-key>
<trusted-key id="fa77dcfef2ee6eb2debedd2c012579464d01c06a">
+ <trusting group="org.apache"/>
<trusting group="org.apache" name="apache"/>
<trusting group="org.codehaus.plexus"/>
</trusted-key>
<trusted-key id="fa7929f83ad44c4590f6cc6815c71c0a4e0b8edd" group="net.java.dev.jna"/>
- <trusted-key id="faabc3738b1f58da2d776fa2eb380dc13c39f675" group="com.intellij" name="annotations"/>
+ <trusted-key id="faabc3738b1f58da2d776fa2eb380dc13c39f675">
+ <trusting group="com.intellij"/>
+ <trusting group="com.intellij" name="annotations"/>
+ </trusted-key>
<trusted-key id="fc411cd3cb7dcb0abc9801058118b3bcdb1a5000" group="jakarta.xml.bind"/>
- <trusted-key id="fd5dea07fcb690a8" group="org.codehaus.mojo"/>
<trusted-key id="ff460acf3266fdce8eb8fe3ba797295e9d87bdd0" group="androidx.build.gradle.gcpbuildcache" name="gcpbuildcache"/>
<trusted-key id="ff6e2c001948c5f2f38b0cc385911f425ec61b51">
<trusting group="junit"/>
+ <trusting group="org.junit"/>
<trusting group="org.junit" name="junit-bom"/>
<trusting group="org.junit.jupiter"/>
<trusting group="org.junit.platform"/>
@@ -549,6 +586,14 @@
<sha256 value="bc787098a208e6bdc8d93720a162bbea01df1b26394d1c1ef5ec523b1d604e8b" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
+ <component group="com.google.android.libraries.identity.googleid" name="googleid" version="0.0.2">
+ <artifact name="googleid-0.0.2.aar">
+ <sha256 value="ae69047587928df1ff82ce71e9f2ec40a777270f04f4a6d1f66241944961b682" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="googleid-0.0.2.pom">
+ <sha256 value="100a2c6db1ec4aab9545ead93be094c9728ecc671fba8353648d04ef405f30c8" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="com.google.android.odml" name="image" version="1.0.0-beta1">
<artifact name="image-1.0.0-beta1.aar">
<sha256 value="2e71aa31f83a9415277f119de67195726f07d1760e9542c111778c320e3aa1f2" origin="Generated by Gradle" reason="Artifact is not signed"/>
@@ -777,94 +822,6 @@
<pgp value="720746177725a89207a7075bfd5dea07fcb690a8"/>
</artifact>
</component>
- <component group="org.jetbrains.dokka" name="all-modules-page-plugin" version="1.7.20-dev-178">
- <artifact name="all-modules-page-plugin-1.7.20-dev-178.jar">
- <sha256 value="968267f870e4c3a21b23fd61249a380df5b32d6eb4b295df93b9b25f0020e49f" origin="Generated manually"/>
- </artifact>
- <artifact name="all-modules-page-plugin-1.7.20-dev-178.module">
- <sha256 value="c4692062327e1e4cea88e5c4ce10e9420525fe746c7b73aeb672738f7109389c" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="android-documentation-plugin" version="1.7.20-dev-178">
- <artifact name="android-documentation-plugin-1.7.20-dev-178.jar">
- <sha256 value="d446f3e440984e927712e8fd894a0fcb004a1d5626a66f2e3eebf85497f7f4c9" origin="Generated manually"/>
- </artifact>
- <artifact name="android-documentation-plugin-1.7.20-dev-178.module">
- <sha256 value="38745965f41d21794376b62b2c285f0feeb612e6a1eef8b32ce42bbba2330d48" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-analysis" version="1.7.20-dev-178">
- <artifact name="dokka-analysis-1.7.20-dev-178.jar">
- <sha256 value="18e8e9dbf885e80de803c00744a820095511915f8eb13c6973478f37b8937f95" origin="Generated manually"/>
- </artifact>
- <artifact name="dokka-analysis-1.7.20-dev-178.module">
- <sha256 value="c2238793675e470beff29a013f1ff97df3a89a53afadca94b022ff55d3d66dd7" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-android-gradle-plugin" version="0.9.17-g014">
- <artifact name="dokka-android-gradle-plugin-0.9.17-g014.jar">
- <sha256 value="64b2e96fd20762351c74f08d598d49c25a490a3b685b8a09446e81d6db36fe81" origin="Generated by Gradle"/>
- </artifact>
- <artifact name="dokka-android-gradle-plugin-0.9.17-g014.pom">
- <sha256 value="956ff381c6c775161a82823bb52d0aa40a8f6a37ab85059f149531f5e5efb7da" origin="Generated by Gradle"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-base" version="1.7.20-dev-178">
- <artifact name="dokka-base-1.7.20-dev-178.jar">
- <sha256 value="043de520b665454fa144a0018875a9303454f16c3cda45c63f3d354f86fdfe66" origin="Generated manually"/>
- </artifact>
- <artifact name="dokka-base-1.7.20-dev-178.module">
- <sha256 value="ddee298e92ee3e8b60c55967bc2b66d8871725db2758d8f44bec3069a7165986" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-cli" version="1.7.20-dev-178">
- <artifact name="dokka-cli-1.7.20-dev-178.jar">
- <sha256 value="4ed2e6846156cd619b00ba942c1bb46489a9cd88118fa7a9236d9ceb2b036930" origin="Generated manually"/>
- </artifact>
- <artifact name="dokka-cli-1.7.20-dev-178.pom">
- <sha256 value="68d9a1bbaa5bca1fea9034450be55cc25ad3f7017f9d017c9b4b65db2f47064a" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-fatjar" version="0.9.17-g014">
- <artifact name="dokka-fatjar-0.9.17-g014.jar">
- <sha256 value="47cf09501402a101e555588cf5fa9ed83f8572bce9fd60db29e74b5d079628e3" origin="Generated by Gradle"/>
- </artifact>
- <artifact name="dokka-fatjar-0.9.17-g014.pom">
- <sha256 value="ceb601f55f14337261fea474bb061407dc0e52146f80d74cd0b43d66febd401f" origin="Generated by Gradle"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="dokka-gradle-plugin" version="0.9.17-g014">
- <artifact name="dokka-gradle-plugin-0.9.17-g014.jar">
- <sha256 value="643a7eddeb521832c6021508b7477b603517438481bc06633dca12eb1f339422" origin="Generated by Gradle"/>
- </artifact>
- <artifact name="dokka-gradle-plugin-0.9.17-g014.pom">
- <sha256 value="b217e9a1f1503c9f0c744b736fc2afed6fa6c3c2e86e5276a3c549f5bd48baef" origin="Generated by Gradle"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="kotlin-analysis-compiler" version="1.7.20-dev-178">
- <artifact name="kotlin-analysis-compiler-1.7.20-dev-178.jar">
- <sha256 value="051c0ed61798fb30ca74eabe20b0c97e510db34080dd4ca40bae7c6465625f8d" origin="Generated manually"/>
- </artifact>
- <artifact name="kotlin-analysis-compiler-1.7.20-dev-178.pom">
- <sha256 value="9dded49204804e237fc0b237b1f073b87a4bde9901eca6482fc3b6dddf44bf4c" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="kotlin-analysis-intellij" version="1.7.20-dev-178">
- <artifact name="kotlin-analysis-intellij-1.7.20-dev-178.jar">
- <sha256 value="85976e1cdd4152d93e6c20be62e0b725c357119955c0a1cc0026a1ba60610acd" origin="Generated manually"/>
- </artifact>
- <artifact name="kotlin-analysis-intellij-1.7.20-dev-178.pom">
- <sha256 value="7bb00911c8f9610c56748277169ea6d95f2d32afca4e9edcfcb4efe23c43cca4" origin="Generated manually"/>
- </artifact>
- </component>
- <component group="org.jetbrains.dokka" name="templating-plugin" version="1.7.20-dev-178">
- <artifact name="templating-plugin-1.7.20-dev-178.jar">
- <sha256 value="41347b118770f3dc48a14c18f728395c40ce6f769018709a0d018bade1a64237" origin="Generated manually"/>
- </artifact>
- <artifact name="templating-plugin-1.7.20-dev-178.module">
- <sha256 value="86b38d52c54ffdd52344326e751c5f8020dd7783bc1c8324435932c470b46d1f" origin="Generated manually"/>
- </artifact>
- </component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.3.71">
<artifact name="kotlin-reflect-1.3.71.pom">
<sha256 value="4df94aaeee8d900be431386e31ef44e82a66e57c3ae30866aec2875aff01fe70" origin="Generated by Gradle"/>
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
index f47e622..38050ea 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
@@ -42,58 +42,72 @@
@RequiresApi(Build.VERSION_CODES.O)
@Test
fun testSyncStrategy_Always() {
- val egl = createAndSetupEGLManager(EGLSpec.V14)
- if (egl.supportsNativeAndroidFence()) {
- val strategy = SyncStrategy.ALWAYS
- val fence = strategy.createSyncFence(egl.eglSpec)
- assertTrue(fence != null)
- fence?.close()
+ withEgl { egl ->
+ if (egl.supportsNativeAndroidFence()) {
+ val strategy = SyncStrategy.ALWAYS
+ val fence = strategy.createSyncFence(egl.eglSpec)
+ assertTrue(fence != null)
+ fence?.close()
+ }
}
}
@Test
fun testSyncStrategy_onFirstShow_FrontBufferUsageOff_Invisible() {
- val egl = createAndSetupEGLManager(EGLSpec.V14)
- if (egl.supportsNativeAndroidFence()) {
- val strategy = FrontBufferSyncStrategy(0L)
- val fence = strategy.createSyncFence(EGLSpec.V14)
- assertTrue(fence != null)
- fence?.close()
+ withEgl { egl ->
+ if (egl.supportsNativeAndroidFence()) {
+ val strategy = FrontBufferSyncStrategy(0L)
+ val fence = strategy.createSyncFence(EGLSpec.V14)
+ assertTrue(fence != null)
+ fence?.close()
+ }
}
}
@Test
fun testSyncStrategy_onFirstShow_FrontBufferUsageOff_Visible() {
- val egl = createAndSetupEGLManager(EGLSpec.V14)
- if (egl.supportsNativeAndroidFence()) {
- val strategy = FrontBufferSyncStrategy(0L)
- strategy.isVisible = true
- val fence = strategy.createSyncFence(EGLSpec.V14)
- assertTrue(fence == null)
- fence?.close()
+ withEgl { egl ->
+ if (egl.supportsNativeAndroidFence()) {
+ val strategy = FrontBufferSyncStrategy(0L)
+ strategy.isVisible = true
+ val fence = strategy.createSyncFence(EGLSpec.V14)
+ assertTrue(fence == null)
+ fence?.close()
+ }
}
}
@Test
fun testSyncStrategy_onFirstShow_FrontBufferUsageOn_Invisible() {
- val egl = createAndSetupEGLManager(EGLSpec.V14)
- if (egl.supportsNativeAndroidFence()) {
- val strategy = FrontBufferSyncStrategy(mUsageFlags)
- val fence = strategy.createSyncFence(egl.eglSpec)
- assertTrue(fence != null)
- fence?.close()
+ withEgl { egl ->
+ if (egl.supportsNativeAndroidFence()) {
+ val strategy = FrontBufferSyncStrategy(mUsageFlags)
+ val fence = strategy.createSyncFence(egl.eglSpec)
+ assertTrue(fence != null)
+ fence?.close()
+ }
}
}
@Test
fun testSyncStrategy_onFirstShow_FrontBufferUsageOn_Visible() {
+ withEgl { egl ->
+ if (egl.supportsNativeAndroidFence()) {
+ val strategy = FrontBufferSyncStrategy(mUsageFlags)
+ strategy.isVisible = true
+ val fence = strategy.createSyncFence(EGLSpec.V14)
+ assertTrue(fence == null)
+ fence?.close()
+ }
+ }
+ }
+
+ private fun withEgl(block: (egl: EGLManager) -> Unit) {
val egl = createAndSetupEGLManager(EGLSpec.V14)
- if (egl.supportsNativeAndroidFence()) {
- val strategy = FrontBufferSyncStrategy(mUsageFlags)
- strategy.isVisible = true
- val fence = strategy.createSyncFence(EGLSpec.V14)
- assertTrue(fence == null)
- fence?.close()
+ try {
+ block(egl)
+ } finally {
+ releaseEGLManager(egl)
}
}
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
index f7e5a2b..d2a9139 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
@@ -58,7 +58,6 @@
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@@ -221,7 +220,6 @@
}
}
- @Ignore // b/266736718
@Test
fun testCreatePBufferSurface() {
testEGLManager {
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/HealthConnectClient.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/HealthConnectClient.kt
index ac90937..8676442 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/HealthConnectClient.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/HealthConnectClient.kt
@@ -58,13 +58,23 @@
* [androidx.health.connect.client.records.metadata.Metadata.id] generated. Insertion of
* multiple [records] is executed in a transaction - if one fails, none is inserted.
*
+ * @param records List of records to insert
+ * @return List of unique identifiers in the order of inserted records.
+ * @throws RemoteException For any IPC transportation failures.
+ * @throws SecurityException For requests with unpermitted access.
+ * @throws IOException For any disk I/O issues.
+ * @throws IllegalStateException If service is not available.
+ *
* For example, to insert basic data like step counts:
+ *
* @sample androidx.health.connect.client.samples.InsertSteps
*
* To insert more complex data like nutrition for a user who’s eaten a banana:
+ *
* @sample androidx.health.connect.client.samples.InsertNutrition
*
* To insert some heart rate data:
+ *
* @sample androidx.health.connect.client.samples.InsertHeartRateSeries
*
* [androidx.health.connect.client.records.metadata.Metadata.clientRecordId] can be used to
@@ -74,13 +84,6 @@
* with the higher
* [androidx.health.connect.client.records.metadata.Metadata.clientRecordVersion] takes
* precedence.
- *
- * @param records List of records to insert
- * @return List of unique identifiers in the order of inserted records.
- * @throws RemoteException For any IPC transportation failures.
- * @throws SecurityException For requests with unpermitted access.
- * @throws IOException For any disk I/O issues.
- * @throws IllegalStateException If service is not available.
*/
suspend fun insertRecords(records: List<Record>): InsertRecordsResponse
@@ -90,7 +93,7 @@
*
* @param records List of records to update
* @throws RemoteException For any IPC transportation failures. Update with invalid identifiers
- * will result in IPC failure.
+ * will result in IPC failure.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
@@ -101,19 +104,20 @@
* Deletes one or more [Record] by their identifiers. Deletion of multiple [Record] is executed
* in single transaction - if one fails, none is deleted.
*
- * Example usage to delete written steps data by its unique identifier:
- * @sample androidx.health.connect.client.samples.DeleteByUniqueIdentifier
- *
* @param recordType Which type of [Record] to delete, such as `Steps::class`
* @param recordIdsList List of [androidx.health.connect.client.records.metadata.Metadata.id] of
- * [Record] to delete
+ * [Record] to delete
* @param clientRecordIdsList List of client record IDs of [Record] to delete
* @throws RemoteException For any IPC transportation failures. Deleting by invalid identifiers
- * such as a non-existing identifier or deleting the same record multiple times will result in
- * IPC failure.
+ * such as a non-existing identifier or deleting the same record multiple times will result in
+ * IPC failure.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example usage to delete written steps data by its unique identifier:
+ *
+ * @sample androidx.health.connect.client.samples.DeleteByUniqueIdentifier
*/
suspend fun deleteRecords(
recordType: KClass<out Record>,
@@ -126,15 +130,16 @@
* filtered to [Record] belonging to the calling application). Deletion of multiple [Record] is
* executed in a transaction - if one fails, none is deleted.
*
- * Example usage to delete written steps data in a time range:
- * @sample androidx.health.connect.client.samples.DeleteByTimeRange
- *
* @param recordType Which type of [Record] to delete, such as `Steps::class`
* @param timeRangeFilter The [TimeRangeFilter] to delete from
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example usage to delete written steps data in a time range:
+ *
+ * @sample androidx.health.connect.client.samples.DeleteByTimeRange
*/
suspend fun deleteRecords(recordType: KClass<out Record>, timeRangeFilter: TimeRangeFilter)
@@ -143,10 +148,10 @@
*
* @param recordType Which type of [Record] to read, such as `Steps::class`
* @param recordId [androidx.health.connect.client.records.metadata.Metadata.id] of [Record] to
- * read
+ * read
* @return The [Record] data point.
* @throws RemoteException For any IPC transportation failures. Update with invalid identifiers
- * will result in IPC failure.
+ * will result in IPC failure.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
@@ -159,17 +164,17 @@
/**
* Retrieves a collection of [Record]s.
*
- * Example code to read basic data like step counts:
- * @sample androidx.health.connect.client.samples.ReadStepsRange
- *
* @param T the type of [Record]
* @param request [ReadRecordsRequest] object specifying time range and other filters
- *
* @return a response containing a collection of [Record]s.
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example code to read basic data like step counts:
+ *
+ * @sample androidx.health.connect.client.samples.ReadStepsRange
*/
suspend fun <T : Record> readRecords(request: ReadRecordsRequest<T>): ReadRecordsResponse<T>
@@ -177,20 +182,21 @@
* Reads [AggregateMetric]s according to requested read criteria: [Record]s from
* [AggregateRequest.dataOriginFilter] and within [AggregateRequest.timeRangeFilter].
*
- * Example code to aggregate cumulative data like distance:
- * @sample androidx.health.connect.client.samples.AggregateDistance
- *
- * Example code to retrieve statistical aggregates like maximum or minimum heart rate:
- * @sample androidx.health.connect.client.samples.AggregateHeartRate
- *
* @param request [AggregateRequest] object specifying [AggregateMetric]s to aggregate and other
- * filters.
- *
+ * filters.
* @return the [AggregationResult] that contains aggregated values.
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example code to aggregate cumulative data like distance:
+ *
+ * @sample androidx.health.connect.client.samples.AggregateDistance
+ *
+ * Example code to retrieve statistical aggregates like maximum or minimum heart rate:
+ *
+ * @sample androidx.health.connect.client.samples.AggregateHeartRate
*/
suspend fun aggregate(request: AggregateRequest): AggregationResult
@@ -205,18 +211,18 @@
* An [AggregationResultGroupedByDuration] is returned only if there are [Record] to aggregate
* within start and end time of the row.
*
- * Example code to retrieve cumulative step count for each minute within provided time range:
- * @sample androidx.health.connect.client.samples.AggregateIntoMinutes
- *
* @param request [AggregateGroupByDurationRequest] object specifying [AggregateMetric]s to
- * aggregate and other filters.
- *
+ * aggregate and other filters.
* @return a list of [AggregationResultGroupedByDuration]s, each contains aggregated values and
- * start/end time of the row. The list is sorted by time in ascending order.
+ * start/end time of the row. The list is sorted by time in ascending order.
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example code to retrieve cumulative step count for each minute within provided time range:
+ *
+ * @sample androidx.health.connect.client.samples.AggregateIntoMinutes
*/
suspend fun aggregateGroupByDuration(
request: AggregateGroupByDurationRequest,
@@ -233,18 +239,18 @@
* An [AggregationResultGroupedByPeriod] is returned only if there are [Record] to aggregate
* within start and end time of the row.
*
- * Example code to retrieve cumulative step count for each month within provided time range:
- * @sample androidx.health.connect.client.samples.AggregateIntoMonths
- *
* @param request [AggregateGroupByPeriodRequest] object specifying [AggregateMetric]s to
- * aggregate and other filters.
- *
+ * aggregate and other filters.
* @return a list of [AggregationResultGroupedByPeriod]s, each contains aggregated values and
- * start/end time of the row. The list is sorted by time in ascending order.
+ * start/end time of the row. The list is sorted by time in ascending order.
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
+ *
+ * Example code to retrieve cumulative step count for each month within provided time range:
+ *
+ * @sample androidx.health.connect.client.samples.AggregateIntoMonths
*/
suspend fun aggregateGroupByPeriod(
request: AggregateGroupByPeriodRequest,
@@ -263,11 +269,9 @@
*
* @param request Includes interested types of record to observe changes and optional filters.
* @return a changes-token
- *
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IllegalStateException If service is not available.
- *
* @see getChanges
*/
suspend fun getChangesToken(request: ChangesTokenRequest): String
@@ -292,12 +296,10 @@
*
* @param notificationIntentAction an action to be used for broadcast messages.
* @param recordTypes specifies [Record] types of interest.
- *
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
- *
* @see unregisterFromDataNotifications
* @see androidx.health.connect.client.datanotification.DataNotification
*/
@@ -311,13 +313,11 @@
* Unregisters the provided [notificationIntentAction] from data notifications.
*
* @param notificationIntentAction an action previously registered using
- * [registerForDataNotifications] method.
- *
+ * [registerForDataNotifications] method.
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IOException For any disk I/O issues.
* @throws IllegalStateException If service is not available.
- *
* @see registerForDataNotifications
*/
@RestrictTo(RestrictTo.Scope.LIBRARY) // Not yet ready for public
@@ -345,13 +345,11 @@
* ```
*
* @param changesToken A Changes-Token that represents a specific point in time in Android
- * Health Platform.
+ * Health Platform.
* @return a [ChangesResponse] with changes since provided [changesToken].
- *
* @throws RemoteException For any IPC transportation failures.
* @throws SecurityException For requests with unpermitted access.
* @throws IllegalStateException If service is not available.
- *
* @see getChangesToken
*/
suspend fun getChanges(changesToken: String): ChangesResponse
@@ -368,8 +366,8 @@
* if they want to re-direct the user to Health Connect.
*/
@get:JvmName("getHealthConnectSettingsAction")
- @JvmStatic val ACTION_HEALTH_CONNECT_SETTINGS =
- "androidx.health.ACTION_HEALTH_CONNECT_SETTINGS"
+ @JvmStatic
+ val ACTION_HEALTH_CONNECT_SETTINGS = "androidx.health.ACTION_HEALTH_CONNECT_SETTINGS"
/**
* The Health Connect SDK is not unavailable on this device at the time. This can be due to
@@ -397,11 +395,11 @@
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef(
value =
- [
- SDK_UNAVAILABLE,
- SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED,
- SDK_AVAILABLE,
- ]
+ [
+ SDK_UNAVAILABLE,
+ SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED,
+ SDK_AVAILABLE,
+ ]
)
annotation class AvailabilityStatus
@@ -410,8 +408,8 @@
*
* @param context the context
* @param providerPackageName optional package provider to choose for backend implementation
- * @return One of [SDK_UNAVAILABLE], [SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED]
- * or [SDK_AVAILABLE]
+ * @return One of [SDK_UNAVAILABLE], [SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED] or
+ * [SDK_AVAILABLE]
* @sample androidx.health.connect.client.samples.AvailabilityCheckSamples
*/
@JvmOverloads
@@ -474,11 +472,10 @@
*
* @param context the context
* @param providerPackageName optional alternative package provider to choose for backend
- * implementation
+ * implementation
* @return instance of [HealthConnectClient] ready for issuing requests
* @throws UnsupportedOperationException if service not available due to SDK version too low
* @throws IllegalStateException if service not available due to not installed
- *
* @see isProviderAvailable
*/
@JvmOverloads
@@ -517,7 +514,7 @@
return packageInfo.applicationInfo.enabled &&
(packageName != DEFAULT_PROVIDER_PACKAGE_NAME ||
PackageInfoCompat.getLongVersionCode(packageInfo) >=
- DEFAULT_PROVIDER_MIN_VERSION_CODE) &&
+ DEFAULT_PROVIDER_MIN_VERSION_CODE) &&
hasBindableService(packageManager, packageName)
}
@@ -534,6 +531,7 @@
/**
* Tag used in SDK debug logs.
+ *
* @suppress
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
diff --git a/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java b/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
index 0c619b1..70c172b 100644
--- a/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
+++ b/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
@@ -949,6 +949,7 @@
verifyBeginAligned();
}
+ @Ignore // b/269352002
@Test
public void testRedundantAppendRemove() throws Throwable {
Intent intent = new Intent();
diff --git a/libraryversions.toml b/libraryversions.toml
index 0abe361..4877b50 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -31,7 +31,7 @@
CONSTRAINTLAYOUT_CORE = "1.1.0-alpha08"
CONTENTPAGER = "1.1.0-alpha01"
COORDINATORLAYOUT = "1.3.0-alpha01"
-CORE = "1.10.0-alpha03"
+CORE = "1.10.0-beta01"
CORE_ANIMATION = "1.0.0-beta02"
CORE_ANIMATION_TESTING = "1.0.0-beta01"
CORE_APPDIGEST = "1.0.0-alpha01"
@@ -82,7 +82,7 @@
LEANBACK_TAB = "1.1.0-beta01"
LEGACY = "1.1.0-alpha01"
LIBYUV = "0.1.0-dev01"
-LIFECYCLE = "2.6.0-beta01"
+LIFECYCLE = "2.6.0-rc01"
LIFECYCLE_EXTENSIONS = "2.2.0"
LOADER = "1.2.0-alpha01"
MEDIA = "1.7.0-alpha02"
@@ -96,7 +96,7 @@
PERCENTLAYOUT = "1.1.0-alpha01"
PREFERENCE = "1.3.0-alpha01"
PRINT = "1.1.0-beta01"
-PRIVACYSANDBOX_ADS = "1.0.0-alpha01"
+PRIVACYSANDBOX_ADS = "1.0.0-beta01"
PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha01"
PRIVACYSANDBOX_TOOLS = "1.0.0-alpha03"
PRIVACYSANDBOX_UI = "1.0.0-alpha01"
@@ -129,7 +129,7 @@
TEST_UIAUTOMATOR = "2.3.0-alpha03"
TEXT = "1.0.0-alpha01"
TRACING = "1.2.0-alpha02"
-TRACING_PERFETTO = "1.0.0-alpha10"
+TRACING_PERFETTO = "1.0.0-alpha11"
TRANSITION = "1.5.0-alpha01"
TV = "1.0.0-alpha04"
TVPROVIDER = "1.1.0-alpha02"
@@ -140,19 +140,19 @@
VIEWPAGER = "1.1.0-alpha02"
VIEWPAGER2 = "1.2.0-alpha01"
WEAR = "1.3.0-alpha05"
-WEAR_COMPOSE = "1.2.0-alpha04"
+WEAR_COMPOSE = "1.2.0-alpha05"
WEAR_COMPOSE_MATERIAL3 = "1.0.0-alpha01"
WEAR_INPUT = "1.2.0-alpha03"
WEAR_INPUT_TESTING = "1.2.0-alpha03"
WEAR_ONGOING = "1.1.0-alpha01"
WEAR_PHONE_INTERACTIONS = "1.1.0-alpha04"
-WEAR_PROTOLAYOUT = "1.0.0-alpha03"
+WEAR_PROTOLAYOUT = "1.0.0-alpha04"
WEAR_REMOTE_INTERACTIONS = "1.1.0-alpha01"
WEAR_TILES = "1.2.0-alpha01"
WEAR_WATCHFACE = "1.2.0-alpha07"
WEBKIT = "1.7.0-alpha03"
-WINDOW = "1.1.0-alpha05"
-WINDOW_EXTENSIONS = "1.1.0-alpha02"
+WINDOW = "1.1.0-alpha06"
+WINDOW_EXTENSIONS = "1.1.0-alpha03"
WINDOW_EXTENSIONS_CORE = "1.0.0-alpha01"
WINDOW_SIDECAR = "1.0.0-rc01"
WORK = "2.9.0-alpha01"
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/LiveDataCoreIssueRegistry.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/LiveDataCoreIssueRegistry.kt
index 0b251e7..b0aab4e 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/LiveDataCoreIssueRegistry.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/LiveDataCoreIssueRegistry.kt
@@ -23,7 +23,7 @@
@Suppress("UnstableApiUsage")
class LiveDataCoreIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues get() = listOf(NonNullableMutableLiveDataDetector.ISSUE)
override val vendor = Vendor(
feedbackUrl = "https://issuetracker.google.com/issues/new?component=413132",
diff --git a/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/Transformations.kt b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/Transformations.kt
index 26d7c36..c3b9ed6 100644
--- a/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/Transformations.kt
+++ b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/Transformations.kt
@@ -177,19 +177,20 @@
@CheckResult
fun <X> LiveData<X>.distinctUntilChanged(): LiveData<X> {
val outputLiveData = MediatorLiveData<X>()
- outputLiveData.addSource(this, object : Observer<X> {
- var firstTime = true
-
- override fun onChanged(value: X) {
- val previousValue = outputLiveData.value
- if (firstTime ||
- previousValue == null && value != null ||
- previousValue != null && previousValue != value
- ) {
- firstTime = false
- outputLiveData.value = value
- }
+ var firstTime = true
+ if (isInitialized) {
+ outputLiveData.value = value
+ firstTime = false
+ }
+ outputLiveData.addSource(this) { value ->
+ val previousValue = outputLiveData.value
+ if (firstTime ||
+ previousValue == null && value != null ||
+ previousValue != null && previousValue != value
+ ) {
+ firstTime = false
+ outputLiveData.value = value
}
- })
+ }
return outputLiveData
}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/TransformationsTest.java b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
index 4b1a493..d7f3527 100644
--- a/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
+++ b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
@@ -193,6 +193,19 @@
}
@Test
+ public void testDistinctUntilChanged_initialValueIsSet() {
+ MutableLiveData<String> originalLiveData = new MutableLiveData<>("value");
+
+ LiveData<String> dedupedLiveData = Transformations.distinctUntilChanged(originalLiveData);
+ assertThat(dedupedLiveData.getValue(), is("value"));
+
+ CountingObserver<String> observer = new CountingObserver<>();
+ dedupedLiveData.observe(mOwner, observer);
+ assertThat(observer.mTimesUpdated, is(1));
+ assertThat(dedupedLiveData.getValue(), is("value"));
+ }
+
+ @Test
public void testDistinctUntilChanged_triggersOnInitialNullValue() {
MutableLiveData<String> originalLiveData = new MutableLiveData<>();
originalLiveData.setValue(null);
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleRuntimeIssueRegistry.kt b/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleRuntimeIssueRegistry.kt
index ca0bb57..b655be5 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleRuntimeIssueRegistry.kt
+++ b/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleRuntimeIssueRegistry.kt
@@ -23,7 +23,7 @@
@Suppress("UnstableApiUsage")
class LifecycleRuntimeIssueRegistry : IssueRegistry() {
// tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
LifecycleWhenChecks.ISSUE,
diff --git a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
index a4f7ce8..312cadd 100644
--- a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
@@ -25,7 +25,7 @@
class AndroidXIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues get(): List<Issue> {
return Issues
}
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
index 7bab6f3..ab2b60d 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
@@ -17,19 +17,17 @@
package androidx.build.lint
-import com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_API
-import com.android.tools.lint.detector.api.ApiConstraint
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
-import com.android.tools.lint.detector.api.Incident
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
+import com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_API
+import com.android.tools.lint.detector.api.Incident
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
-import com.android.tools.lint.detector.api.VersionChecks.Companion.isPrecededByVersionCheckExit
-import com.android.tools.lint.detector.api.VersionChecks.Companion.isWithinVersionCheckConditional
+import com.android.tools.lint.detector.api.VersionChecks
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UCallExpression
@@ -57,14 +55,15 @@
if (!context.evaluator.isMemberInClass(method, METHOD_REFLECTION_CLASS)) return
// Flag if the call isn't inside or preceded by an SDK_INT check.
- if (!isWithinVersionCheckConditional(
+ if (!VersionChecks.isWithinVersionCheckConditional(
context,
node,
- ApiConstraint.get(HIGHEST_KNOWN_API), false
+ HIGHEST_KNOWN_API,
+ false
) &&
- !isWithinVersionCheckConditional(context, node, ApiConstraint.get(1), true) &&
- !isPrecededByVersionCheckExit(context, node, ApiConstraint.get(HIGHEST_KNOWN_API)) &&
- !isPrecededByVersionCheckExit(context, node, ApiConstraint.get(1)) &&
+ !VersionChecks.isWithinVersionCheckConditional(context, node, 1, true) &&
+ !VersionChecks.isPrecededByVersionCheckExit(context, node, HIGHEST_KNOWN_API) &&
+ !VersionChecks.isPrecededByVersionCheckExit(context, node, 1) &&
!isWithinDeprecatedSinceApiMethod(node) &&
!isWithinDeprecatedSinceApiClass(node)
) {
diff --git a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
index 9e9ffe2..62d19a0 100644
--- a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
@@ -202,7 +202,8 @@
?: return
// Change: Removed SimpleDateFormat and Animator checks
- var api = apiDatabase.getMethodVersions(owner, name, desc).min()
+ @Suppress("DEPRECATION") // b/262915628
+ var api = apiDatabase.getMethodVersion(owner, name, desc)
if (api == -1) {
return
}
@@ -259,9 +260,10 @@
for (type in inheritanceChain) {
val expressionOwner = evaluator.getQualifiedName(type)
if (expressionOwner != null && expressionOwner != owner) {
- val specificApi = apiDatabase.getMethodVersions(
+ @Suppress("DEPRECATION") // b/262915628
+ val specificApi = apiDatabase.getMethodVersion(
expressionOwner, name, desc
- ).min()
+ )
if (specificApi == -1) {
if (apiDatabase.isRelevantOwner(expressionOwner)) {
return
@@ -338,8 +340,9 @@
) {
break
}
+ @Suppress("DEPRECATION") // b/262915628
val specificApi =
- apiDatabase.getMethodVersions(expressionOwner, name, desc).min()
+ apiDatabase.getMethodVersion(expressionOwner, name, desc)
if (specificApi == -1) {
if (apiDatabase.isRelevantOwner(expressionOwner)) {
break
@@ -384,9 +387,10 @@
if (provider != null) {
val methodOwner = evaluator.getQualifiedName(provider)
if (methodOwner != null) {
- val methodApi = apiDatabase.getMethodVersions(
+ @Suppress("DEPRECATION") // b/262915628
+ val methodApi = apiDatabase.getMethodVersion(
methodOwner, name, desc
- ).min()
+ )
if (methodApi == -1 || methodApi <= minSdk) {
// Yes, we found another call that doesn't have an API requirement
return
@@ -852,7 +856,8 @@
private fun classAvailableAtMinSdk(className: String): Boolean {
val apiDatabase = apiDatabase ?: return false
val minSdk = getMinSdk(context)
- val version = apiDatabase.getClassVersions(className).min()
+ @Suppress("DEPRECATION") // b/262915628
+ val version = apiDatabase.getClassVersion(className)
return version <= minSdk
}
diff --git a/navigation/OWNERS b/navigation/OWNERS
index bf053cd..ec2387e6 100644
--- a/navigation/OWNERS
+++ b/navigation/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 409828
+# Bug component: 606741
[email protected]
[email protected]
[email protected]
diff --git a/navigation/navigation-common-lint/src/main/java/androidx/navigation/common/lint/NavigationCommonIssueRegistry.kt b/navigation/navigation-common-lint/src/main/java/androidx/navigation/common/lint/NavigationCommonIssueRegistry.kt
index f5a5d52..ff861cd 100644
--- a/navigation/navigation-common-lint/src/main/java/androidx/navigation/common/lint/NavigationCommonIssueRegistry.kt
+++ b/navigation/navigation-common-lint/src/main/java/androidx/navigation/common/lint/NavigationCommonIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class NavigationCommonIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
EmptyNavDeepLinkDetector.EmptyNavDeepLink
diff --git a/navigation/navigation-compose-lint/src/main/java/androidx/navigation/compose/lint/NavigationComposeIssueRegistry.kt b/navigation/navigation-compose-lint/src/main/java/androidx/navigation/compose/lint/NavigationComposeIssueRegistry.kt
index b6b5d155..402db3be 100644
--- a/navigation/navigation-compose-lint/src/main/java/androidx/navigation/compose/lint/NavigationComposeIssueRegistry.kt
+++ b/navigation/navigation-compose-lint/src/main/java/androidx/navigation/compose/lint/NavigationComposeIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class NavigationComposeIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
ComposableDestinationInComposeScopeDetector.ComposableDestinationInComposeScope,
diff --git a/navigation/navigation-compose/samples/build.gradle b/navigation/navigation-compose/samples/build.gradle
index 8ee9740..4cc57c0 100644
--- a/navigation/navigation-compose/samples/build.gradle
+++ b/navigation/navigation-compose/samples/build.gradle
@@ -30,6 +30,7 @@
compileOnly(projectOrArtifact(":annotation:annotation-sampled"))
implementation("androidx.compose.foundation:foundation:1.0.1")
+ implementation projectOrArtifact(":compose:ui:ui-tooling")
implementation(projectOrArtifact(":navigation:navigation-compose"))
implementation("androidx.compose.material:material:1.0.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
diff --git a/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/NavigationSamples.kt b/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/NavigationSamples.kt
index d38c258..4cc5ef4 100644
--- a/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/NavigationSamples.kt
+++ b/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/NavigationSamples.kt
@@ -21,6 +21,7 @@
import androidx.annotation.Sampled
import androidx.annotation.StringRes
import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -35,11 +36,15 @@
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Color.Companion.LightGray
+import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
@@ -242,6 +247,27 @@
}
}
+@Preview
+@Composable
+fun NavHostPreview() {
+ CompositionLocalProvider(
+ LocalInspectionMode provides true,
+ ) {
+ Box(Modifier.fillMaxSize().background(Color.Red)) {
+ NavHost(
+ navController = rememberNavController(),
+ startDestination = "home"
+ ) {
+ composable("home") {
+ Box(Modifier.fillMaxSize().background(Color.Blue)) {
+ Text(text = "test", modifier = Modifier.testTag("text"))
+ }
+ }
+ }
+ }
+ }
+}
+
private val phrases = listOf(
"Easy As Pie",
"Wouldn't Harm a Fly",
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
index 989e166..4cec329 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
@@ -41,6 +41,7 @@
import java.util.concurrent.TimeUnit
import kotlin.reflect.KClass
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -696,6 +697,7 @@
assertWithMessage("Entry2 should have been stopped").that(entry1Stopped).isTrue()
}
+ @Ignore // b/269297210
@LargeTest
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
diff --git a/navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/NavigationRuntimeIssueRegistry.kt b/navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/NavigationRuntimeIssueRegistry.kt
index 48b846a..b4d90ba 100644
--- a/navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/NavigationRuntimeIssueRegistry.kt
+++ b/navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/NavigationRuntimeIssueRegistry.kt
@@ -27,7 +27,7 @@
*/
class NavigationRuntimeIssueRegistry : IssueRegistry() {
// Tests are run with this version. We ensure that with ApiLintVersionsTest
- override val api = 14
+ override val api = 13
override val minApi = CURRENT_API
override val issues get() = listOf(
DeepLinkInActivityDestinationDetector.DeepLinkInActivityDestination
diff --git a/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta01.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+ public abstract class AdIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AdIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+ public abstract class AdSelectionManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+ }
+
+ public static final class AdSelectionManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+ public abstract class AppSetIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AppSetIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+ public abstract class CustomAudienceManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+ }
+
+ public static final class CustomAudienceManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+ public abstract class MeasurementManagerFutures {
+ method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+ method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+ }
+
+ public static final class MeasurementManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+ public abstract class TopicsManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+ }
+
+ public static final class TopicsManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+ public abstract class AdIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AdIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+ public abstract class AdSelectionManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+ }
+
+ public static final class AdSelectionManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+ public abstract class AppSetIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AppSetIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+ public abstract class CustomAudienceManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+ }
+
+ public static final class CustomAudienceManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+ public abstract class MeasurementManagerFutures {
+ method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+ method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+ }
+
+ public static final class MeasurementManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+ public abstract class TopicsManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+ }
+
+ public static final class TopicsManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta01.txt
diff --git a/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,92 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.java.adid {
+
+ public abstract class AdIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adid.AdId> getAdIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AdIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.adselection {
+
+ public abstract class AdSelectionManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> reportImpressionAsync(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome> selectAdsAsync(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ field public static final androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures.Companion Companion;
+ }
+
+ public static final class AdSelectionManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.appsetid {
+
+ public abstract class AppSetIdManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.appsetid.AppSetId> getAppSetIdAsync();
+ field public static final androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures.Companion Companion;
+ }
+
+ public static final class AppSetIdManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.customaudience {
+
+ public abstract class CustomAudienceManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> joinCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> leaveCustomAudienceAsync(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures.Companion Companion;
+ }
+
+ public static final class CustomAudienceManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.measurement {
+
+ public abstract class MeasurementManagerFutures {
+ method public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> deleteRegistrationsAsync(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest);
+ method public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getMeasurementApiStatusAsync();
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerSourceAsync(android.net.Uri attributionSource, android.view.InputEvent? inputEvent);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerTriggerAsync(android.net.Uri trigger);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebSourceAsync(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> registerWebTriggerAsync(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures.Companion Companion;
+ }
+
+ public static final class MeasurementManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures? from(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.java.topics {
+
+ public abstract class TopicsManagerFutures {
+ method public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract com.google.common.util.concurrent.ListenableFuture<androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse> getTopicsAsync(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request);
+ field public static final androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures.Companion Companion;
+ }
+
+ public static final class TopicsManagerFutures.Companion {
+ method public androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures? from(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
index 8d5d99a..6da172a 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
@@ -135,6 +135,21 @@
runShellCommand("setprop debug.adservices.disable_measurement_enrollment_check null");
}
+ // Force using bundled files instead of using MDD downloaded files. This helps to make the test
+ // results deterministic.
+ public void shouldForceUseBundledFiles(boolean shouldUse) {
+ if (shouldUse) {
+ runShellCommand("device_config put adservices classifier_force_use_bundled_files true");
+ }
+ else {
+ runShellCommand("device_config delete adservices classifier_force_use_bundled_files");
+ }
+ }
+
+ public void enableVerboseLogging() {
+ runShellCommand("setprop log.tag.adservices VERBOSE");
+ }
+
@SuppressWarnings("deprecation")
// Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
public String getAdServicesPackageName() {
diff --git a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/topics/TopicsManagerTest.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/topics/TopicsManagerTest.java
index 49c545ae..b6155a8 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/topics/TopicsManagerTest.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/topics/TopicsManagerTest.java
@@ -66,6 +66,10 @@
mTestUtil.overrideAllowlists(true);
// TODO: Remove this override.
mTestUtil.enableEnrollmentCheck(true);
+ // Force to use bundled files to make test result deterministic.
+ mTestUtil.shouldForceUseBundledFiles(true);
+ // Enable verbose logging.
+ mTestUtil.enableVerboseLogging();
}
@After
@@ -76,6 +80,7 @@
mTestUtil.overrideConsentManagerDebugMode(false);
mTestUtil.overrideAllowlists(false);
mTestUtil.enableEnrollmentCheck(false);
+ mTestUtil.shouldForceUseBundledFiles(false);
}
@Test
@@ -92,7 +97,7 @@
GetTopicsResponse response = topicsManager.getTopicsAsync(request).get();
// At beginning, Sdk1 receives no topic.
- assertThat(response.getTopics().isEmpty());
+ assertThat(response.getTopics()).isEmpty();
// Now force the Epoch Computation Job. This should be done in the same epoch for
// callersCanLearnMap to have the entry for processing.
@@ -106,8 +111,8 @@
response = topicsManager.getTopicsAsync(request).get();
assertThat(response.getTopics()).isNotEmpty();
- // Top 5 classifications for empty string with v2 model are [10230, 10253, 10227, 10250,
- // 10257]. This is computed by running the model on the device for empty string.
+ // Top 5 classifications for empty string with v2 model are [10147, 10253, 10175, 10254,
+ // 10333]. This is computed by running the model on the device for empty string.
// These 5 classification topics will become top 5 topics of the epoch since there is
// no other apps calling Topics API.
// The app will be assigned one random topic from one of these 5 topics.
@@ -116,7 +121,7 @@
Topic topic = response.getTopics().get(0);
// topic is one of the 5 classification topics of the Test App.
- assertThat(topic.getTopicId()).isIn(Arrays.asList(10230, 10253, 10227, 10250, 10257));
+ assertThat(topic.getTopicId()).isIn(Arrays.asList(10147, 10253, 10175, 10254, 10333));
assertThat(topic.getModelVersion()).isAtLeast(1L);
assertThat(topic.getTaxonomyVersion()).isAtLeast(1L);
diff --git a/privacysandbox/ads/ads-adservices/api/1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/1.0.0-beta01.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+ public final class AdId {
+ method public String getAdId();
+ method public boolean isLimitAdTrackingEnabled();
+ property public final String adId;
+ property public final boolean isLimitAdTrackingEnabled;
+ }
+
+ public abstract class AdIdManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+ method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+ }
+
+ public static final class AdIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+ public final class AdSelectionConfig {
+ ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+ method public android.net.Uri getDecisionLogicUri();
+ method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+ method public android.net.Uri getTrustedScoringSignalsUri();
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+ property public final android.net.Uri decisionLogicUri;
+ property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+ property public final android.net.Uri trustedScoringSignalsUri;
+ }
+
+ public abstract class AdSelectionManager {
+ method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+ field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+ }
+
+ public static final class AdSelectionManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ }
+
+ public final class AdSelectionOutcome {
+ ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+ method public long getAdSelectionId();
+ method public android.net.Uri getRenderUri();
+ property public final long adSelectionId;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class ReportImpressionRequest {
+ ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+ method public long getAdSelectionId();
+ property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+ property public final long adSelectionId;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+ public final class AppSetId {
+ ctor public AppSetId(String id, int scope);
+ method public String getId();
+ method public int getScope();
+ property public final String id;
+ property public final int scope;
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+ field public static final int SCOPE_APP = 1; // 0x1
+ field public static final int SCOPE_DEVELOPER = 2; // 0x2
+ }
+
+ public static final class AppSetId.Companion {
+ }
+
+ public abstract class AppSetIdManager {
+ method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+ method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+ }
+
+ public static final class AppSetIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+ public final class AdData {
+ ctor public AdData(android.net.Uri renderUri, String metadata);
+ method public String getMetadata();
+ method public android.net.Uri getRenderUri();
+ property public final String metadata;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class AdSelectionSignals {
+ ctor public AdSelectionSignals(String signals);
+ method public String getSignals();
+ property public final String signals;
+ }
+
+ public final class AdTechIdentifier {
+ ctor public AdTechIdentifier(String identifier);
+ method public String getIdentifier();
+ property public final String identifier;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+ public final class CustomAudience {
+ ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+ method public java.time.Instant? getActivationTime();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+ method public android.net.Uri getBiddingLogicUri();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public android.net.Uri getDailyUpdateUri();
+ method public java.time.Instant? getExpirationTime();
+ method public String getName();
+ method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+ property public final java.time.Instant? activationTime;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+ property public final android.net.Uri biddingLogicUri;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final android.net.Uri dailyUpdateUri;
+ property public final java.time.Instant? expirationTime;
+ property public final String name;
+ property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+ }
+
+ public static final class CustomAudience.Builder {
+ ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+ }
+
+ public abstract class CustomAudienceManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+ }
+
+ public static final class CustomAudienceManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ }
+
+ public final class JoinCustomAudienceRequest {
+ ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+ property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+ }
+
+ public final class LeaveCustomAudienceRequest {
+ ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public String getName();
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final String name;
+ }
+
+ public final class TrustedBiddingData {
+ ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+ method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+ method public android.net.Uri getTrustedBiddingUri();
+ property public final java.util.List<java.lang.String> trustedBiddingKeys;
+ property public final android.net.Uri trustedBiddingUri;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+ ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+ method public int getDeletionMode();
+ method public java.util.List<android.net.Uri> getDomainUris();
+ method public java.time.Instant getEnd();
+ method public int getMatchBehavior();
+ method public java.util.List<android.net.Uri> getOriginUris();
+ method public java.time.Instant getStart();
+ property public final int deletionMode;
+ property public final java.util.List<android.net.Uri> domainUris;
+ property public final java.time.Instant end;
+ property public final int matchBehavior;
+ property public final java.util.List<android.net.Uri> originUris;
+ property public final java.time.Instant start;
+ field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+ field public static final int DELETION_MODE_ALL = 0; // 0x0
+ field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+ field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+ field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+ ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+ }
+
+ public static final class DeletionRequest.Companion {
+ }
+
+ public abstract class MeasurementManager {
+ ctor public MeasurementManager();
+ method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+ method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+ field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+ field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+ }
+
+ public static final class MeasurementManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+ ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+ ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+ method public android.net.Uri? getAppDestination();
+ method public android.view.InputEvent? getInputEvent();
+ method public android.net.Uri getTopOriginUri();
+ method public android.net.Uri? getVerifiedDestination();
+ method public android.net.Uri? getWebDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+ property public final android.net.Uri? appDestination;
+ property public final android.view.InputEvent? inputEvent;
+ property public final android.net.Uri topOriginUri;
+ property public final android.net.Uri? verifiedDestination;
+ property public final android.net.Uri? webDestination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+ }
+
+ public static final class WebSourceRegistrationRequest.Builder {
+ ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+ ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+ ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+ method public android.net.Uri getDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+ property public final android.net.Uri destination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+ public final class GetTopicsRequest {
+ ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+ method public String getAdsSdkName();
+ method public boolean getShouldRecordObservation();
+ property public final String adsSdkName;
+ property public final boolean shouldRecordObservation;
+ }
+
+ public static final class GetTopicsRequest.Builder {
+ ctor public GetTopicsRequest.Builder();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+ }
+
+ public final class GetTopicsResponse {
+ ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+ method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+ }
+
+ public final class Topic {
+ ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+ method public long getModelVersion();
+ method public long getTaxonomyVersion();
+ method public int getTopicId();
+ property public final long modelVersion;
+ property public final long taxonomyVersion;
+ property public final int topicId;
+ }
+
+ public abstract class TopicsManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+ method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+ }
+
+ public static final class TopicsManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+ public final class AdId {
+ method public String getAdId();
+ method public boolean isLimitAdTrackingEnabled();
+ property public final String adId;
+ property public final boolean isLimitAdTrackingEnabled;
+ }
+
+ public abstract class AdIdManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+ method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+ }
+
+ public static final class AdIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+ public final class AdSelectionConfig {
+ ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+ method public android.net.Uri getDecisionLogicUri();
+ method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+ method public android.net.Uri getTrustedScoringSignalsUri();
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+ property public final android.net.Uri decisionLogicUri;
+ property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+ property public final android.net.Uri trustedScoringSignalsUri;
+ }
+
+ public abstract class AdSelectionManager {
+ method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+ field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+ }
+
+ public static final class AdSelectionManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ }
+
+ public final class AdSelectionOutcome {
+ ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+ method public long getAdSelectionId();
+ method public android.net.Uri getRenderUri();
+ property public final long adSelectionId;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class ReportImpressionRequest {
+ ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+ method public long getAdSelectionId();
+ property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+ property public final long adSelectionId;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+ public final class AppSetId {
+ ctor public AppSetId(String id, int scope);
+ method public String getId();
+ method public int getScope();
+ property public final String id;
+ property public final int scope;
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+ field public static final int SCOPE_APP = 1; // 0x1
+ field public static final int SCOPE_DEVELOPER = 2; // 0x2
+ }
+
+ public static final class AppSetId.Companion {
+ }
+
+ public abstract class AppSetIdManager {
+ method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+ method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+ }
+
+ public static final class AppSetIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+ public final class AdData {
+ ctor public AdData(android.net.Uri renderUri, String metadata);
+ method public String getMetadata();
+ method public android.net.Uri getRenderUri();
+ property public final String metadata;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class AdSelectionSignals {
+ ctor public AdSelectionSignals(String signals);
+ method public String getSignals();
+ property public final String signals;
+ }
+
+ public final class AdTechIdentifier {
+ ctor public AdTechIdentifier(String identifier);
+ method public String getIdentifier();
+ property public final String identifier;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+ public final class CustomAudience {
+ ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+ method public java.time.Instant? getActivationTime();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+ method public android.net.Uri getBiddingLogicUri();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public android.net.Uri getDailyUpdateUri();
+ method public java.time.Instant? getExpirationTime();
+ method public String getName();
+ method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+ property public final java.time.Instant? activationTime;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+ property public final android.net.Uri biddingLogicUri;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final android.net.Uri dailyUpdateUri;
+ property public final java.time.Instant? expirationTime;
+ property public final String name;
+ property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+ }
+
+ public static final class CustomAudience.Builder {
+ ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+ }
+
+ public abstract class CustomAudienceManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+ }
+
+ public static final class CustomAudienceManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ }
+
+ public final class JoinCustomAudienceRequest {
+ ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+ property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+ }
+
+ public final class LeaveCustomAudienceRequest {
+ ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public String getName();
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final String name;
+ }
+
+ public final class TrustedBiddingData {
+ ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+ method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+ method public android.net.Uri getTrustedBiddingUri();
+ property public final java.util.List<java.lang.String> trustedBiddingKeys;
+ property public final android.net.Uri trustedBiddingUri;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+ ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+ method public int getDeletionMode();
+ method public java.util.List<android.net.Uri> getDomainUris();
+ method public java.time.Instant getEnd();
+ method public int getMatchBehavior();
+ method public java.util.List<android.net.Uri> getOriginUris();
+ method public java.time.Instant getStart();
+ property public final int deletionMode;
+ property public final java.util.List<android.net.Uri> domainUris;
+ property public final java.time.Instant end;
+ property public final int matchBehavior;
+ property public final java.util.List<android.net.Uri> originUris;
+ property public final java.time.Instant start;
+ field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+ field public static final int DELETION_MODE_ALL = 0; // 0x0
+ field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+ field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+ field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+ ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+ }
+
+ public static final class DeletionRequest.Companion {
+ }
+
+ public abstract class MeasurementManager {
+ ctor public MeasurementManager();
+ method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+ method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+ field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+ field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+ }
+
+ public static final class MeasurementManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+ ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+ ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+ method public android.net.Uri? getAppDestination();
+ method public android.view.InputEvent? getInputEvent();
+ method public android.net.Uri getTopOriginUri();
+ method public android.net.Uri? getVerifiedDestination();
+ method public android.net.Uri? getWebDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+ property public final android.net.Uri? appDestination;
+ property public final android.view.InputEvent? inputEvent;
+ property public final android.net.Uri topOriginUri;
+ property public final android.net.Uri? verifiedDestination;
+ property public final android.net.Uri? webDestination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+ }
+
+ public static final class WebSourceRegistrationRequest.Builder {
+ ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+ ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+ ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+ method public android.net.Uri getDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+ property public final android.net.Uri destination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+ public final class GetTopicsRequest {
+ ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+ method public String getAdsSdkName();
+ method public boolean getShouldRecordObservation();
+ property public final String adsSdkName;
+ property public final boolean shouldRecordObservation;
+ }
+
+ public static final class GetTopicsRequest.Builder {
+ ctor public GetTopicsRequest.Builder();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+ }
+
+ public final class GetTopicsResponse {
+ ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+ method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+ }
+
+ public final class Topic {
+ ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+ method public long getModelVersion();
+ method public long getTaxonomyVersion();
+ method public int getTopicId();
+ property public final long modelVersion;
+ property public final long taxonomyVersion;
+ property public final int topicId;
+ }
+
+ public abstract class TopicsManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+ method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+ }
+
+ public static final class TopicsManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta01.txt
diff --git a/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta01.txt b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,345 @@
+// Signature format: 4.0
+package androidx.privacysandbox.ads.adservices.adid {
+
+ public final class AdId {
+ method public String getAdId();
+ method public boolean isLimitAdTrackingEnabled();
+ property public final String adId;
+ property public final boolean isLimitAdTrackingEnabled;
+ }
+
+ public abstract class AdIdManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID) public abstract suspend Object? getAdId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adid.AdId>);
+ method public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.adid.AdIdManager.Companion Companion;
+ }
+
+ public static final class AdIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adid.AdIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.adselection {
+
+ public final class AdSelectionConfig {
+ ctor public AdSelectionConfig(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller, android.net.Uri decisionLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals, androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals, java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals, android.net.Uri trustedScoringSignalsUri);
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getAdSelectionSignals();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> getCustomAudienceBuyers();
+ method public android.net.Uri getDecisionLogicUri();
+ method public java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> getPerBuyerSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getSeller();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals getSellerSignals();
+ method public android.net.Uri getTrustedScoringSignalsUri();
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals adSelectionSignals;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier> customAudienceBuyers;
+ property public final android.net.Uri decisionLogicUri;
+ property public final java.util.Map<androidx.privacysandbox.ads.adservices.common.AdTechIdentifier,androidx.privacysandbox.ads.adservices.common.AdSelectionSignals> perBuyerSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier seller;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals sellerSignals;
+ property public final android.net.Uri trustedScoringSignalsUri;
+ }
+
+ public abstract class AdSelectionManager {
+ method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? reportImpression(androidx.privacysandbox.ads.adservices.adselection.ReportImpressionRequest reportImpressionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? selectAds(androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.adselection.AdSelectionOutcome>);
+ field public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager.Companion Companion;
+ }
+
+ public static final class AdSelectionManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+ }
+
+ public final class AdSelectionOutcome {
+ ctor public AdSelectionOutcome(long adSelectionId, android.net.Uri renderUri);
+ method public long getAdSelectionId();
+ method public android.net.Uri getRenderUri();
+ property public final long adSelectionId;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class ReportImpressionRequest {
+ ctor public ReportImpressionRequest(long adSelectionId, androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig);
+ method public androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig getAdSelectionConfig();
+ method public long getAdSelectionId();
+ property public final androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig adSelectionConfig;
+ property public final long adSelectionId;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.appsetid {
+
+ public final class AppSetId {
+ ctor public AppSetId(String id, int scope);
+ method public String getId();
+ method public int getScope();
+ property public final String id;
+ property public final int scope;
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetId.Companion Companion;
+ field public static final int SCOPE_APP = 1; // 0x1
+ field public static final int SCOPE_DEVELOPER = 2; // 0x2
+ }
+
+ public static final class AppSetId.Companion {
+ }
+
+ public abstract class AppSetIdManager {
+ method public abstract suspend Object? getAppSetId(kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.appsetid.AppSetId>);
+ method public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager.Companion Companion;
+ }
+
+ public static final class AppSetIdManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.appsetid.AppSetIdManager? obtain(android.content.Context context);
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.common {
+
+ public final class AdData {
+ ctor public AdData(android.net.Uri renderUri, String metadata);
+ method public String getMetadata();
+ method public android.net.Uri getRenderUri();
+ property public final String metadata;
+ property public final android.net.Uri renderUri;
+ }
+
+ public final class AdSelectionSignals {
+ ctor public AdSelectionSignals(String signals);
+ method public String getSignals();
+ property public final String signals;
+ }
+
+ public final class AdTechIdentifier {
+ ctor public AdTechIdentifier(String identifier);
+ method public String getIdentifier();
+ property public final String identifier;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.customaudience {
+
+ public final class CustomAudience {
+ ctor public CustomAudience(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads, optional java.time.Instant? activationTime, optional java.time.Instant? expirationTime, optional androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals, optional androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals);
+ method public java.time.Instant? getActivationTime();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> getAds();
+ method public android.net.Uri getBiddingLogicUri();
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public android.net.Uri getDailyUpdateUri();
+ method public java.time.Instant? getExpirationTime();
+ method public String getName();
+ method public androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? getTrustedBiddingSignals();
+ method public androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? getUserBiddingSignals();
+ property public final java.time.Instant? activationTime;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads;
+ property public final android.net.Uri biddingLogicUri;
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final android.net.Uri dailyUpdateUri;
+ property public final java.time.Instant? expirationTime;
+ property public final String name;
+ property public final androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData? trustedBiddingSignals;
+ property public final androidx.privacysandbox.ads.adservices.common.AdSelectionSignals? userBiddingSignals;
+ }
+
+ public static final class CustomAudience.Builder {
+ ctor public CustomAudience.Builder(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name, android.net.Uri dailyUpdateUri, android.net.Uri biddingLogicUri, java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience build();
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setActivationTime(java.time.Instant activationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setAds(java.util.List<androidx.privacysandbox.ads.adservices.common.AdData> ads);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBiddingLogicUri(android.net.Uri biddingLogicUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setBuyer(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setDailyUpdateUri(android.net.Uri dailyUpdateUri);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setExpirationTime(java.time.Instant expirationTime);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setName(String name);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setTrustedBiddingData(androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData trustedBiddingSignals);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience.Builder setUserBiddingSignals(androidx.privacysandbox.ads.adservices.common.AdSelectionSignals userBiddingSignals);
+ }
+
+ public abstract class CustomAudienceManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? joinCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE) public abstract suspend Object? leaveCustomAudience(androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager.Companion Companion;
+ }
+
+ public static final class CustomAudienceManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudienceManager? obtain(android.content.Context context);
+ }
+
+ public final class JoinCustomAudienceRequest {
+ ctor public JoinCustomAudienceRequest(androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience);
+ method public androidx.privacysandbox.ads.adservices.customaudience.CustomAudience getCustomAudience();
+ property public final androidx.privacysandbox.ads.adservices.customaudience.CustomAudience customAudience;
+ }
+
+ public final class LeaveCustomAudienceRequest {
+ ctor public LeaveCustomAudienceRequest(androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer, String name);
+ method public androidx.privacysandbox.ads.adservices.common.AdTechIdentifier getBuyer();
+ method public String getName();
+ property public final androidx.privacysandbox.ads.adservices.common.AdTechIdentifier buyer;
+ property public final String name;
+ }
+
+ public final class TrustedBiddingData {
+ ctor public TrustedBiddingData(android.net.Uri trustedBiddingUri, java.util.List<java.lang.String> trustedBiddingKeys);
+ method public java.util.List<java.lang.String> getTrustedBiddingKeys();
+ method public android.net.Uri getTrustedBiddingUri();
+ property public final java.util.List<java.lang.String> trustedBiddingKeys;
+ property public final android.net.Uri trustedBiddingUri;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.measurement {
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class DeletionRequest {
+ ctor public DeletionRequest(int deletionMode, int matchBehavior, optional java.time.Instant start, optional java.time.Instant end, optional java.util.List<? extends android.net.Uri> domainUris, optional java.util.List<? extends android.net.Uri> originUris);
+ method public int getDeletionMode();
+ method public java.util.List<android.net.Uri> getDomainUris();
+ method public java.time.Instant getEnd();
+ method public int getMatchBehavior();
+ method public java.util.List<android.net.Uri> getOriginUris();
+ method public java.time.Instant getStart();
+ property public final int deletionMode;
+ property public final java.util.List<android.net.Uri> domainUris;
+ property public final java.time.Instant end;
+ property public final int matchBehavior;
+ property public final java.util.List<android.net.Uri> originUris;
+ property public final java.time.Instant start;
+ field public static final androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Companion Companion;
+ field public static final int DELETION_MODE_ALL = 0; // 0x0
+ field public static final int DELETION_MODE_EXCLUDE_INTERNAL_DATA = 1; // 0x1
+ field public static final int MATCH_BEHAVIOR_DELETE = 0; // 0x0
+ field public static final int MATCH_BEHAVIOR_PRESERVE = 1; // 0x1
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static final class DeletionRequest.Builder {
+ ctor public DeletionRequest.Builder(int deletionMode, int matchBehavior);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setDomainUris(java.util.List<? extends android.net.Uri> domainUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setEnd(java.time.Instant end);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setOriginUris(java.util.List<? extends android.net.Uri> originUris);
+ method public androidx.privacysandbox.ads.adservices.measurement.DeletionRequest.Builder setStart(java.time.Instant start);
+ }
+
+ public static final class DeletionRequest.Companion {
+ }
+
+ public abstract class MeasurementManager {
+ ctor public MeasurementManager();
+ method public abstract suspend Object? deleteRegistrations(androidx.privacysandbox.ads.adservices.measurement.DeletionRequest deletionRequest, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? getMeasurementApiStatus(kotlin.coroutines.Continuation<? super java.lang.Integer>);
+ method public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerSource(android.net.Uri attributionSource, android.view.InputEvent? inputEvent, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerTrigger(android.net.Uri trigger, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebSource(androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) public abstract suspend Object? registerWebTrigger(androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest request, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ field public static final androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion Companion;
+ field public static final int MEASUREMENT_API_STATE_DISABLED = 0; // 0x0
+ field public static final int MEASUREMENT_API_STATE_ENABLED = 1; // 0x1
+ }
+
+ public static final class MeasurementManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.measurement.MeasurementManager? obtain(android.content.Context context);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceParams {
+ ctor public WebSourceParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebSourceRegistrationRequest {
+ ctor public WebSourceRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri, optional android.view.InputEvent? inputEvent, optional android.net.Uri? appDestination, optional android.net.Uri? webDestination, optional android.net.Uri? verifiedDestination);
+ method public android.net.Uri? getAppDestination();
+ method public android.view.InputEvent? getInputEvent();
+ method public android.net.Uri getTopOriginUri();
+ method public android.net.Uri? getVerifiedDestination();
+ method public android.net.Uri? getWebDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> getWebSourceParams();
+ property public final android.net.Uri? appDestination;
+ property public final android.view.InputEvent? inputEvent;
+ property public final android.net.Uri topOriginUri;
+ property public final android.net.Uri? verifiedDestination;
+ property public final android.net.Uri? webDestination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams;
+ }
+
+ public static final class WebSourceRegistrationRequest.Builder {
+ ctor public WebSourceRegistrationRequest.Builder(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebSourceParams> webSourceParams, android.net.Uri topOriginUri);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest build();
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setAppDestination(android.net.Uri? appDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setInputEvent(android.view.InputEvent inputEvent);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setVerifiedDestination(android.net.Uri? verifiedDestination);
+ method public androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest.Builder setWebDestination(android.net.Uri? webDestination);
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerParams {
+ ctor public WebTriggerParams(android.net.Uri registrationUri, boolean debugKeyAllowed);
+ method public boolean getDebugKeyAllowed();
+ method public android.net.Uri getRegistrationUri();
+ property public final boolean debugKeyAllowed;
+ property public final android.net.Uri registrationUri;
+ }
+
+ @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class WebTriggerRegistrationRequest {
+ ctor public WebTriggerRegistrationRequest(java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams, android.net.Uri destination);
+ method public android.net.Uri getDestination();
+ method public java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> getWebTriggerParams();
+ property public final android.net.Uri destination;
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.measurement.WebTriggerParams> webTriggerParams;
+ }
+
+}
+
+package androidx.privacysandbox.ads.adservices.topics {
+
+ public final class GetTopicsRequest {
+ ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+ method public String getAdsSdkName();
+ method public boolean getShouldRecordObservation();
+ property public final String adsSdkName;
+ property public final boolean shouldRecordObservation;
+ }
+
+ public static final class GetTopicsRequest.Builder {
+ ctor public GetTopicsRequest.Builder();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest build();
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setAdsSdkName(String adsSdkName);
+ method public androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest.Builder setShouldRecordObservation(boolean shouldRecordObservation);
+ }
+
+ public final class GetTopicsResponse {
+ ctor public GetTopicsResponse(java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics);
+ method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+ property public final java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> topics;
+ }
+
+ public final class Topic {
+ ctor public Topic(long taxonomyVersion, long modelVersion, int topicId);
+ method public long getModelVersion();
+ method public long getTaxonomyVersion();
+ method public int getTopicId();
+ property public final long modelVersion;
+ property public final long taxonomyVersion;
+ property public final int topicId;
+ }
+
+ public abstract class TopicsManager {
+ method @RequiresPermission(android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS) public abstract suspend Object? getTopics(androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest request, kotlin.coroutines.Continuation<? super androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse>);
+ method public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ field public static final androidx.privacysandbox.ads.adservices.topics.TopicsManager.Companion Companion;
+ }
+
+ public static final class TopicsManager.Companion {
+ method public androidx.privacysandbox.ads.adservices.topics.TopicsManager? obtain(android.content.Context context);
+ }
+
+}
+
diff --git a/privacysandbox/ads/ads-adservices/build.gradle b/privacysandbox/ads/ads-adservices/build.gradle
index 2679d8e..1c3ab60 100644
--- a/privacysandbox/ads/ads-adservices/build.gradle
+++ b/privacysandbox/ads/ads-adservices/build.gradle
@@ -28,7 +28,7 @@
api(libs.kotlinStdlib)
api(libs.kotlinCoroutinesCore)
implementation("androidx.core:core-ktx:1.8.0")
- api(projectOrArtifact(":annotation:annotation"))
+ api("androidx.annotation:annotation:1.6.0")
androidTestImplementation(libs.junit)
androidTestImplementation(libs.kotlinTestJunit)
diff --git a/recyclerview/recyclerview-lint/src/main/java/androidx/recyclerview/lint/RecyclerViewIssueRegistry.kt b/recyclerview/recyclerview-lint/src/main/java/androidx/recyclerview/lint/RecyclerViewIssueRegistry.kt
index 877177f..4e2d8ab 100644
--- a/recyclerview/recyclerview-lint/src/main/java/androidx/recyclerview/lint/RecyclerViewIssueRegistry.kt
+++ b/recyclerview/recyclerview-lint/src/main/java/androidx/recyclerview/lint/RecyclerViewIssueRegistry.kt
@@ -25,7 +25,7 @@
class RecyclerViewIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues: List<Issue>
get() = listOf(
InvalidSetHasFixedSizeDetector.ISSUE
diff --git a/recyclerview/recyclerview/api/current.txt b/recyclerview/recyclerview/api/current.txt
index 3750c3c..ca945e9 100644
--- a/recyclerview/recyclerview/api/current.txt
+++ b/recyclerview/recyclerview/api/current.txt
@@ -470,6 +470,7 @@
method public void setAccessibilityDelegateCompat(androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate?);
method public void setAdapter(androidx.recyclerview.widget.RecyclerView.Adapter?);
method public void setChildDrawingOrderCallback(androidx.recyclerview.widget.RecyclerView.ChildDrawingOrderCallback?);
+ method public static void setDebugAssertionsEnabled(boolean);
method public void setEdgeEffectFactory(androidx.recyclerview.widget.RecyclerView.EdgeEffectFactory);
method public void setHasFixedSize(boolean);
method public void setItemAnimator(androidx.recyclerview.widget.RecyclerView.ItemAnimator?);
@@ -483,6 +484,7 @@
method public void setRecycledViewPool(androidx.recyclerview.widget.RecyclerView.RecycledViewPool?);
method @Deprecated public void setRecyclerListener(androidx.recyclerview.widget.RecyclerView.RecyclerListener?);
method public void setScrollingTouchSlop(int);
+ method public static void setVerboseLoggingEnabled(boolean);
method public void setViewCacheExtension(androidx.recyclerview.widget.RecyclerView.ViewCacheExtension?);
method public void smoothScrollBy(@Px int, @Px int);
method public void smoothScrollBy(@Px int, @Px int, android.view.animation.Interpolator?);
diff --git a/recyclerview/recyclerview/api/public_plus_experimental_current.txt b/recyclerview/recyclerview/api/public_plus_experimental_current.txt
index 3750c3c..ca945e9 100644
--- a/recyclerview/recyclerview/api/public_plus_experimental_current.txt
+++ b/recyclerview/recyclerview/api/public_plus_experimental_current.txt
@@ -470,6 +470,7 @@
method public void setAccessibilityDelegateCompat(androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate?);
method public void setAdapter(androidx.recyclerview.widget.RecyclerView.Adapter?);
method public void setChildDrawingOrderCallback(androidx.recyclerview.widget.RecyclerView.ChildDrawingOrderCallback?);
+ method public static void setDebugAssertionsEnabled(boolean);
method public void setEdgeEffectFactory(androidx.recyclerview.widget.RecyclerView.EdgeEffectFactory);
method public void setHasFixedSize(boolean);
method public void setItemAnimator(androidx.recyclerview.widget.RecyclerView.ItemAnimator?);
@@ -483,6 +484,7 @@
method public void setRecycledViewPool(androidx.recyclerview.widget.RecyclerView.RecycledViewPool?);
method @Deprecated public void setRecyclerListener(androidx.recyclerview.widget.RecyclerView.RecyclerListener?);
method public void setScrollingTouchSlop(int);
+ method public static void setVerboseLoggingEnabled(boolean);
method public void setViewCacheExtension(androidx.recyclerview.widget.RecyclerView.ViewCacheExtension?);
method public void smoothScrollBy(@Px int, @Px int);
method public void smoothScrollBy(@Px int, @Px int, android.view.animation.Interpolator?);
diff --git a/recyclerview/recyclerview/api/restricted_current.txt b/recyclerview/recyclerview/api/restricted_current.txt
index 31a4f238..2b2bdad 100644
--- a/recyclerview/recyclerview/api/restricted_current.txt
+++ b/recyclerview/recyclerview/api/restricted_current.txt
@@ -470,6 +470,7 @@
method public void setAccessibilityDelegateCompat(androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate?);
method public void setAdapter(androidx.recyclerview.widget.RecyclerView.Adapter?);
method public void setChildDrawingOrderCallback(androidx.recyclerview.widget.RecyclerView.ChildDrawingOrderCallback?);
+ method public static void setDebugAssertionsEnabled(boolean);
method public void setEdgeEffectFactory(androidx.recyclerview.widget.RecyclerView.EdgeEffectFactory);
method public void setHasFixedSize(boolean);
method public void setItemAnimator(androidx.recyclerview.widget.RecyclerView.ItemAnimator?);
@@ -483,6 +484,7 @@
method public void setRecycledViewPool(androidx.recyclerview.widget.RecyclerView.RecycledViewPool?);
method @Deprecated public void setRecyclerListener(androidx.recyclerview.widget.RecyclerView.RecyclerListener?);
method public void setScrollingTouchSlop(int);
+ method public static void setVerboseLoggingEnabled(boolean);
method public void setViewCacheExtension(androidx.recyclerview.widget.RecyclerView.ViewCacheExtension?);
method public void smoothScrollBy(@Px int, @Px int);
method public void smoothScrollBy(@Px int, @Px int, android.view.animation.Interpolator?);
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GapWorker.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GapWorker.java
index b2d9f2e..5bbdcf1 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GapWorker.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GapWorker.java
@@ -157,7 +157,7 @@
}
public void add(RecyclerView recyclerView) {
- if (RecyclerView.DEBUG && mRecyclerViews.contains(recyclerView)) {
+ if (RecyclerView.sDebugAssertionsEnabled && mRecyclerViews.contains(recyclerView)) {
throw new IllegalStateException("RecyclerView already present in worker list!");
}
mRecyclerViews.add(recyclerView);
@@ -165,7 +165,7 @@
public void remove(RecyclerView recyclerView) {
boolean removeSuccess = mRecyclerViews.remove(recyclerView);
- if (RecyclerView.DEBUG && !removeSuccess) {
+ if (RecyclerView.sDebugAssertionsEnabled && !removeSuccess) {
throw new IllegalStateException("RecyclerView removal failed!");
}
}
@@ -175,7 +175,7 @@
*/
void postFromTraversal(RecyclerView recyclerView, int prefetchDx, int prefetchDy) {
if (recyclerView.isAttachedToWindow()) {
- if (RecyclerView.DEBUG && !mRecyclerViews.contains(recyclerView)) {
+ if (RecyclerView.sDebugAssertionsEnabled && !mRecyclerViews.contains(recyclerView)) {
throw new IllegalStateException("attempting to post unregistered view!");
}
if (mPostTimeNs == 0) {
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
index 149cc67..22e7245 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
@@ -219,7 +219,8 @@
static final String TAG = "RecyclerView";
- static final boolean DEBUG = false;
+ static boolean sDebugAssertionsEnabled = false;
+ static boolean sVerboseLoggingEnabled = false;
static final boolean VERBOSE_TRACING = false;
@@ -386,6 +387,35 @@
private static final Class<?>[] LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE =
new Class<?>[]{Context.class, AttributeSet.class, int.class, int.class};
+ /**
+ * Enable internal assertions about RecyclerView's state and throw exceptions if the
+ * assertions are violated.
+ * <p>
+ * This is primarily intended to diagnose problems with RecyclerView, and
+ * <strong>should not be enabled in production</strong> unless you have a specific reason to
+ * do so.
+ * <p>
+ * Enabling this may negatively affect performance and/or stability.
+ *
+ * @param debugAssertionsEnabled true to enable assertions; false to disable them
+ */
+ public static void setDebugAssertionsEnabled(boolean debugAssertionsEnabled) {
+ RecyclerView.sDebugAssertionsEnabled = debugAssertionsEnabled;
+ }
+
+ /**
+ * Enable verbose logging within RecyclerView itself.
+ * <p>
+ * Enabling this may negatively affect performance and reduce the utility of logcat due to
+ * high-volume logging. This generally <strong>should not be enabled in production</strong>
+ * unless you have a specific reason for doing so.
+ *
+ * @param verboseLoggingEnabled true to enable logging; false to disable it
+ */
+ public static void setVerboseLoggingEnabled(boolean verboseLoggingEnabled) {
+ RecyclerView.sVerboseLoggingEnabled = verboseLoggingEnabled;
+ }
+
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
final Recycler mRecycler = new Recycler();
@@ -983,7 +1013,7 @@
throw new IllegalArgumentException("Called attach on a child which is not"
+ " detached: " + vh + exceptionLabel());
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "reAttach " + vh);
}
vh.clearTmpDetachFlag();
@@ -1001,7 +1031,7 @@
throw new IllegalArgumentException("called detach on an already"
+ " detached child " + vh + exceptionLabel());
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "tmpDetach " + vh);
}
vh.addFlags(ViewHolder.FLAG_TMP_DETACHED);
@@ -1039,7 +1069,7 @@
// ensure it is not hidden because for adapter helper, the only thing matter is that
// LM thinks view is a child.
if (mChildHelper.isHidden(vh.itemView)) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "assuming view holder cannot be find because it is hidden");
}
return null;
@@ -1554,7 +1584,7 @@
final ViewHolder viewHolder = getChildViewHolderInt(view);
mRecycler.unscrapView(viewHolder);
mRecycler.recycleViewHolderInternal(viewHolder);
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "after removing animated view: " + view + ", " + this);
}
}
@@ -1638,7 +1668,7 @@
if (state == mScrollState) {
return;
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "setting scroll state to " + state + " from " + mScrollState,
new Exception());
}
@@ -2407,7 +2437,7 @@
void stopInterceptRequestLayout(boolean performLayoutChildren) {
if (mInterceptRequestLayoutDepth < 1) {
//noinspection PointlessBooleanExpression
- if (DEBUG) {
+ if (sDebugAssertionsEnabled) {
throw new IllegalStateException("stopInterceptRequestLayout was called more "
+ "times than startInterceptRequestLayout."
+ exceptionLabel());
@@ -4105,7 +4135,7 @@
void onExitLayoutOrScroll(boolean enableChangeEvents) {
mLayoutOrScrollCounter--;
if (mLayoutOrScrollCounter < 1) {
- if (DEBUG && mLayoutOrScrollCounter < 0) {
+ if (sDebugAssertionsEnabled && mLayoutOrScrollCounter < 0) {
throw new IllegalStateException("layout or scroll counter cannot go below zero."
+ "Some calls are not matching" + exceptionLabel());
}
@@ -5015,7 +5045,7 @@
final int childCount = mChildHelper.getUnfilteredChildCount();
for (int i = 0; i < childCount; i++) {
final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
- if (DEBUG && holder.mPosition == -1 && !holder.isRemoved()) {
+ if (sDebugAssertionsEnabled && holder.mPosition == -1 && !holder.isRemoved()) {
throw new IllegalStateException("view holder cannot have position -1 unless it"
+ " is removed" + exceptionLabel());
}
@@ -5054,7 +5084,7 @@
if (holder == null || holder.mPosition < start || holder.mPosition > end) {
continue;
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForMove attached child " + i + " holder "
+ holder);
}
@@ -5075,7 +5105,7 @@
for (int i = 0; i < childCount; i++) {
final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
if (holder != null && !holder.shouldIgnore() && holder.mPosition >= positionStart) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForInsert attached child " + i + " holder "
+ holder + " now at position " + (holder.mPosition + itemCount));
}
@@ -5095,7 +5125,7 @@
final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
if (holder != null && !holder.shouldIgnore()) {
if (holder.mPosition >= positionEnd) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForRemove attached child " + i
+ " holder " + holder + " now at position "
+ (holder.mPosition - itemCount));
@@ -5103,7 +5133,7 @@
holder.offsetPosition(-itemCount, applyToPreLayout);
mState.mStructureChanged = true;
} else if (holder.mPosition >= positionStart) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForRemove attached child " + i
+ " holder " + holder + " now REMOVED");
}
@@ -6284,7 +6314,7 @@
PoolingContainer.callPoolingContainerOnRelease(scrap.itemView);
return;
}
- if (DEBUG && scrapHeap.contains(scrap)) {
+ if (sDebugAssertionsEnabled && scrapHeap.contains(scrap)) {
throw new IllegalArgumentException("this scrap item already exists");
}
scrap.resetInternal();
@@ -6539,7 +6569,7 @@
// if it is a removed holder, nothing to verify since we cannot ask adapter anymore
// if it is not removed, verify the type and id.
if (holder.isRemoved()) {
- if (DEBUG && !mState.isPreLayout()) {
+ if (sDebugAssertionsEnabled && !mState.isPreLayout()) {
throw new IllegalStateException("should not receive a removed view unless it"
+ " is pre layout" + exceptionLabel());
}
@@ -6788,7 +6818,7 @@
}
}
if (holder == null) { // fallback to pool
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "tryGetViewHolderForPositionByDeadline("
+ position + ") fetching from shared pool");
}
@@ -6818,7 +6848,7 @@
long end = getNanoTime();
mRecyclerPool.factorInCreateTime(type, end - start);
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "tryGetViewHolderForPositionByDeadline created new ViewHolder");
}
}
@@ -6845,7 +6875,7 @@
// do not update unless we absolutely have to.
holder.mPreLayoutPosition = position;
} else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
- if (DEBUG && holder.isRemoved()) {
+ if (sDebugAssertionsEnabled && holder.isRemoved()) {
throw new IllegalStateException("Removed holder should be bound and it should"
+ " come here only in pre-layout. Holder: " + holder
+ exceptionLabel());
@@ -6984,11 +7014,11 @@
* @param cachedViewIndex The index of the view in cached views list
*/
void recycleCachedViewAt(int cachedViewIndex) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "Recycling cached view at index " + cachedViewIndex);
}
ViewHolder viewHolder = mCachedViews.get(cachedViewIndex);
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "CachedViewHolder to be recycled: " + viewHolder);
}
addViewHolderToRecycledViewPool(viewHolder, true);
@@ -7026,7 +7056,7 @@
&& mAdapter.onFailedToRecycleView(holder);
boolean cached = false;
boolean recycled = false;
- if (DEBUG && mCachedViews.contains(holder)) {
+ if (sDebugAssertionsEnabled && mCachedViews.contains(holder)) {
throw new IllegalArgumentException("cached view received recycle internal? "
+ holder + exceptionLabel());
}
@@ -7072,7 +7102,7 @@
// TODO: consider cancelling an animation when an item is removed scrollBy,
// to return it to the pool faster
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "trying to recycle a non-recycleable holder. Hopefully, it will "
+ "re-visit here. We are still removing it from animation lists"
+ exceptionLabel());
@@ -7274,7 +7304,7 @@
if (!dryRun) {
mCachedViews.remove(i);
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "getScrapOrHiddenOrCachedHolderForPosition(" + position
+ ") found match in cache: " + holder);
}
@@ -7354,7 +7384,7 @@
if (mState != null) {
mViewInfoStore.removeViewHolder(holder);
}
- if (DEBUG) Log.d(TAG, "dispatchViewRecycled: " + holder);
+ if (sVerboseLoggingEnabled) Log.d(TAG, "dispatchViewRecycled: " + holder);
}
void onAdapterChanged(Adapter<?> oldAdapter, Adapter<?> newAdapter,
@@ -7388,7 +7418,7 @@
} else {
holder.offsetPosition(inBetweenOffset, false);
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForMove cached child " + i + " holder "
+ holder);
}
@@ -7400,7 +7430,7 @@
for (int i = 0; i < cachedCount; i++) {
final ViewHolder holder = mCachedViews.get(i);
if (holder != null && holder.mPosition >= insertedAt) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForInsert cached " + i + " holder "
+ holder + " now at position " + (holder.mPosition + count));
}
@@ -7423,7 +7453,7 @@
final ViewHolder holder = mCachedViews.get(i);
if (holder != null) {
if (holder.mPosition >= removedEnd) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "offsetPositionRecordsForRemove cached " + i
+ " holder " + holder + " now at position "
+ (holder.mPosition - count));
@@ -9173,7 +9203,7 @@
* @param position Scroll to this adapter position.
*/
public void scrollToPosition(int position) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.e(TAG, "You MUST implement scrollToPosition. It will soon become abstract");
}
}
@@ -9354,7 +9384,7 @@
}
}
if (lp.mPendingInvalidate) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "consuming pending invalidate on child " + lp.mViewHolder);
}
holder.itemView.invalidate();
@@ -9946,7 +9976,7 @@
private void scrapOrRecycleView(Recycler recycler, int index, View view) {
final ViewHolder viewHolder = getChildViewHolderInt(view);
if (viewHolder.shouldIgnore()) {
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "ignoring view " + viewHolder);
}
return;
@@ -12246,7 +12276,7 @@
mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1;
if (mIsRecyclableCount < 0) {
mIsRecyclableCount = 0;
- if (DEBUG) {
+ if (sDebugAssertionsEnabled) {
throw new RuntimeException("isRecyclable decremented below 0: "
+ "unmatched pair of setIsRecyable() calls for " + this);
}
@@ -12257,7 +12287,7 @@
} else if (recyclable && mIsRecyclableCount == 0) {
mFlags &= ~FLAG_NOT_RECYCLABLE;
}
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "setIsRecyclable val:" + recyclable + ":" + this);
}
}
@@ -12852,7 +12882,7 @@
protected void onChildAttachedToWindow(View child) {
if (getChildPosition(child) == getTargetPosition()) {
mTargetView = child;
- if (DEBUG) {
+ if (sVerboseLoggingEnabled) {
Log.d(TAG, "smooth scroll target view has been attached");
}
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
index b1a65c0..9ad98bf 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
@@ -29,7 +29,7 @@
* @see javax.lang.model.type.TypeMirror
* @see [XArrayType]
*/
-interface XType {
+interface XType : XAnnotated {
/**
* The Javapoet [TypeName] representation of the type
*/
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotation.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotation.kt
new file mode 100644
index 0000000..ac2d325
--- /dev/null
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotation.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2023 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.room.compiler.processing.javac
+
+import androidx.room.compiler.processing.InternalXAnnotation
+import androidx.room.compiler.processing.XAnnotationBox
+import androidx.room.compiler.processing.XAnnotationValue
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.javac.kotlin.KmAnnotationContainer
+
+internal class JavacKmAnnotation(
+ private val env: JavacProcessingEnv,
+ private val kmAnnotation: KmAnnotationContainer
+) : InternalXAnnotation() {
+ override fun <T : Annotation> asAnnotationBox(annotationClass: Class<T>): XAnnotationBox<T> {
+ throw UnsupportedOperationException("No plan to support XAnnotationBox.")
+ }
+
+ override val name: String
+ get() = typeElement.name
+
+ override val qualifiedName: String
+ get() = typeElement.qualifiedName
+
+ override val typeElement: JavacTypeElement by lazy {
+ requireNotNull(env.findTypeElement(kmAnnotation.className))
+ }
+
+ override val type: XType
+ get() = typeElement.type
+
+ override val annotationValues: List<XAnnotationValue> by lazy {
+ val methods = typeElement.getDeclaredMethods()
+ methods.map { method ->
+ JavacKmAnnotationValue(
+ method = method,
+ kmAnnotationArgumentContainer =
+ kmAnnotation.getArguments(env).getValue(method.jvmName)
+ )
+ }
+ }
+}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotationValue.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotationValue.kt
new file mode 100644
index 0000000..c100d0b
--- /dev/null
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacKmAnnotationValue.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.room.compiler.processing.javac
+
+import androidx.room.compiler.processing.InternalXAnnotationValue
+import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.javac.kotlin.KmAnnotationArgumentContainer
+
+internal class JavacKmAnnotationValue(
+ private val method: XMethodElement,
+ override val valueType: XType = method.returnType,
+ private val kmAnnotationArgumentContainer: KmAnnotationArgumentContainer
+) : InternalXAnnotationValue() {
+ override val name: String = method.jvmName
+ override val value: Any? by lazy {
+ kmAnnotationArgumentContainer.getValue(method)
+ }
+}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
index 3dd55ea..89420be 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
@@ -17,6 +17,9 @@
package androidx.room.compiler.processing.javac
import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.processing.InternalXAnnotated
+import androidx.room.compiler.processing.XAnnotation
+import androidx.room.compiler.processing.XAnnotationBox
import androidx.room.compiler.processing.XEquality
import androidx.room.compiler.processing.XNullability
import androidx.room.compiler.processing.XRawType
@@ -25,6 +28,8 @@
import androidx.room.compiler.processing.javac.kotlin.KmTypeContainer
import androidx.room.compiler.processing.ksp.ERROR_JTYPE_NAME
import androidx.room.compiler.processing.safeTypeName
+import androidx.room.compiler.processing.unwrapRepeatedAnnotationsFromContainer
+import com.google.auto.common.MoreElements
import com.google.auto.common.MoreTypes
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
@@ -34,7 +39,8 @@
internal val env: JavacProcessingEnv,
open val typeMirror: TypeMirror,
internal val maybeNullability: XNullability?,
-) : XType, XEquality {
+) : XType, XEquality, InternalXAnnotated {
+
// Kotlin type information about the type if this type is driven from Kotlin code.
abstract val kotlinType: KmTypeContainer?
@@ -85,6 +91,37 @@
override fun asTypeName() = xTypeName
+ override fun <T : Annotation> getAnnotations(
+ annotation: KClass<T>,
+ containerAnnotation: KClass<out Annotation>?
+ ): List<XAnnotationBox<T>> {
+ throw UnsupportedOperationException("No plan to support XAnnotationBox.")
+ }
+
+ override fun hasAnnotation(
+ annotation: KClass<out Annotation>,
+ containerAnnotation: KClass<out Annotation>?
+ ): Boolean {
+ val annotationClassName: String = annotation.java.canonicalName!!
+ return getAllAnnotations().any { it.qualifiedName == annotationClassName }
+ }
+
+ override fun getAllAnnotations(): List<XAnnotation> {
+ return kotlinType?.annotations?.map {
+ JavacKmAnnotation(env, it)
+ } ?: typeMirror.annotationMirrors.map { mirror -> JavacAnnotation(env, mirror) }
+ .flatMap { annotation ->
+ annotation.unwrapRepeatedAnnotationsFromContainer() ?: listOf(annotation)
+ }
+ }
+
+ override fun hasAnnotationWithPackage(pkg: String): Boolean {
+ return getAllAnnotations().any {
+ val element = (it.typeElement as JavacTypeElement).element
+ MoreElements.getPackage(element).toString() == pkg
+ }
+ }
+
override fun equals(other: Any?): Boolean {
return XEquality.equals(this, other)
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
index 5b09016..1029947 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
@@ -37,6 +37,7 @@
import com.squareup.kotlinpoet.javapoet.JClassName
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
+import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind
import javax.lang.model.util.ElementFilter
@@ -218,11 +219,15 @@
}
override val superInterfaces by lazy {
+ val superTypesFromKotlinMetadata = kotlinMetadata?.superTypes
+ ?.associateBy { it.className } ?: emptyMap()
element.interfaces.map {
+ check(it is DeclaredType)
+ val interfaceName = ClassName.get(MoreElements.asType(it.asElement()))
val element = MoreTypes.asTypeElement(it)
env.wrap<JavacType>(
typeMirror = it,
- kotlinType = KmClassContainer.createFor(env, element)?.type,
+ kotlinType = superTypesFromKotlinMetadata[interfaceName.canonicalName()],
elementNullability = element.nullability
)
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
index fdf221a..9e8131c 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
@@ -16,7 +16,12 @@
package androidx.room.compiler.processing.javac.kotlin
+import androidx.room.compiler.processing.XArrayType
+import androidx.room.compiler.processing.XEnumTypeElement
+import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XNullability
+import androidx.room.compiler.processing.javac.JavacKmAnnotation
+import androidx.room.compiler.processing.javac.JavacKmAnnotationValue
import androidx.room.compiler.processing.javac.JavacProcessingEnv
import androidx.room.compiler.processing.util.sanitizeAsJavaParameterName
import javax.lang.model.element.Element
@@ -25,7 +30,10 @@
import javax.tools.Diagnostic
import kotlinx.metadata.Flag
import kotlinx.metadata.Flags
+import kotlinx.metadata.KmAnnotation
+import kotlinx.metadata.KmAnnotationArgument
import kotlinx.metadata.KmClass
+import kotlinx.metadata.KmClassifier
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmFunction
import kotlinx.metadata.KmProperty
@@ -50,10 +58,14 @@
val type: KmTypeContainer by lazy {
KmTypeContainer(
- kmType = KmType(flags),
+ kmType = KmType(flags).apply {
+ classifier = KmClassifier.Class(kmClass.name)
+ },
typeArguments = kmClass.typeParameters.map { kmTypeParameter ->
KmTypeContainer(
- kmType = KmType(kmTypeParameter.flags),
+ kmType = KmType(kmTypeParameter.flags).apply {
+ classifier = KmClassifier.Class(kmTypeParameter.name)
+ },
typeArguments = emptyList(),
upperBounds = kmTypeParameter.upperBounds.map { it.asContainer() }
)
@@ -65,6 +77,10 @@
kmClass.supertypes.firstOrNull()?.asContainer()
}
+ val superTypes: List<KmTypeContainer> by lazy {
+ kmClass.supertypes.map { it.asContainer() }
+ }
+
val typeParameters: List<KmTypeParameterContainer> by lazy {
kmClass.typeParameters.map { it.asContainer() }
}
@@ -265,6 +281,16 @@
) : KmFlags {
override val flags: Flags
get() = kmType.flags
+
+ val className: String? = kmType.classifier.let {
+ when (it) {
+ is KmClassifier.Class -> it.name.replace('/', '.')
+ else -> null
+ }
+ }
+
+ val annotations = kmType.annotations.map { it.asContainer() }
+
fun isExtensionType() =
kmType.annotations.any { it.className == "kotlin/ExtensionFunctionType" }
fun isNullable() = Flag.Type.IS_NULLABLE(flags)
@@ -278,6 +304,49 @@
)
}
+internal class KmAnnotationContainer(private val kmAnnotation: KmAnnotation) {
+ val className = kmAnnotation.className.replace('/', '.')
+ fun getArguments(env: JavacProcessingEnv): Map<String, KmAnnotationArgumentContainer> {
+ return kmAnnotation.arguments.mapValues { (_, arg) ->
+ arg.asContainer(env)
+ }
+ }
+}
+
+internal class KmAnnotationArgumentContainer(
+ private val env: JavacProcessingEnv,
+ private val kmAnnotationArgument: KmAnnotationArgument
+) {
+ fun getValue(method: XMethodElement): Any? {
+ return kmAnnotationArgument.let {
+ when (it) {
+ is KmAnnotationArgument.LiteralValue<*> -> it.value
+ is KmAnnotationArgument.ArrayValue -> {
+ it.elements.map {
+ val valueType = (method.returnType as XArrayType).componentType
+ JavacKmAnnotationValue(method, valueType, it.asContainer(env))
+ }
+ }
+ is KmAnnotationArgument.EnumValue -> {
+ val enumTypeElement = env.findTypeElement(
+ it.enumClassName.replace('/', '.')) as XEnumTypeElement
+ enumTypeElement.entries.associateBy { it.name }[it.enumEntryName]
+ }
+ is KmAnnotationArgument.AnnotationValue -> {
+ val kmAnnotation = KmAnnotation(
+ it.annotation.className,
+ it.annotation.arguments
+ ).asContainer()
+ JavacKmAnnotation(env, kmAnnotation)
+ }
+ is KmAnnotationArgument.KClassValue -> {
+ env.requireType(it.className.replace('/', '.'))
+ }
+ }
+ }
+ }
+}
+
internal val KmTypeContainer.nullability: XNullability
get() = if (isNullable()) {
XNullability.NULLABLE
@@ -346,13 +415,14 @@
// it here since it is not valid name
name = "set-?".sanitizeAsJavaParameterName(0)
).apply { type = [email protected] }
+ val returnType = KmType(0).apply { classifier = KmClassifier.Class("Unit") }
KmPropertyFunctionContainerImpl(
flags = this.setterFlags,
name = JvmAbi.computeSetterName(this.name),
jvmName = it.name,
descriptor = it.asString(),
parameters = listOf(param.asContainer()),
- returnType = KmType(0).asContainer(),
+ returnType = returnType.asContainer(),
)
},
)
@@ -373,4 +443,9 @@
KmValueParameterContainer(
kmValueParameter = this,
type = this.type.asContainer()
- )
\ No newline at end of file
+ )
+
+private fun KmAnnotation.asContainer() = KmAnnotationContainer(this)
+
+private fun KmAnnotationArgument.asContainer(env: JavacProcessingEnv) =
+ KmAnnotationArgumentContainer(env, this)
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
index 1080617..4039290 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
@@ -72,7 +72,7 @@
override fun hasAnnotationWithPackage(pkg: String): Boolean {
return annotations().any {
- it.annotationType.resolve().declaration.qualifiedName?.getQualifier() == pkg
+ it.annotationType.resolve().declaration.packageName.asString() == pkg
}
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotation.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotation.kt
index 51a0c6e..4e48afc 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotation.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotation.kt
@@ -28,7 +28,9 @@
val ksAnnotated: KSAnnotation
) : InternalXAnnotation() {
- val ksType: KSType by lazy { ksAnnotated.annotationType.resolve() }
+ val ksType: KSType by lazy {
+ ksAnnotated.annotationType.resolve()
+ }
override val name: String
get() = ksAnnotated.shortName.asString()
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index b0d03e1..d6b75dd 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -24,6 +24,7 @@
import androidx.room.compiler.processing.tryBox
import androidx.room.compiler.processing.tryUnbox
import com.google.devtools.ksp.KspExperimental
+import com.google.devtools.ksp.symbol.KSAnnotation
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.symbol.KSTypeArgument
@@ -46,13 +47,13 @@
* Similarly, we may not be able to get a [KSType] (e.g. if it resolves to error).
*/
internal abstract class KspType(
- val env: KspProcessingEnv,
+ env: KspProcessingEnv,
val ksType: KSType,
/**
* Type resolver to convert KSType into its JVM representation.
*/
protected val jvmTypeResolver: KspJvmTypeResolver?
-) : XType, XEquality {
+) : KspAnnotated(env), XType, XEquality {
override val rawType by lazy {
KspRawType(this)
}
@@ -213,6 +214,8 @@
}
}
+ override fun annotations(): Sequence<KSAnnotation> = ksType.annotations
+
override fun isNone(): Boolean {
// even void is converted to Unit so we don't have none type in KSP
// see: KspTypeTest.noneType
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
index d96e81d..2b79b8b 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationTest.kt
@@ -1106,6 +1106,158 @@
}
}
+ @Test
+ fun typeAnnotations() {
+ val kotlinSource = Source.kotlin(
+ "foo.bar.Subject.kt",
+ """
+ package foo.bar
+
+ interface MyInterface
+ open class Base
+
+ @Target(AnnotationTarget.TYPE)
+ annotation class A
+
+ class Subject(i: @A MyInterface) : @A Base(), @A MyInterface {
+ val p: @A MyInterface = TODO()
+ fun f(a: @A MyInterface): @A MyInterface = TODO()
+ }
+ """.trimIndent()
+ )
+ val javaSource = Source.java(
+ "foo.bar.Subject.java",
+ """
+ package foo.bar;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ import java.lang.annotation.Repeatable;
+
+ interface MyInterface {}
+ class Base {}
+
+ @Target(ElementType.TYPE_USE)
+ @interface A {}
+
+ class Subject extends @A Base implements @A MyInterface {
+ Subject(@A MyInterface i) {}
+ @A MyInterface p;
+ @A MyInterface f(@A MyInterface a) {
+ throw new RuntimeException();
+ }
+ }
+ """.trimIndent()
+ )
+
+ listOf(javaSource, kotlinSource).forEach { source ->
+ runTest(
+ sources = listOf(source)
+ ) { invocation ->
+ // We can't see type annotations from precompiled Java classes. Skipping it for now:
+ // https://github.com/google/ksp/issues/1296
+ if (source == javaSource && preCompiled) {
+ return@runTest
+ }
+ val subject = invocation.processingEnv.requireTypeElement("foo.bar.Subject")
+ // There's an issue in KSP that prevents us from getting type annotations in
+ // places other than supertypes: https://github.com/google/ksp/issues/1325
+ val annotations = if (invocation.isKsp) {
+ listOf(
+ subject.superClass!!.getAllAnnotations().first(),
+ subject.superInterfaces.first().getAllAnnotations().first(),
+ )
+ } else {
+ listOf(
+ subject.superClass!!.getAllAnnotations().first(),
+ subject.superInterfaces.first().getAllAnnotations().first(),
+ subject.getDeclaredField("p").type.getAllAnnotations().first(),
+ subject.getConstructors().first().parameters.first().type
+ .getAllAnnotations().first(),
+ subject.getMethodByJvmName("f").returnType
+ .getAllAnnotations().first(),
+ subject.getMethodByJvmName("f").parameters.first().type
+ .getAllAnnotations().first()
+ )
+ }
+ annotations.forEach { annotation ->
+ assertThat(annotation.qualifiedName).isEqualTo("foo.bar.A")
+ }
+ assertThat(subject.superClass!!.hasAnnotationWithPackage("foo.bar")).isTrue()
+ subject.superInterfaces.forEach {
+ assertThat(it.hasAnnotationWithPackage("foo.bar")).isTrue()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun repeatedTypeAnnotations() {
+ val kotlinSource = Source.kotlin(
+ "foo.bar.Subject.kt",
+ """
+ package foo.bar
+
+ @Target(AnnotationTarget.TYPE)
+ @Repeatable
+ annotation class A(val value: Int)
+
+ open class Base
+
+ class Subject : @A(0) @A(1) Base()
+ """.trimIndent()
+ )
+ val javaSource = Source.java(
+ "foo.bar.Subject.java",
+ """
+ package foo.bar;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ import java.lang.annotation.Repeatable;
+
+ class Base {}
+
+ @Repeatable(AContainer.class)
+ @Target(ElementType.TYPE_USE)
+ @interface A {
+ int value();
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @interface AContainer {
+ A[] value();
+ }
+
+ class Subject extends @A(0) @A(1) Base {}
+ """.trimIndent()
+ )
+
+ listOf(javaSource, kotlinSource).forEach { source ->
+ runTest(
+ sources = listOf(source)
+ ) { invocation ->
+ // We can't see type annotations from precompiled Java classes. Skipping it for now:
+ // https://github.com/google/ksp/issues/1296
+ if (source == javaSource && preCompiled) {
+ return@runTest
+ }
+ val subject = invocation.processingEnv.requireTypeElement("foo.bar.Subject")
+ val base = subject.superClass!!
+ assertThat(base.getAllAnnotations()[0].name)
+ .isEqualTo("A")
+ assertThat(base.getAllAnnotations()[0].qualifiedName)
+ .isEqualTo("foo.bar.A")
+ assertThat(base.getAllAnnotations()[0].annotationValues.first().asInt())
+ .isEqualTo(0)
+ assertThat(base.getAllAnnotations()[1].name)
+ .isEqualTo("A")
+ assertThat(base.getAllAnnotations()[1].qualifiedName)
+ .isEqualTo("foo.bar.A")
+ assertThat(base.getAllAnnotations()[1].annotationValues.first().asInt())
+ .isEqualTo(1)
+ }
+ }
+ }
+
// helper function to read what we need
private fun XAnnotated.getSuppressValues(): List<String>? {
return this.findAnnotation<TestSuppressWarnings>()
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
index 3d05e0b..0ca863f 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationValueTest.kt
@@ -57,6 +57,7 @@
class XAnnotationValueTest(
private val isPreCompiled: Boolean,
private val sourceKind: SourceKind,
+ private val isTypeAnnotation: Boolean,
) {
private fun runTest(
javaSource: Source.JavaSource,
@@ -104,34 +105,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
boolean booleanParam();
boolean[] booleanArrayParam();
boolean[] booleanVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
booleanParam = true,
booleanArrayParam = {true, false, true},
booleanVarArgsParam = {false, true, false}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ booleanParam = true,
+ booleanArrayParam = {true, false, true},
+ booleanVarArgsParam = {false, true, false}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val booleanParam: Boolean,
val booleanArrayParam: BooleanArray,
vararg val booleanVarArgsParam: Boolean,
)
+ interface MyInterface
@MyAnnotation(
booleanParam = true,
booleanArrayParam = [true, false, true],
booleanVarArgsParam = [false, true, false],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ booleanParam = true,
+ booleanArrayParam = [true, false, true],
+ booleanVarArgsParam = [false, true, false],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -161,11 +180,7 @@
checkSingleValue(value, expectedValues[i])
}
}
-
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -194,34 +209,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
int intParam();
int[] intArrayParam();
int[] intVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
intParam = (short) 1,
intArrayParam = {(byte) 3, (short) 5, 7},
intVarArgsParam = {(byte) 9, (short) 11, 13}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ intParam = (short) 1,
+ intArrayParam = {(byte) 3, (short) 5, 7},
+ intVarArgsParam = {(byte) 9, (short) 11, 13}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val intParam: Int,
val intArrayParam: IntArray,
vararg val intVarArgsParam: Int,
)
+ interface MyInterface
@MyAnnotation(
intParam = 1,
intArrayParam = [3, 5, 7],
intVarArgsParam = [9, 11, 13],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ intParam = 1,
+ intArrayParam = [3, 5, 7],
+ intVarArgsParam = [9, 11, 13],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -252,10 +285,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -284,34 +314,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
short shortParam();
short[] shortArrayParam();
short[] shortVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
shortParam = (byte) 1,
shortArrayParam = {(byte) 3, (short) 5, 7},
shortVarArgsParam = {(byte) 9, (short) 11, 13}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ shortParam = (byte) 1,
+ shortArrayParam = {(byte) 3, (short) 5, 7},
+ shortVarArgsParam = {(byte) 9, (short) 11, 13}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val shortParam: Short,
val shortArrayParam: ShortArray,
vararg val shortVarArgsParam: Short,
)
+ interface MyInterface
@MyAnnotation(
shortParam = 1,
shortArrayParam = [3, 5, 7],
shortVarArgsParam = [9, 11, 13],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ shortParam = 1,
+ shortArrayParam = [3, 5, 7],
+ shortVarArgsParam = [9, 11, 13],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -342,10 +390,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -374,34 +419,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
long longParam();
long[] longArrayParam();
long[] longVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
longParam = (byte) 1,
longArrayParam = {(short) 3, (int) 5, 7L},
longVarArgsParam = {(short) 9, (int) 11, 13L}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ longParam = (byte) 1,
+ longArrayParam = {(short) 3, (int) 5, 7L},
+ longVarArgsParam = {(short) 9, (int) 11, 13L}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val longParam: Long,
val longArrayParam: LongArray,
vararg val longVarArgsParam: Long,
)
+ interface MyInterface
@MyAnnotation(
longParam = 1L,
longArrayParam = [3L, 5L, 7L],
longVarArgsParam = [9L, 11L, 13L],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ longParam = 1L,
+ longArrayParam = [3L, 5L, 7L],
+ longVarArgsParam = [9L, 11L, 13L],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -432,10 +495,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -464,34 +524,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
float floatParam();
float[] floatArrayParam();
float[] floatVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
floatParam = (byte) 1,
floatArrayParam = {(short) 3, 5.1F, 7.1F},
floatVarArgsParam = {9, 11.1F, 13.1F}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ floatParam = (byte) 1,
+ floatArrayParam = {(short) 3, 5.1F, 7.1F},
+ floatVarArgsParam = {9, 11.1F, 13.1F}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val floatParam: Float,
val floatArrayParam: FloatArray,
vararg val floatVarArgsParam: Float,
)
+ interface MyInterface
@MyAnnotation(
floatParam = 1F,
floatArrayParam = [3F, 5.1F, 7.1F],
floatVarArgsParam = [9F, 11.1F, 13.1F],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ floatParam = 1F,
+ floatArrayParam = [3F, 5.1F, 7.1F],
+ floatVarArgsParam = [9F, 11.1F, 13.1F],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -522,10 +600,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -554,34 +629,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
double doubleParam();
double[] doubleArrayParam();
double[] doubleVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
doubleParam = (byte) 1,
doubleArrayParam = {(short) 3, 5.1F, 7.1},
doubleVarArgsParam = {9, 11.1F, 13.1}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ doubleParam = (byte) 1,
+ doubleArrayParam = {(short) 3, 5.1F, 7.1},
+ doubleVarArgsParam = {9, 11.1F, 13.1}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val doubleParam: Double,
val doubleArrayParam: DoubleArray,
vararg val doubleVarArgsParam: Double,
)
+ interface MyInterface
@MyAnnotation(
doubleParam = 1.0,
doubleArrayParam = [3.0, 5.1, 7.1],
doubleVarArgsParam = [9.0, 11.1, 13.1],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ doubleParam = 1.0,
+ doubleArrayParam = [3.0, 5.1, 7.1],
+ doubleVarArgsParam = [9.0, 11.1, 13.1],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -612,9 +705,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
+ val annotation = getAnnotation(invocation)
annotation.getAnnotationValue("doubleParam").value
annotation.getAnnotationValue("doubleArrayParam").value
annotation.getAnnotationValue("doubleVarArgsParam").value
@@ -676,34 +767,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
byte byteParam();
byte[] byteArrayParam();
byte[] byteVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
byteParam = (byte) 1,
byteArrayParam = {(byte) 3, (byte) 5, (byte) 7},
byteVarArgsParam = {(byte) 9, (byte) 11, (byte) 13}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ byteParam = (byte) 1,
+ byteArrayParam = {(byte) 3, (byte) 5, (byte) 7},
+ byteVarArgsParam = {(byte) 9, (byte) 11, (byte) 13}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val byteParam: Byte,
val byteArrayParam: ByteArray,
vararg val byteVarArgsParam: Byte,
)
+ interface MyInterface
@MyAnnotation(
byteParam = 1,
byteArrayParam = [3, 5, 7],
byteVarArgsParam = [9, 11, 13],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ byteParam = 1,
+ byteArrayParam = [3, 5, 7],
+ byteVarArgsParam = [9, 11, 13],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -734,10 +843,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -766,34 +872,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
char charParam();
char[] charArrayParam();
char[] charVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
charParam = '1',
charArrayParam = {'2', '3', '4'},
charVarArgsParam = {'5', '6', '7'}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ charParam = '1',
+ charArrayParam = {'2', '3', '4'},
+ charVarArgsParam = {'5', '6', '7'}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val charParam: Char,
val charArrayParam: CharArray,
vararg val charVarArgsParam: Char,
)
+ interface MyInterface
@MyAnnotation(
charParam = '1',
charArrayParam = ['2', '3', '4'],
charVarArgsParam = ['5', '6', '7'],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ charParam = '1',
+ charArrayParam = ['2', '3', '4'],
+ charVarArgsParam = ['5', '6', '7'],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -824,10 +948,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -856,34 +977,52 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
String stringParam();
String[] stringArrayParam();
String[] stringVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
stringParam = "1",
stringArrayParam = {"3", "5", "7"},
stringVarArgsParam = {"9", "11", "13"}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ stringParam = "1",
+ stringArrayParam = {"3", "5", "7"},
+ stringVarArgsParam = {"9", "11", "13"}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
"test.MyClass.kt",
"""
package test
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val stringParam: String,
val stringArrayParam: Array<String>,
vararg val stringVarArgsParam: String,
)
+ interface MyInterface
@MyAnnotation(
stringParam = "1",
stringArrayParam = ["3", "5", "7"],
stringVarArgsParam = ["9", "11", "13"],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ stringParam = "1",
+ stringArrayParam = ["3", "5", "7"],
+ stringVarArgsParam = ["9", "11", "13"],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -925,10 +1064,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -957,18 +1093,28 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
enum MyEnum {V1, V2, V3}
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
MyEnum enumParam();
MyEnum[] enumArrayParam();
MyEnum[] enumVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
enumParam = MyEnum.V1,
enumArrayParam = {MyEnum.V1, MyEnum.V2, MyEnum.V3},
enumVarArgsParam = {MyEnum.V3, MyEnum.V2, MyEnum.V1}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ enumParam = MyEnum.V1,
+ enumArrayParam = {MyEnum.V1, MyEnum.V2, MyEnum.V3},
+ enumVarArgsParam = {MyEnum.V3, MyEnum.V2, MyEnum.V1}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
@@ -976,17 +1122,25 @@
"""
package test
enum class MyEnum {V1, V2, V3}
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val enumParam: MyEnum,
val enumArrayParam: Array<MyEnum>,
vararg val enumVarArgsParam: MyEnum,
)
+ interface MyInterface
@MyAnnotation(
enumParam = MyEnum.V1,
enumArrayParam = [MyEnum.V1, MyEnum.V2, MyEnum.V3],
enumVarArgsParam = [MyEnum.V3, MyEnum.V2, MyEnum.V1],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ enumParam = MyEnum.V1,
+ enumArrayParam = [MyEnum.V1, MyEnum.V2, MyEnum.V3],
+ enumVarArgsParam = [MyEnum.V3, MyEnum.V2, MyEnum.V1],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -1031,10 +1185,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@test.MyAnnotation(
@@ -1062,20 +1213,30 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
class C1 {}
class C2 {}
class C3 {}
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
Class<?> typeParam();
Class<?>[] typeArrayParam();
Class<?>[] typeVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
typeParam = C1.class,
typeArrayParam = {C1.class, C2.class, C3.class},
typeVarArgsParam = {C3.class, C2.class, C1.class}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ typeParam = C1.class,
+ typeArrayParam = {C1.class, C2.class, C3.class},
+ typeVarArgsParam = {C3.class, C2.class, C1.class}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
@@ -1085,17 +1246,25 @@
class C1
class C2
class C3
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val typeParam: kotlin.reflect.KClass<*>,
val typeArrayParam: Array<kotlin.reflect.KClass<*>>,
vararg val typeVarArgsParam: kotlin.reflect.KClass<*>,
)
+ interface MyInterface
@MyAnnotation(
typeParam = C1::class,
typeArrayParam = [C1::class, C2::class, C3::class],
typeVarArgsParam = [C3::class, C2::class, C1::class],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ typeParam = C1::class,
+ typeArrayParam = [C1::class, C2::class, C3::class],
+ typeVarArgsParam = [C3::class, C2::class, C1::class],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -1154,10 +1323,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -1186,20 +1352,30 @@
"test.MyClass",
"""
package test;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
@interface A {
String value();
}
+ @Target({ElementType.TYPE, ElementType.TYPE_USE})
@interface MyAnnotation {
A annotationParam();
A[] annotationArrayParam();
A[] annotationVarArgsParam(); // There's no varargs in java so use array
}
+ interface MyInterface {}
@MyAnnotation(
annotationParam = @A("1"),
annotationArrayParam = {@A("3"), @A("5"), @A("7")},
annotationVarArgsParam = {@A("9"), @A("11"), @A("13")}
)
- class MyClass {}
+ class MyClass implements
+ @MyAnnotation(
+ annotationParam = @A("1"),
+ annotationArrayParam = {@A("3"), @A("5"), @A("7")},
+ annotationVarArgsParam = {@A("9"), @A("11"), @A("13")}
+ )
+ MyInterface {}
""".trimIndent()
) as Source.JavaSource,
kotlinSource = Source.kotlin(
@@ -1207,17 +1383,25 @@
"""
package test
annotation class A(val value: String)
+ @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class MyAnnotation(
val annotationParam: A,
val annotationArrayParam: Array<A>,
vararg val annotationVarArgsParam: A,
)
+ interface MyInterface
@MyAnnotation(
annotationParam = A("1"),
annotationArrayParam = [A("3"), A("5"), A("7")],
annotationVarArgsParam = [A("9"), A("11"), A("13")],
)
- class MyClass
+ class MyClass :
+ @MyAnnotation(
+ annotationParam = A("1"),
+ annotationArrayParam = [A("3"), A("5"), A("7")],
+ annotationVarArgsParam = [A("9"), A("11"), A("13")],
+ )
+ MyInterface
""".trimIndent()
) as Source.KotlinSource
) { invocation ->
@@ -1263,10 +1447,7 @@
}
}
- val annotation = invocation.processingEnv.requireTypeElement("test.MyClass")
- .getAllAnnotations()
- .single { it.qualifiedName == "test.MyAnnotation" }
-
+ val annotation = getAnnotation(invocation)
// Compare the AnnotationSpec string ignoring whitespace
assertThat(annotation.toAnnotationSpec().toString().removeWhiteSpace())
.isEqualTo("""
@@ -1292,17 +1473,36 @@
return this.replace("\\s+".toRegex(), "")
}
+ private fun getAnnotation(invocation: XTestInvocation): XAnnotation {
+ val typeElement = invocation.processingEnv.requireTypeElement("test.MyClass")
+ return if (isTypeAnnotation) {
+ typeElement.superInterfaces.first().getAllAnnotations()
+ .single { it.qualifiedName == "test.MyAnnotation" }
+ } else {
+ typeElement.getAllAnnotations().single { it.qualifiedName == "test.MyAnnotation" }
+ }
+ }
+
enum class SourceKind { JAVA, KOTLIN }
companion object {
@JvmStatic
- @Parameterized.Parameters(name = "isPreCompiled_{0}_sourceKind_{1}")
+ @Parameterized.Parameters(name = "isPreCompiled_{0}_sourceKind_{1}_isTypeAnnotation_{2}")
fun params(): List<Array<Any>> {
val isPreCompiledValues = arrayOf(false, true)
val sourceKindValues = arrayOf(SourceKind.JAVA, SourceKind.KOTLIN)
+ val isTypeAnnotation = arrayOf(false, true)
return isPreCompiledValues.flatMap { isPreCompiled ->
- sourceKindValues.map { sourceKind ->
- arrayOf(isPreCompiled, sourceKind)
+ sourceKindValues.flatMap { sourceKind ->
+ isTypeAnnotation.mapNotNull { isTypeAnnotation ->
+ // We can't see type annotations from precompiled Java classes. Skipping it
+ // for now: https://github.com/google/ksp/issues/1296
+ if (isPreCompiled && sourceKind == SourceKind.JAVA && isTypeAnnotation) {
+ null
+ } else {
+ arrayOf(isPreCompiled, sourceKind, isTypeAnnotation)
+ }
+ }
}
}
}
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index e44db5b..9036fa2 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -19,6 +19,7 @@
import androidx.room.compiler.codegen.XClassName
import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.codegen.asClassName
+import androidx.room.compiler.processing.javac.JavacType
import androidx.room.compiler.processing.ksp.jvmDescriptor
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
@@ -255,6 +256,9 @@
assertThat(superInterface.typeArguments[0].asTypeName().kotlin)
.isEqualTo(KClassName("kotlin", "String"))
}
+ if (! invocation.isKsp) {
+ assertThat((superInterface as JavacType).kotlinType).isNotNull()
+ }
}
}
}
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index 835cdfd..724c037 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -24,6 +24,7 @@
import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.compiler.processing.util.asJClassName
import androidx.room.compiler.processing.util.asKClassName
+import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.dumpToString
import androidx.room.compiler.processing.util.getDeclaredField
import androidx.room.compiler.processing.util.getDeclaredMethodByJvmName
@@ -1525,4 +1526,115 @@
it.assertCompilationResult { hasErrorContaining("Unresolved reference: MissingType") }
}
}
+
+ @Test
+ fun hasAnnotationWithPackage() {
+ val kotlinSrc = Source.kotlin(
+ "KotlinClass.kt",
+ """
+ package foo.bar
+ interface KotlinInterface
+ open class KotlinBase
+ @Target(AnnotationTarget.TYPE)
+ annotation class KotlinAnnotation {
+ @Target(AnnotationTarget.TYPE)
+ annotation class KotlinNestedAnnotation
+ }
+ class KotlinClass : @KotlinAnnotation.KotlinNestedAnnotation KotlinBase(),
+ @KotlinAnnotation KotlinInterface {
+ inner class KotlinInner : @KotlinAnnotation KotlinInterface
+ class KotlinNested : @KotlinAnnotation KotlinInterface
+ }
+ """.trimIndent()
+ )
+ // KSP can't read nested annotations in Java sources if the filename does not match
+ // the outer class.
+ val javaAnnotationSource = Source.java(
+ "foo.bar.JavaAnnotation",
+ """
+ package foo.bar;
+ import java.lang.annotation.ElementType;
+ import java.lang.annotation.Target;
+ @Target(ElementType.TYPE_USE)
+ @interface JavaAnnotation {
+ @Target(ElementType.TYPE_USE)
+ @interface JavaNestedAnnotation {}
+ }
+ """.trimIndent()
+ )
+ val javaSrc = Source.java(
+ "foo.bar.JavaClass",
+ """
+ package foo.bar;
+ interface JavaInterface {}
+ class JavaBase {}
+ class JavaClass extends @JavaAnnotation.JavaNestedAnnotation JavaBase
+ implements @JavaAnnotation JavaInterface {}
+ """.trimIndent()
+ )
+ fun checkKotlin(invocation: XTestInvocation) {
+ val kotlinTypeElement = invocation.processingEnv.requireTypeElement(
+ "foo.bar.KotlinClass")
+ kotlinTypeElement.superInterfaces.single().let {
+ assertThat(it.getAllAnnotations().single().typeElement.packageName)
+ .isEqualTo("foo.bar")
+ assertThat(it.getAllAnnotations().single().typeElement.qualifiedName)
+ .isEqualTo("foo.bar.KotlinAnnotation")
+
+ assertThat(it.hasAnnotationWithPackage("foo.bar.KotlinAnnotation")).isFalse()
+ assertThat(it.hasAnnotationWithPackage("foo.bar")).isTrue()
+ assertThat(it.hasAnnotationWithPackage("foo")).isFalse()
+ }
+ kotlinTypeElement.superClass!!.let {
+ assertThat(it.getAllAnnotations().single().typeElement.packageName)
+ .isEqualTo("foo.bar")
+ assertThat(it.getAllAnnotations().single().typeElement.qualifiedName)
+ .isEqualTo("foo.bar.KotlinAnnotation.KotlinNestedAnnotation")
+
+ assertThat(it.getAllAnnotations().single().typeElement.packageName)
+ .isEqualTo("foo.bar")
+ assertThat(it.getAllAnnotations().single().typeElement.qualifiedName)
+ .isEqualTo("foo.bar.KotlinAnnotation.KotlinNestedAnnotation")
+ }
+ }
+ fun checkJava(invocation: XTestInvocation) {
+ val javaTypeElement = invocation.processingEnv.requireTypeElement(
+ "foo.bar.JavaClass")
+ javaTypeElement.superInterfaces.first().let {
+ assertThat(it.getAllAnnotations().single().typeElement.packageName)
+ .isEqualTo("foo.bar")
+ assertThat(it.getAllAnnotations().single().typeElement.qualifiedName)
+ .isEqualTo("foo.bar.JavaAnnotation")
+
+ assertThat(it.hasAnnotationWithPackage("foo.bar.JavaClass")).isFalse()
+ assertThat(it.hasAnnotationWithPackage("foo.bar")).isTrue()
+ assertThat(it.hasAnnotationWithPackage("foo")).isFalse()
+ }
+ javaTypeElement.superClass!!.let {
+ assertThat(it.getAllAnnotations().single().typeElement.packageName)
+ .isEqualTo("foo.bar")
+ assertThat(it.getAllAnnotations().single().typeElement.qualifiedName)
+ .isEqualTo("foo.bar.JavaAnnotation.JavaNestedAnnotation")
+
+ assertThat(it.hasAnnotationWithPackage("foo.bar.JavaClass")).isFalse()
+ assertThat(it.hasAnnotationWithPackage("foo.bar")).isTrue()
+ assertThat(it.hasAnnotationWithPackage("foo")).isFalse()
+ }
+ }
+ runProcessorTest(
+ sources = listOf(kotlinSrc, javaAnnotationSource, javaSrc),
+ handler = {
+ checkKotlin(it)
+ checkJava(it)
+ }
+ )
+ runProcessorTest(
+ classpath = compileFiles(listOf(kotlinSrc)),
+ handler = {
+ // We can't see type annotations from precompiled Java classes. Skipping it
+ // for now: https://github.com/google/ksp/issues/1296
+ checkKotlin(it)
+ }
+ )
+ }
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
index 7d67afd..e5efa51 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
@@ -141,14 +141,45 @@
}
}
+ @Test
+ fun interfaceDao_private() {
+ val source = Source.kotlin(
+ "Foo.kt",
+ """
+ import androidx.room.*
+ @Dao
+ interface SubjectDao {
+ private fun upsert() {
+ TODO("")
+ }
+
+ private suspend fun suspendUpsert() {
+ TODO("")
+ }
+ }
+ """.trimIndent()
+ )
+ compileInEachDefaultsMode(
+ source = source,
+ jvmTarget = "11" // private functions in interface require target jvm 9+
+ ) {}
+ }
+
private fun compileInEachDefaultsMode(
source: Source,
+ jvmTarget: String = "1.8",
handler: (StringSubject) -> Unit
) {
// TODO should run these with KSP as well. https://github.com/google/ksp/issues/627
runKaptTest(
sources = listOf(source, COMMON.COROUTINES_ROOM, COMMON.ROOM_DATABASE_KTX),
- kotlincArguments = listOf("-Xjvm-default=${jvmDefaultMode.description}")
+ javacArguments = listOf(
+ "-source", jvmTarget
+ ),
+ kotlincArguments = listOf(
+ "-jvm-target=$jvmTarget",
+ "-Xjvm-default=${jvmDefaultMode.description}"
+ )
) { invocation ->
invocation.roundEnv
.getElementsAnnotatedWith(
diff --git a/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt b/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
index 57e13f0..4ddc81c 100644
--- a/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
+++ b/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
@@ -64,9 +64,7 @@
}
// If the call is within an SDK_INT check, then its OK
if (
- @Suppress("DEPRECATION") // b/262915639
VersionChecks.isWithinVersionCheckConditional(context, node, 16) ||
- @Suppress("DEPRECATION") // b/262915639
VersionChecks.isPrecededByVersionCheckExit(context, node, 16)
) {
return
diff --git a/room/room-runtime-lint/src/main/java/androidx/room/lint/RoomIssueRegistry.kt b/room/room-runtime-lint/src/main/java/androidx/room/lint/RoomIssueRegistry.kt
index daedba0..577b802 100644
--- a/room/room-runtime-lint/src/main/java/androidx/room/lint/RoomIssueRegistry.kt
+++ b/room/room-runtime-lint/src/main/java/androidx/room/lint/RoomIssueRegistry.kt
@@ -23,7 +23,7 @@
class RoomIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues: List<Issue> = listOf(
CursorKotlinUseIssueDetector.ISSUE,
)
diff --git a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedFile.java b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedFile.java
index 9ecf09b..1a7bd69f 100644
--- a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedFile.java
+++ b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedFile.java
@@ -143,6 +143,10 @@
/**
* Builder for an EncryptedFile.
*
+ * <p>If the <code>masterKeyAlias</code> used here is for a key that is not yet
+ * created, this method will not be thread safe. Use the alternate signature that is not
+ * deprecated for multi-threaded contexts.
+ *
* @deprecated Use {@link #Builder(Context, File, MasterKey, FileEncryptionScheme)} instead.
*/
@Deprecated
diff --git a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
index 2060e40..d974cd37 100644
--- a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
+++ b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
@@ -134,6 +134,12 @@
/**
* Opens an instance of encrypted SharedPreferences
*
+ * <p>If the <code>masterKeyAlias</code> used here is for a key that is not yet created, this
+ * method will not be thread safe. Use the alternate signature that is not deprecated for
+ * multi-threaded contexts.
+ *
+ * @deprecated Use {@link #create(Context, String, MasterKey,
+ * PrefKeyEncryptionScheme, PrefValueEncryptionScheme)} instead.
* @param fileName The name of the file to open; can not contain path
* separators.
* @param masterKeyAlias The alias of the master key to use.
@@ -143,8 +149,6 @@
* @return The SharedPreferences instance that encrypts all data.
* @throws GeneralSecurityException when a bad master key or keyset has been attempted
* @throws IOException when fileName can not be used
- * @deprecated Use {@link #create(Context, String, MasterKey,
- * PrefKeyEncryptionScheme, PrefValueEncryptionScheme)} instead.
*/
@Deprecated
@NonNull
diff --git a/settings.gradle b/settings.gradle
index 2449093..e4063e7 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -985,20 +985,20 @@
includeProject(":wear:watchface:watchface-style-old-api-test-stub", "wear/watchface/watchface-style/old-api-test-stub", [BuildType.MAIN, BuildType.WEAR])
includeProject(":webkit:integration-tests:testapp", [BuildType.MAIN])
includeProject(":webkit:webkit", [BuildType.MAIN])
-includeProject(":window:window", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-samples", "window/window/samples", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:extensions:extensions", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:extensions:core:core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:integration-tests:configuration-change-tests", [BuildType.MAIN])
-includeProject(":window:sidecar:sidecar", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-java", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-rxjava2", [BuildType.MAIN])
-includeProject(":window:window-rxjava3", [BuildType.MAIN])
-includeProject(":window:window-demos:demo", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-demos:demo-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-demos:demo-second-app", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
-includeProject(":window:window-testing", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA])
+includeProject(":window:window", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-samples", "window/window/samples", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:extensions:extensions", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:extensions:core:core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:integration-tests:configuration-change-tests", [BuildType.MAIN, BuildType.WINDOW])
+includeProject(":window:sidecar:sidecar", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-java", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-core", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-rxjava2", [BuildType.MAIN, BuildType.WINDOW])
+includeProject(":window:window-rxjava3", [BuildType.MAIN, BuildType.WINDOW])
+includeProject(":window:window-demos:demo", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-demos:demo-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-demos:demo-second-app", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
+includeProject(":window:window-testing", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.CAMERA, BuildType.WINDOW])
includeProject(":work:integration-tests:testapp", [BuildType.MAIN])
includeProject(":work:work-benchmark", [BuildType.MAIN])
includeProject(":work:work-gcm", [BuildType.MAIN])
@@ -1030,7 +1030,7 @@
// Note: don't add new samples/ apps. Instead, Create
// <module>/integration-tests/testapp in the "Libraries" section above.
includeProject(":androidx-demos", new File(samplesRoot, "AndroidXDemos"), [BuildType.MAIN])
-includeProject(":media-routing-demo", new File(samplesRoot, "MediaRoutingDemo"), [BuildType.MAIN])
+includeProject(":media-routing-demo", new File(samplesRoot, "MediaRoutingDemo"), [BuildType.MAIN, BuildType.MEDIA])
includeProject(":support-animation-demos", new File(samplesRoot, "SupportAnimationDemos"), [BuildType.MAIN])
includeProject(":support-content-demos", new File(samplesRoot, "SupportContentDemos"), [BuildType.MAIN])
includeProject(":support-emoji-demos", new File(samplesRoot, "SupportEmojiDemos"), [BuildType.MAIN])
diff --git a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/StartupRuntimeIssueRegistry.kt b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/StartupRuntimeIssueRegistry.kt
index fad6e87..84f5620 100644
--- a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/StartupRuntimeIssueRegistry.kt
+++ b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/StartupRuntimeIssueRegistry.kt
@@ -28,7 +28,7 @@
*/
class StartupRuntimeIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues: List<Issue>
get() = listOf(
InitializerConstructorDetector.ISSUE,
diff --git a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
index b255881..3a3c4f6 100644
--- a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
+++ b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
@@ -519,4 +519,36 @@
}
}
}
+
+ /**
+ * @deprecated You probably meant to call [containsNoneOf] instead.
+ */
+ @Deprecated(
+ message = "You probably meant to call containsNoneOf instead.",
+ replaceWith = ReplaceWith(expression = "containsNoneOf"),
+ )
+ override fun isNoneOf(first: Any?, second: Any?, vararg rest: Any?) {
+ super.isNoneOf(first, second, *rest)
+ }
+
+ @Deprecated(
+ message = "You probably meant to call containsNoneIn instead.",
+ replaceWith = ReplaceWith(expression = "containsNoneIn"),
+ )
+ override fun isNotIn(iterable: Iterable<*>?) {
+ super.isNotIn(iterable)
+
+ requireNonNull(iterable)
+
+ val nonIterables = iterable.filterNot { it is Iterable<*> }
+ if (nonIterables.isNotEmpty()) {
+ fail(
+ "The actual value is an Iterable, and you've written a test that compares it to " +
+ "some objects that are not Iterables. Did you instead mean to check " +
+ "whether its *contents* match any of the *contents* of the given values? " +
+ "If so, call containsNoneOf(...)/containsNoneIn(...) instead. " +
+ "Non-iterables: $nonIterables"
+ )
+ }
+ }
}
diff --git a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
index 346a81d..8c5c948 100644
--- a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
+++ b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
@@ -18,6 +18,7 @@
import kotlin.test.assertIs
import kotlin.test.assertTrue
+import kotlin.test.fail
// As opposed to Truth, which limits visibility on `actual` and the generic type, we purposely make
// them visible in Kruth to allow for an easier time extending in Kotlin.
@@ -68,6 +69,30 @@
* Fails if the subject is not an instance of the given class.
*/
inline fun <reified V> isInstanceOf() = assertIs<V>(actual)
+
+ /** Fails unless the subject is equal to any element in the given [iterable]. */
+ open fun isIn(iterable: Iterable<*>?) {
+ if (actual !in requireNonNull(iterable)) {
+ fail("Expected $actual to be in $iterable, but was not")
+ }
+ }
+
+ /** Fails unless the subject is equal to any of the given elements. */
+ open fun isAnyOf(first: Any?, second: Any?, vararg rest: Any?) {
+ isIn(listOf(first, second, *rest))
+ }
+
+ /** Fails if the subject is equal to any element in the given [iterable]. */
+ open fun isNotIn(iterable: Iterable<*>?) {
+ if (actual in requireNonNull(iterable)) {
+ fail("Expected $actual not to be in $iterable, but it was")
+ }
+ }
+
+ /** Fails if the subject is equal to any of the given elements. */
+ open fun isNoneOf(first: Any?, second: Any?, vararg rest: Any?) {
+ isNotIn(listOf(first, second, *rest))
+ }
}
private fun Any?.standardIsEqualTo(expected: Any?) {
diff --git a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/IterableSubjectTest.kt b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/IterableSubjectTest.kt
index e08ecda..fd3cd7e 100644
--- a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/IterableSubjectTest.kt
+++ b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/IterableSubjectTest.kt
@@ -1000,70 +1000,52 @@
}
}
-//
-// private class Foo private constructor(val x: Int)
-//
-// private class Bar(x: Int) : Foo(x)
-//
-// private val FOO_COMPARATOR: Comparator<Foo> = object : Comparator<Foo?>() {
-// fun compare(a: Foo, b: Foo): Int {
-// return if (a.x < b.x) -1 else if (a.x > b.x) 1 else 0
-// }
-// }
-//
-// @Test
-// fun iterableOrderedByBaseClassComparator() {
-// val targetList: Iterable<Bar> = listOf(Bar(1), Bar(2), Bar(3))
-// assertThat(targetList).isInOrder(FOO_COMPARATOR)
-// assertThat(targetList).isInStrictOrder(FOO_COMPARATOR)
-// }
-//
-// @Test
-// fun isIn() {
-// val actual: ImmutableList<String> = listOf("a")
-// val expectedA: ImmutableList<String> = listOf("a")
-// val expectedB: ImmutableList<String> = listOf("b")
-// val expected: ImmutableList<ImmutableList<String>> = listOf(expectedA, expectedB)
-// assertThat(actual).isIn(expected)
-// }
-//
-// @Test
-// fun isNotIn() {
-// val actual: ImmutableList<String> = listOf("a")
-// assertThat(actual).isNotIn(listOf(listOf("b"), listOf("c")))
-// expectFailureWhenTestingThat(actual).isNotIn(listOf("a", "b"))
-// assertThat(expectFailure.getFailure())
-// .hasMessageThat()
-// .isEqualTo(
-// "The actual value is an Iterable, and you've written a test that compares it to some "
-// + "objects that are not Iterables. Did you instead mean to check whether its "
-// + "*contents* match any of the *contents* of the given values? If so, call "
-// + "containsNoneOf(...)/containsNoneIn(...) instead. Non-iterables: [a, b]"
-// )
-// }
-//
-// @Test
-// fun isAnyOf() {
-// val actual: ImmutableList<String> = listOf("a")
-// val expectedA: ImmutableList<String> = listOf("a")
-// val expectedB: ImmutableList<String> = listOf("b")
-// assertThat(actual).isAnyOf(expectedA, expectedB)
-// }
-//
-// @Test
-// fun isNoneOf() {
-// val actual: ImmutableList<String> = listOf("a")
-// assertThat(actual).isNoneOf(listOf("b"), listOf("c"))
-// expectFailureWhenTestingThat(actual).isNoneOf("a", "b")
-// assertThat(expectFailure.getFailure())
-// .hasMessageThat()
-// .isEqualTo(
-// ("The actual value is an Iterable, and you've written a test that compares it to some "
-// + "objects that are not Iterables. Did you instead mean to check whether its "
-// + "*contents* match any of the *contents* of the given values? If so, call "
-// + "containsNoneOf(...)/containsNoneIn(...) instead. Non-iterables: [a, b]")
-// )
-// }
+ @Test
+ fun iterableOrderedByBaseClassComparator() {
+ val comparator = compareBy<Foo> { it.x }
+ val targetList: Iterable<Bar> = listOf(Bar(1), Bar(2), Bar(3))
+ assertThat(targetList).isInOrder(comparator)
+ assertThat(targetList).isInStrictOrder(comparator)
+ }
+
+ @Test
+ fun isIn() {
+ val actual = listOf("a")
+ val expectedA = listOf("a")
+ val expectedB = listOf("b")
+ val expected = listOf(expectedA, expectedB)
+ assertThat(actual).isIn(expected)
+ }
+
+ @Suppress("DEPRECATION") // Testing a deprecated method
+ @Test
+ fun isNotIn() {
+ val actual = listOf("a")
+ assertThat(actual).isNotIn(listOf(listOf("b"), listOf("c")))
+
+ assertFailsWith<AssertionError> {
+ assertThat(actual).isNotIn(listOf("a", "b"))
+ }
+ }
+
+ @Test
+ fun isAnyOf() {
+ val actual = listOf("a")
+ val expectedA = listOf("a")
+ val expectedB = listOf("b")
+ assertThat(actual).isAnyOf(expectedA, expectedB)
+ }
+
+ @Suppress("DEPRECATION") // Testing a deprecated method
+ @Test
+ fun isNoneOf() {
+ val actual = listOf("a")
+ assertThat(actual).isNoneOf(listOf("b"), listOf("c"))
+
+ assertFailsWith<AssertionError> {
+ assertThat(actual).isNoneOf("a", "b")
+ }
+ }
private companion object {
private val COMPARE_AS_DECIMAL: Comparator<String?> =
@@ -1088,4 +1070,8 @@
override fun toString(): String = "HCT"
}
+
+ private open class Foo(val x: Int)
+
+ private class Bar(x: Int) : Foo(x)
}
diff --git a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
index fed8784..c2d784c 100644
--- a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
+++ b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
@@ -153,6 +153,142 @@
assertThat(StringBuilder("foo")).isEqualTo(StringBuilder("foo"))
}
}
+
+ @Test
+ fun isIn() {
+ assertThat("b").isIn(oneShotIterable("a", "b", "c"))
+ }
+
+ @Test
+ fun isInJustTwo() {
+ assertThat("b").isIn(oneShotIterable("a", "b"))
+ }
+
+ @Test
+ fun isInFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat("x").isIn(oneShotIterable("a", "b", "c"))
+ }
+ }
+
+ @Test
+ fun isInNullInListWithNull() {
+ assertThat(null as String?).isIn(oneShotIterable("a", "b", null as String?))
+ }
+
+ @Test
+ fun isInNonnullInListWithNull() {
+ assertThat("b").isIn(oneShotIterable("a", "b", null as String?))
+ }
+
+ @Test
+ fun isInNullFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat(null as String?).isIn(oneShotIterable("a", "b", "c"))
+ }
+ }
+
+ @Test
+ fun isInEmptyFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat("b").isIn(emptyList<String>())
+ }
+ }
+
+ @Test
+ fun isAnyOf() {
+ assertThat("b").isAnyOf("a", "b", "c")
+ }
+
+ @Test
+ fun isAnyOfJustTwo() {
+ assertThat("b").isAnyOf("a", "b")
+ }
+
+ @Test
+ fun isAnyOfFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat("x").isAnyOf("a", "b", "c")
+ }
+ }
+
+ @Test
+ fun isAnyOfNullInListWithNull() {
+ assertThat(null as String?).isAnyOf("a", "b", null as String?)
+ }
+
+ @Test
+ fun isAnyOfNonnullInListWithNull() {
+ assertThat("b").isAnyOf("a", "b", null as String?)
+ }
+
+ @Test
+ fun isAnyOfNullFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat(null as String?).isAnyOf("a", "b", "c")
+ }
+ }
+
+ @Test
+ fun isNotIn() {
+ assertThat("x").isNotIn(oneShotIterable("a", "b", "c"))
+ }
+
+ @Test
+ fun isNotInFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat("b").isNotIn(oneShotIterable("a", "b", "c"))
+ }
+ }
+
+ @Test
+ fun isNotInNull() {
+ assertThat(null as String?).isNotIn(oneShotIterable("a", "b", "c"))
+ }
+
+ @Test
+ fun isNotInNullFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat(null as String?).isNotIn(oneShotIterable("a", "b", null as String?))
+ }
+ }
+
+ @Test
+ fun isNotInEmpty() {
+ assertThat("b").isNotIn(emptyList<String>())
+ }
+
+ @Test
+ fun isNoneOf() {
+ assertThat("x").isNoneOf("a", "b", "c")
+ }
+
+ @Test
+ fun isNoneOfFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat("b").isNoneOf("a", "b", "c")
+ }
+ }
+
+ @Test
+ fun isNoneOfNull() {
+ assertThat(null as String?).isNoneOf("a", "b", "c")
+ }
+
+ @Test
+ fun isNoneOfNullFailure() {
+ assertFailsWith<AssertionError> {
+ assertThat(null as String?).isNoneOf("a", "b", null as String?)
+ }
+ }
+
+ private fun <T> oneShotIterable(vararg values: T): Iterable<T> =
+ object : Iterable<T> {
+ private val iterator = values.iterator()
+
+ override fun iterator(): Iterator<T> = iterator
+ override fun toString(): String = values.contentToString()
+ }
}
@Suppress("EqualsOrHashCode")
diff --git a/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc b/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
index 72776fc..e634a06 100644
--- a/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
+++ b/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
@@ -25,7 +25,7 @@
// Concept of version useful e.g. for human-readable error messages, and stable once released.
// Does not replace the need for a binary verification mechanism (e.g. checksum check).
// TODO: populate using CMake
-#define VERSION "1.0.0-alpha10"
+#define VERSION "1.0.0-alpha11"
namespace tracing_perfetto {
void RegisterWithPerfetto() {
diff --git a/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt b/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
index 7178a50..753b9d8 100644
--- a/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
+++ b/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
@@ -30,7 +30,7 @@
init {
PerfettoNative.loadLib()
}
- const val libraryVersion = "1.0.0-alpha10" // TODO: get using reflection
+ const val libraryVersion = "1.0.0-alpha11" // TODO: get using reflection
}
@Test
diff --git a/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt b/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
index 5278ec7..a328d3b 100644
--- a/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
+++ b/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
@@ -25,12 +25,12 @@
// TODO(224510255): load from a file produced at build time
object Metadata {
- const val version = "1.0.0-alpha10"
+ const val version = "1.0.0-alpha11"
val checksums = mapOf(
- "arm64-v8a" to "189348f277f588ff41f51b4284bf0568bf3d0eab786f6664f8d66847694e0674",
- "armeabi-v7a" to "9550b32340d790d58fe069b3882815e3d2b20474aa634f01e448392e898cc95b",
- "x86" to "07967aaad711d16f35f509783f56139903f28f661ebb0415522c10fc0453810f",
- "x86_64" to "6b2f4129cb1e52d9c9dca5b89d575c7b2a905670da2e0474917d37223f0c8bf5",
+ "arm64-v8a" to "7b593d218cd0d2938b527779f2797e87ddb7d6c042cc5bf1f12543f103a9c291",
+ "armeabi-v7a" to "5c19ff0e61035b7dbdc450642e16761a8948f588ee523adfc329e10f854499b4",
+ "x86" to "2544cdb37d037b5c9976a55d032712c4642a92d1eab22210f9e2831a5df6531a",
+ "x86_64" to "5214e2a413835b2b7328055f50399aa8ae1be28b63a030193003406bf441ac61",
)
}
diff --git a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPinnableContainerTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPinnableContainerTest.kt
index 98ba1e9..53c3a19 100644
--- a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPinnableContainerTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPinnableContainerTest.kt
@@ -38,6 +38,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -250,6 +251,7 @@
.assertIsNotPlaced()
}
+ @Ignore // b/268720713
@Test
fun pinnedItemIsStillPinnedWhenReorderedAndNotVisibleAnymore() {
val state = TvLazyListState()
diff --git a/viewpager2/integration-tests/testapp/OWNERS b/viewpager2/integration-tests/testapp/OWNERS
index b0972b6c..859a7b9 100644
--- a/viewpager2/integration-tests/testapp/OWNERS
+++ b/viewpager2/integration-tests/testapp/OWNERS
@@ -1,2 +1,2 @@
-# Bug components: 607924
+# Bug component: 607924
[email protected]
\ No newline at end of file
diff --git a/wear/compose/compose-material/api/current.txt b/wear/compose/compose-material/api/current.txt
index fca0d12..7a338f6 100644
--- a/wear/compose/compose-material/api/current.txt
+++ b/wear/compose/compose-material/api/current.txt
@@ -280,7 +280,7 @@
}
public final class PickerGroupKt {
- method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
+ method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional boolean propagateMinConstraints, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.PickerGroupState rememberPickerGroupState(optional int initiallySelectedIndex);
}
diff --git a/wear/compose/compose-material/api/public_plus_experimental_current.txt b/wear/compose/compose-material/api/public_plus_experimental_current.txt
index 863b8a2..0c19e30 100644
--- a/wear/compose/compose-material/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material/api/public_plus_experimental_current.txt
@@ -296,7 +296,7 @@
}
public final class PickerGroupKt {
- method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
+ method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional boolean propagateMinConstraints, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.PickerGroupState rememberPickerGroupState(optional int initiallySelectedIndex);
}
diff --git a/wear/compose/compose-material/api/restricted_current.txt b/wear/compose/compose-material/api/restricted_current.txt
index fca0d12..7a338f6 100644
--- a/wear/compose/compose-material/api/restricted_current.txt
+++ b/wear/compose/compose-material/api/restricted_current.txt
@@ -280,7 +280,7 @@
}
public final class PickerGroupKt {
- method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
+ method @androidx.compose.runtime.Composable public static void PickerGroup(androidx.wear.compose.material.PickerGroupItem![] pickers, optional androidx.compose.ui.Modifier modifier, optional androidx.wear.compose.material.PickerGroupState pickerGroupState, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> onSelected, optional boolean autoCenter, optional boolean propagateMinConstraints, optional androidx.wear.compose.material.TouchExplorationStateProvider touchExplorationStateProvider, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? separator);
method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.PickerGroupState rememberPickerGroupState(optional int initiallySelectedIndex);
}
diff --git a/wear/compose/compose-material/samples/build.gradle b/wear/compose/compose-material/samples/build.gradle
index fc8c8f3..4eddd5f 100644
--- a/wear/compose/compose-material/samples/build.gradle
+++ b/wear/compose/compose-material/samples/build.gradle
@@ -60,3 +60,13 @@
inceptionYear = "2021"
description = "Contains the sample code for the Android Wear Compose Material Classes"
}
+
+// Workaround for https://github.com/gradle/gradle/issues/19882
+configurations.all {
+ resolutionStrategy.dependencySubstitution {
+ substitute(module("androidx.lifecycle:lifecycle-viewmodel-ktx:")).
+ using project(":lifecycle:lifecycle-viewmodel-ktx")
+ substitute(module("androidx.lifecycle:lifecycle-runtime-ktx:")).
+ using project(":lifecycle:lifecycle-runtime-ktx")
+ }
+}
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/HorizontalPageIndicator.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/HorizontalPageIndicator.kt
index f73c371..08dd5cc 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/HorizontalPageIndicator.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/HorizontalPageIndicator.kt
@@ -272,9 +272,7 @@
modifier = modifier,
// 90 degrees equals to 6 o'clock position, at the bottom of the screen
anchor = 90f,
- // Since Swipe to dismiss is always LtR, we want to follow the same direction when
- // navigating amongst pages, so the first page is always on the left.
- angularDirection = CurvedDirection.Angular.CounterClockwise
+ angularDirection = CurvedDirection.Angular.Reversed
) {
// drawing 1 extra spacer for transition
curvedComposable {
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
index a6f1306..845c4685 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
@@ -37,6 +37,7 @@
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.ParentDataModifier
import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.wear.compose.foundation.HierarchicalFocusCoordinator
import androidx.wear.compose.foundation.rememberActiveFocusRequester
@@ -64,6 +65,7 @@
* recommended to set this as true when all the pickers cannot be fit into the screen. Or provide a
* mechanism to navigate to pickers which are not visible on screen. If false, the whole row
* containing pickers would be centered.
+ * @param propagateMinConstraints Whether the incoming min constraints should be passed to content.
* @param touchExplorationStateProvider A [TouchExplorationStateProvider] to provide the current
* state of touch exploration service. This will be used to determine how the PickerGroup and
* talkback focus behaves/reacts to click and scroll events.
@@ -78,18 +80,21 @@
pickerGroupState: PickerGroupState = rememberPickerGroupState(),
onSelected: (selectedIndex: Int) -> Unit = {},
autoCenter: Boolean = true,
+ propagateMinConstraints: Boolean = false,
touchExplorationStateProvider: TouchExplorationStateProvider =
DefaultTouchExplorationStateProvider(),
separator: (@Composable (Int) -> Unit)? = null
) {
val touchExplorationServicesEnabled by touchExplorationStateProvider.touchExplorationState()
+
AutoCenteringRow(
modifier = modifier
.then(
// When touch exploration services are enabled, send the scroll events on the parent
// composable to selected picker
if (touchExplorationServicesEnabled &&
- pickerGroupState.selectedIndex in pickers.indices) {
+ pickerGroupState.selectedIndex in pickers.indices
+ ) {
Modifier.scrollablePicker(
pickers[pickerGroupState.selectedIndex].pickerState
)
@@ -97,6 +102,7 @@
Modifier
}
),
+ propagateMinConstraints = propagateMinConstraints
) {
pickers.forEachIndexed { index, pickerData ->
val pickerSelected = index == pickerGroupState.selectedIndex
@@ -235,17 +241,23 @@
@Composable
private fun AutoCenteringRow(
modifier: Modifier = Modifier,
+ propagateMinConstraints: Boolean,
content: @Composable () -> Unit
) {
- Layout(modifier = modifier, content = content) { measurables, constraints ->
+ Layout(modifier = modifier, content = content) { measurables, parentConstraints ->
+ // Reset the min width and height of the constraints used to measure child composables
+ // if min constraints are not supposed to propagated.
+ val constraints = if (propagateMinConstraints) {
+ parentConstraints
+ } else {
+ parentConstraints.copy(minWidth = 0, minHeight = 0)
+ }
val placeables = measurables.map { it.measure(constraints) }
val centeringOffset = computeCenteringOffset(placeables)
val rowWidth =
if (constraints.hasBoundedWidth) constraints.maxWidth
else constraints.minWidth
- val rowHeight =
- if (constraints.hasBoundedHeight) constraints.maxHeight
- else constraints.minHeight
+ val rowHeight = calculateHeight(constraints, placeables)
layout(width = rowWidth, height = rowHeight) {
var x = rowWidth / 2f - centeringOffset
placeables.forEach {
@@ -290,6 +302,16 @@
return sumWidth / 2
}
+/**
+ * Calculates the height of the [AutoCenteringRow] from the given [Placeable]s and [Constraints]. It
+ * is calculated based on the max height of all the [Placeable]s and the height passed from the
+ * [Constraints].
+ */
+private fun calculateHeight(constraints: Constraints, placeables: List<Placeable>): Int {
+ val maxChildrenHeight = placeables.maxOf { it.height }
+ return maxChildrenHeight.coerceIn(constraints.minHeight, constraints.maxHeight)
+}
+
@Suppress("ModifierInspectorInfo")
internal fun Modifier.autoCenteringTarget() = this.then(
object : ParentDataModifier {
diff --git a/wear/compose/compose-material3/samples/build.gradle b/wear/compose/compose-material3/samples/build.gradle
index 8f54238..10c22e1 100644
--- a/wear/compose/compose-material3/samples/build.gradle
+++ b/wear/compose/compose-material3/samples/build.gradle
@@ -59,3 +59,13 @@
inceptionYear = "2022"
description = "Contains the sample code for the Android Wear Compose Material 3 Classes"
}
+
+// Workaround for https://github.com/gradle/gradle/issues/19882
+configurations.all {
+ resolutionStrategy.dependencySubstitution {
+ substitute(module("androidx.lifecycle:lifecycle-viewmodel-ktx:")).
+ using project(":lifecycle:lifecycle-viewmodel-ktx")
+ substitute(module("androidx.lifecycle:lifecycle-runtime-ktx:")).
+ using project(":lifecycle:lifecycle-runtime-ktx")
+ }
+}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
index 9e68e8f..def1922 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
@@ -135,9 +135,9 @@
// When the time picker loads, none of the individual pickers are selected in talkback mode,
// otherwise hours picker should be focused.
val pickerGroupState = if (touchExplorationServicesEnabled) {
- rememberPickerGroupState(-1)
+ rememberPickerGroupState(FocusableElementsTimePicker.NONE.index)
} else {
- rememberPickerGroupState(0)
+ rememberPickerGroupState(FocusableElementsTimePicker.HOURS.index)
}
val textStyle = MaterialTheme.typography.display3
val optionColor = MaterialTheme.colors.secondary
@@ -159,13 +159,14 @@
createDescription(pickerGroupState, secondState.selectedOption, "seconds")
}
}
- val onPickerSelected = { selectedPicker: Int ->
- if (pickerGroupState.selectedIndex != selectedPicker) {
- pickerGroupState.selectedIndex = selectedPicker
- } else if (selectedPicker > 2) {
+ val onPickerSelected = { curr: FocusableElementsTimePicker,
+ next: FocusableElementsTimePicker ->
+ if (pickerGroupState.selectedIndex != curr.index) {
+ pickerGroupState.selectedIndex = curr.index
+ } else if (next == FocusableElementsTimePicker.CONFIRM_BUTTON) {
focusRequesterConfirmButton.requestFocus()
} else {
- pickerGroupState.selectedIndex += 1
+ pickerGroupState.selectedIndex = next.index
}
}
@@ -176,10 +177,10 @@
) {
Spacer(Modifier.height(12.dp))
Text(
- text = when (pickerGroupState.selectedIndex) {
- 0 -> "Hour"
- 1 -> "Minute"
- 2 -> "Second"
+ text = when (FocusableElementsTimePicker[pickerGroupState.selectedIndex]) {
+ FocusableElementsTimePicker.HOURS -> "Hour"
+ FocusableElementsTimePicker.MINUTES -> "Minute"
+ FocusableElementsTimePicker.SECONDS -> "Second"
else -> ""
},
color = optionColor,
@@ -202,7 +203,12 @@
pickerState = hourState,
modifier = Modifier.size(40.dp, 100.dp),
focusRequester = remember { FocusRequester() },
- onSelected = { onPickerSelected(0) },
+ onSelected = {
+ onPickerSelected(
+ FocusableElementsTimePicker.HOURS,
+ FocusableElementsTimePicker.MINUTES
+ )
+ },
contentDescription = hourContentDescription,
option = pickerOption
),
@@ -210,7 +216,12 @@
pickerState = minuteState,
modifier = Modifier.size(40.dp, 100.dp),
focusRequester = remember { FocusRequester() },
- onSelected = { onPickerSelected(1) },
+ onSelected = {
+ onPickerSelected(
+ FocusableElementsTimePicker.MINUTES,
+ FocusableElementsTimePicker.SECONDS
+ )
+ },
contentDescription = minuteContentDescription,
option = pickerOption
),
@@ -218,7 +229,12 @@
pickerState = secondState,
modifier = Modifier.size(40.dp, 100.dp),
focusRequester = remember { FocusRequester() },
- onSelected = { onPickerSelected(2) },
+ onSelected = {
+ onPickerSelected(
+ FocusableElementsTimePicker.SECONDS,
+ FocusableElementsTimePicker.CONFIRM_BUTTON
+ )
+ },
contentDescription = secondContentDescription,
option = pickerOption
),
@@ -304,23 +320,21 @@
.touchExplorationState()
MaterialTheme(typography = typography) {
- var focusedElement by remember {
- mutableStateOf(
- if (touchExplorationServicesEnabled) FocusableElement12Hour.NONE
- else FocusableElement12Hour.HOURS
- )
- }
+ val pickerGroupState =
+ if (touchExplorationServicesEnabled) {
+ rememberPickerGroupState(FocusableElement12Hour.NONE.index)
+ } else {
+ rememberPickerGroupState(FocusableElement12Hour.HOURS.index)
+ }
val textStyle = MaterialTheme.typography.display3
- val focusRequesterHours = remember { FocusRequester() }
- val focusRequesterMinutes = remember { FocusRequester() }
- val focusRequesterPeriod = remember { FocusRequester() }
+ val pickerOption = pickerTextOption(textStyle) { "%02d".format(it) }
val focusRequesterConfirmButton = remember { FocusRequester() }
val hoursContentDescription by remember { derivedStateOf {
- createDescription12Hour(focusedElement, hourState.selectedOption + 1, "hours")
+ createDescription12Hour(pickerGroupState, hourState.selectedOption + 1, "hours")
} }
val minutesContentDescription by remember { derivedStateOf {
- createDescription12Hour(focusedElement, minuteState.selectedOption, "minutes")
+ createDescription12Hour(pickerGroupState, minuteState.selectedOption, "minutes")
} }
val amString = remember {
@@ -330,28 +344,13 @@
LocalTime.of(18, 0).format(DateTimeFormatter.ofPattern("a"))
}
val periodContentDescription by remember { derivedStateOf {
- if (focusedElement == FocusableElement12Hour.NONE)
- createDescription12Hour(focusedElement, periodState.selectedOption, "period")
+ if (pickerGroupState.selectedIndex == FocusableElement12Hour.NONE.index)
+ createDescription12Hour(pickerGroupState, periodState.selectedOption, "period")
else if (periodState.selectedOption == 0)
- createDescription12Hour(focusedElement, periodState.selectedOption, amString)
- else createDescription12Hour(focusedElement, periodState.selectedOption, pmString)
+ createDescription12Hour(pickerGroupState, periodState.selectedOption, amString)
+ else createDescription12Hour(pickerGroupState, periodState.selectedOption, pmString)
} }
- Box(
- modifier = modifier
- .fillMaxSize()
- .then(
- if (touchExplorationServicesEnabled) {
- when (focusedElement) {
- FocusableElement12Hour.HOURS -> Modifier.scrollablePicker(hourState)
- FocusableElement12Hour.MINUTES -> Modifier.scrollablePicker(minuteState)
- FocusableElement12Hour.PERIOD -> Modifier.scrollablePicker(periodState)
- else -> Modifier
- }
- } else {
- Modifier
- }
- )
- ) {
+ Box(modifier = modifier.fillMaxSize()) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
@@ -359,7 +358,7 @@
) {
Spacer(Modifier.height(12.dp))
Text(
- text = when (focusedElement) {
+ text = when (FocusableElement12Hour[pickerGroupState.selectedIndex]) {
FocusableElement12Hour.HOURS -> "Hour"
FocusableElement12Hour.MINUTES -> "Minute"
else -> ""
@@ -368,10 +367,11 @@
style = MaterialTheme.typography.button,
maxLines = 1,
)
+ val weightsToCenterVertically = 0.5f
Spacer(
Modifier
.fillMaxWidth()
- .weight(0.5f)
+ .weight(weightsToCenterVertically)
)
Row(
modifier = Modifier.fillMaxWidth(),
@@ -380,104 +380,79 @@
) {
val doubleTapToNext =
- { position: FocusableElement12Hour, next: FocusableElement12Hour ->
- focusedElement = when (focusedElement) {
- position -> next
- else -> position
+ { current: FocusableElement12Hour, next: FocusableElement12Hour ->
+ if (pickerGroupState.selectedIndex != current.index) {
+ focusRequesterConfirmButton.requestFocus()
+ } else if (next == FocusableElement12Hour.CONFIRM_BUTTON) {
+ pickerGroupState.selectedIndex = current.index
+ } else {
+ pickerGroupState.selectedIndex = next.index
}
}
- Spacer(Modifier.width(8.dp))
- PickerWithRSB(
- readOnly = focusedElement != FocusableElement12Hour.HOURS,
- state = hourState,
- focusRequester = focusRequesterHours,
- modifier = Modifier.size(48.dp, 100.dp),
- onSelected = {
- doubleTapToNext(
- FocusableElement12Hour.HOURS,
- FocusableElement12Hour.MINUTES
- )
- },
- contentDescription = hoursContentDescription,
- userScrollEnabled = !touchExplorationServicesEnabled ||
- focusedElement == FocusableElement12Hour.HOURS
- ) { hour: Int ->
- TimePiece(
- selected = focusedElement == FocusableElement12Hour.HOURS,
+ PickerGroup(
+ PickerGroupItem(
+ pickerState = hourState,
+ modifier = Modifier.size(40.dp, 100.dp),
+ focusRequester = remember { FocusRequester() },
onSelected = {
doubleTapToNext(
FocusableElement12Hour.HOURS,
FocusableElement12Hour.MINUTES
)
},
- text = "%02d".format(hour + 1),
- style = textStyle,
- touchExplorationServicesEnabled = touchExplorationServicesEnabled
- )
- }
- Separator(2.dp, textStyle)
- PickerWithRSB(
- readOnly = focusedElement != FocusableElement12Hour.MINUTES,
- state = minuteState,
- focusRequester = focusRequesterMinutes,
- modifier = Modifier.size(48.dp, 100.dp),
- onSelected = {
- doubleTapToNext(
- FocusableElement12Hour.MINUTES,
- FocusableElement12Hour.PERIOD
- )
- },
- contentDescription = minutesContentDescription,
- userScrollEnabled = !touchExplorationServicesEnabled ||
- focusedElement == FocusableElement12Hour.MINUTES
- ) { minute: Int ->
- TimePiece(
- selected = focusedElement == FocusableElement12Hour.MINUTES,
+ contentDescription = hoursContentDescription,
+ option = pickerOption
+ ),
+ PickerGroupItem(
+ pickerState = minuteState,
+ modifier = Modifier.size(48.dp, 100.dp),
+ focusRequester = remember { FocusRequester() },
+
onSelected = {
doubleTapToNext(
FocusableElement12Hour.MINUTES,
FocusableElement12Hour.PERIOD
)
},
- text = "%02d".format(minute),
- style = textStyle,
- touchExplorationServicesEnabled = touchExplorationServicesEnabled
- )
- }
- Spacer(Modifier.width(6.dp))
- PickerWithRSB(
- readOnly = focusedElement != FocusableElement12Hour.PERIOD,
- state = periodState,
- focusRequester = focusRequesterPeriod,
- modifier = Modifier.size(64.dp, 100.dp),
- onSelected = {
- doubleTapToNext(
- FocusableElement12Hour.PERIOD,
- FocusableElement12Hour.CONFIRM_BUTTON
- )
- },
- contentDescription = periodContentDescription,
- userScrollEnabled = !touchExplorationServicesEnabled ||
- focusedElement == FocusableElement12Hour.PERIOD
- ) { period: Int ->
- TimePiece(
- selected = focusedElement == FocusableElement12Hour.PERIOD,
+ contentDescription = minutesContentDescription,
+ option = pickerOption
+ ),
+ PickerGroupItem(
+ pickerState = periodState,
+ modifier = Modifier.size(64.dp, 100.dp),
+ focusRequester = remember { FocusRequester() },
+ contentDescription = periodContentDescription,
onSelected = {
doubleTapToNext(
FocusableElement12Hour.PERIOD,
FocusableElement12Hour.CONFIRM_BUTTON
)
},
- text = if (period == 0) amString else pmString,
- style = textStyle,
- touchExplorationServicesEnabled = touchExplorationServicesEnabled
- )
- }
+ option = { optionIndex: Int, pickerSelected: Boolean ->
+ Box(modifier = Modifier.fillMaxSize()) {
+ Text(
+ text = if (optionIndex == 0) amString else pmString,
+ maxLines = 1,
+ style = textStyle,
+ color =
+ if (pickerSelected) MaterialTheme.colors.secondary
+ else MaterialTheme.colors.onBackground,
+ modifier = Modifier
+ .align(Alignment.Center)
+ .wrapContentSize()
+ )
+ }
+ }
+ ),
+ autoCenter = false,
+ pickerGroupState = pickerGroupState,
+ separator = { Separator(6.dp, textStyle) },
+ )
}
Spacer(
Modifier
.fillMaxWidth()
- .weight(0.5f)
+ .weight(weightsToCenterVertically)
)
Button(onClick = {
val confirmedTime = LocalTime.of(
@@ -489,7 +464,8 @@
},
modifier = Modifier
.semantics {
- focused = focusedElement == FocusableElement12Hour.CONFIRM_BUTTON
+ focused = pickerGroupState.selectedIndex ==
+ FocusableElement12Hour.CONFIRM_BUTTON.index
}
.focusRequester(focusRequesterConfirmButton)
@@ -503,14 +479,6 @@
)
}
Spacer(Modifier.height(8.dp))
- LaunchedEffect(focusedElement) {
- if (focusedElement != FocusableElement12Hour.NONE) {
- listOf(
- focusRequesterHours, focusRequesterMinutes, focusRequesterPeriod,
- focusRequesterConfirmButton
- )[focusedElement.index].requestFocus()
- }
- }
}
}
}
@@ -785,14 +753,6 @@
}
Spacer(Modifier.height(12.dp))
}
- LaunchedEffect(focusedElement) {
- if (focusedElement != FocusableElementDatePicker.NONE) {
- listOf(
- focusRequesterDay, focusRequesterMonth, focusRequesterYear,
- focusRequesterConfirmButton
- )[focusedElement.index].requestFocus()
- }
- }
}
}
}
@@ -828,6 +788,8 @@
}
}
+// This is a demo file, suppressing the annotation group error.
+@SuppressLint("NullAnnotationGroup")
@OptIn(ExperimentalComposeUiApi::class)
@Composable
internal fun TimePiece(
@@ -959,21 +921,21 @@
label: String
): String {
return when (pickerGroupState.selectedIndex) {
- -1 -> label
+ FocusableElementsTimePicker.NONE.index -> label
else -> "$selectedValue" + label
}
}
private fun createDescription12Hour(
- focusedElement: FocusableElement12Hour,
+ pickerGroupState: PickerGroupState,
selectedValue: Int,
label: String
): String {
- return when (focusedElement) {
- FocusableElement12Hour.HOURS -> {
+ return when (pickerGroupState.selectedIndex) {
+ FocusableElement12Hour.HOURS.index -> {
"$selectedValue" + label
}
- FocusableElement12Hour.MINUTES -> {
+ FocusableElement12Hour.MINUTES.index -> {
"$selectedValue" + label
}
else -> label
@@ -1161,12 +1123,29 @@
}
}
+enum class FocusableElementsTimePicker(val index: Int) {
+ HOURS(0),
+ MINUTES(1),
+ SECONDS(2),
+ CONFIRM_BUTTON(3),
+ NONE(-1);
+
+ companion object {
+ private val map = FocusableElementsTimePicker.values().associateBy { it.index }
+ operator fun get(value: Int) = map[value]
+ }
+}
+
enum class FocusableElement12Hour(val index: Int) {
HOURS(0),
MINUTES(1),
PERIOD(2),
CONFIRM_BUTTON(3),
- NONE(-1)
+ NONE(-1);
+ companion object {
+ private val map = FocusableElement12Hour.values().associateBy { it.index }
+ operator fun get(value: Int) = map[value]
+ }
}
enum class FocusableElementDatePicker(val index: Int) {
@@ -1174,5 +1153,9 @@
MONTH(1),
YEAR(2),
CONFIRM_BUTTON(3),
- NONE(-1)
+ NONE(-1);
+ companion object {
+ private val map = FocusableElementDatePicker.values().associateBy { it.index }
+ operator fun get(value: Int) = map[value]
+ }
}
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/current.txt b/wear/protolayout/protolayout-expression-pipeline/api/current.txt
index 6f6c05a..5cd07fa 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/current.txt
@@ -12,6 +12,8 @@
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Float!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Duration!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Instant!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Boolean!>);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
method @UiThread public void disablePlatformDataSources();
@@ -42,7 +44,7 @@
method @UiThread public void registerSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void registerSensorGatewayConsumer(java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void unregisterSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
- field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
+ field @RequiresApi(android.os.Build.VERSION_CODES.Q) @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final int SENSOR_DATA_TYPE_HEART_RATE = 0; // 0x0
field public static final int SENSOR_DATA_TYPE_INVALID = -1; // 0xffffffff
}
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
index 6f6c05a..5cd07fa 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/public_plus_experimental_current.txt
@@ -12,6 +12,8 @@
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Float!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Duration!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Instant!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Boolean!>);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
method @UiThread public void disablePlatformDataSources();
@@ -42,7 +44,7 @@
method @UiThread public void registerSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void registerSensorGatewayConsumer(java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void unregisterSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
- field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
+ field @RequiresApi(android.os.Build.VERSION_CODES.Q) @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final int SENSOR_DATA_TYPE_HEART_RATE = 0; // 0x0
field public static final int SENSOR_DATA_TYPE_INVALID = -1; // 0xffffffff
}
diff --git a/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
index 25399f3..3a48704 100644
--- a/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-expression-pipeline/api/restricted_current.txt
@@ -12,6 +12,8 @@
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Float!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Integer!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Duration!>);
+ method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.time.Instant!>);
method public androidx.wear.protolayout.expression.pipeline.BoundDynamicType bind(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool, androidx.wear.protolayout.expression.pipeline.DynamicTypeValueReceiver<java.lang.Boolean!>);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void close();
method @UiThread public void disablePlatformDataSources();
@@ -46,7 +48,7 @@
method @UiThread public void registerSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void registerSensorGatewayConsumer(java.util.concurrent.Executor, androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
method @UiThread public void unregisterSensorGatewayConsumer(androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.Consumer);
- field @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
+ field @RequiresApi(android.os.Build.VERSION_CODES.Q) @RequiresPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) public static final int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1; // 0x1
field @RequiresPermission(android.Manifest.permission.BODY_SENSORS) public static final int SENSOR_DATA_TYPE_HEART_RATE = 0; // 0x0
field public static final int SENSOR_DATA_TYPE_INVALID = -1; // 0xffffffff
}
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/ColorNodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/ColorNodes.java
index 54cbc77..1ef366a 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/ColorNodes.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/ColorNodes.java
@@ -101,7 +101,7 @@
ValueAnimator.ofArgb(mProtoNode.getFromArgb(), mProtoNode.getToArgb());
animator.addUpdateListener(a -> mDownstream.onData((Integer) a.getAnimatedValue()));
- applyAnimationSpecToAnimator(animator, mProtoNode.getSpec());
+ applyAnimationSpecToAnimator(animator, mProtoNode.getAnimationSpec());
mQuotaAwareAnimator.updateAnimator(animator);
startOrSkipAnimator();
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DurationNodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DurationNodes.java
new file mode 100644
index 0000000..3813bd8
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DurationNodes.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.wear.protolayout.expression.pipeline;
+
+import java.time.Duration;
+import java.time.Instant;
+
+/** Dynamic data nodes which yield durations. */
+class DurationNodes {
+ private DurationNodes() {}
+
+ /** Dynamic duration node that gets the duration between two time instants. */
+ static class BetweenInstancesNode
+ extends DynamicDataBiTransformNode<Instant, Instant, Duration> {
+
+ BetweenInstancesNode(DynamicTypeValueReceiver<Duration> downstream) {
+ super(downstream, Duration::between);
+ }
+ }
+}
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
index 2468ae7..2080180 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluator.java
@@ -37,6 +37,7 @@
import androidx.wear.protolayout.expression.pipeline.ColorNodes.DynamicAnimatedColorNode;
import androidx.wear.protolayout.expression.pipeline.ColorNodes.FixedColorNode;
import androidx.wear.protolayout.expression.pipeline.ColorNodes.StateColorSourceNode;
+import androidx.wear.protolayout.expression.pipeline.DurationNodes.BetweenInstancesNode;
import androidx.wear.protolayout.expression.pipeline.FloatNodes.AnimatableFixedFloatNode;
import androidx.wear.protolayout.expression.pipeline.FloatNodes.ArithmeticFloatNode;
import androidx.wear.protolayout.expression.pipeline.FloatNodes.DynamicAnimatedFloatNode;
@@ -44,13 +45,15 @@
import androidx.wear.protolayout.expression.pipeline.FloatNodes.Int32ToFloatNode;
import androidx.wear.protolayout.expression.pipeline.FloatNodes.StateFloatNode;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.AnimatableFixedInt32Node;
+import androidx.wear.protolayout.expression.pipeline.InstantNodes.FixedInstantNode;
+import androidx.wear.protolayout.expression.pipeline.InstantNodes.PlatformTimeSourceNode;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.ArithmeticInt32Node;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.DynamicAnimatedInt32Node;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.FixedInt32Node;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.FloatToInt32Node;
+import androidx.wear.protolayout.expression.pipeline.Int32Nodes.GetDurationPartOpNode;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.PlatformInt32SourceNode;
import androidx.wear.protolayout.expression.pipeline.Int32Nodes.StateInt32SourceNode;
-import androidx.wear.protolayout.expression.pipeline.PlatformDataSources.EpochTimePlatformDataSource;
import androidx.wear.protolayout.expression.pipeline.PlatformDataSources.SensorGatewayPlatformDataSource;
import androidx.wear.protolayout.expression.pipeline.StringNodes.FixedStringNode;
import androidx.wear.protolayout.expression.pipeline.StringNodes.FloatFormatNode;
@@ -66,13 +69,17 @@
import androidx.wear.protolayout.expression.proto.DynamicProto.ConditionalStringOp;
import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicBool;
import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicColor;
+import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicDuration;
import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicFloat;
+import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicInstant;
import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicInt32;
import androidx.wear.protolayout.expression.proto.DynamicProto.DynamicString;
import androidx.wear.protolayout.expression.proto.FixedProto.FixedColor;
import androidx.wear.protolayout.expression.proto.FixedProto.FixedFloat;
import androidx.wear.protolayout.expression.proto.FixedProto.FixedInt32;
+import java.time.Duration;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -276,12 +283,6 @@
* Adds dynamic type from the given {@link DynamicBuilders.DynamicString} for evaluation.
* Evaluation will start immediately.
*
- * <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
- *
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param stringSource The given String dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -303,10 +304,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param stringSource The given String dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -329,12 +326,6 @@
* Adds dynamic type from the given {@link DynamicBuilders.DynamicInt32} for evaluation.
* Evaluation will start immediately.
*
- * <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
- *
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param int32Source The given integer dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -355,10 +346,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param int32Source The given integer dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -378,10 +365,6 @@
/**
* Adds pending expression from the given {@link DynamicInt32} for future evaluation.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with{@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param int32Source The given integer dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -405,12 +388,6 @@
* Adds dynamic type from the given {@link DynamicBuilders.DynamicFloat} for evaluation.
* Evaluation will start immediately.
*
- * <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
- *
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param floatSource The given float dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -431,10 +408,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param floatSource The given float dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -459,10 +432,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param floatSource The given float dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -482,12 +451,6 @@
* Adds dynamic type from the given {@link DynamicBuilders.DynamicColor} for evaluation.
* Evaluation will start immediately.
*
- * <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
- *
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param colorSource The given color dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -508,10 +471,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param colorSource The given color dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -533,10 +492,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param colorSource The given color dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -557,14 +512,86 @@
}
/**
- * Adds dynamic type from the given {@link DynamicBuilders.DynamicBool} for evaluation.
+ * Adds dynamic type from the given {@link DynamicBuilders.DynamicDuration} for evaluation.
* Evaluation will start immediately.
*
+ * @param durationSource The given duration dynamic type that should be evaluated.
+ * @param consumer The registered consumer for results of the evaluation. It will be called from
+ * UI thread.
+ */
+ @NonNull
+ public BoundDynamicType bind(
+ @NonNull DynamicBuilders.DynamicDuration durationSource,
+ @NonNull DynamicTypeValueReceiver<Duration> consumer) {
+ List<DynamicDataNode<?>> resultBuilder = new ArrayList<>();
+ bindRecursively(durationSource.toDynamicDurationProto(), consumer, resultBuilder);
+ processBindings(resultBuilder);
+ return new BoundDynamicTypeImpl(resultBuilder);
+ }
+
+ /**
+ * Adds pending dynamic type from the given {@link DynamicDuration} for future evaluation.
+ *
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
+ * @param durationSource The given durations dynamic type that should be evaluated.
+ * @param consumer The registered consumer for results of the evaluation. It will be called from
+ * UI thread.
+ * @hide
+ */
+ @NonNull
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ public BoundDynamicType bind(
+ @NonNull DynamicDuration durationSource,
+ @NonNull DynamicTypeValueReceiver<Duration> consumer) {
+ List<DynamicDataNode<?>> resultBuilder = new ArrayList<>();
+ bindRecursively(durationSource, consumer, resultBuilder);
+ mDynamicTypeNodes.addAll(resultBuilder);
+ return new BoundDynamicTypeImpl(resultBuilder);
+ }
+
+ /**
+ * Adds dynamic type from the given {@link DynamicBuilders.DynamicInstant} for evaluation.
+ * Evaluation will start immediately.
+ *
+ * @param instantSource The given instant dynamic type that should be evaluated.
+ * @param consumer The registered consumer for results of the evaluation. It will be called from
+ * UI thread.
+ */
+ @NonNull
+ public BoundDynamicType bind(
+ @NonNull DynamicBuilders.DynamicInstant instantSource,
+ @NonNull DynamicTypeValueReceiver<Instant> consumer) {
+ List<DynamicDataNode<?>> resultBuilder = new ArrayList<>();
+ bindRecursively(instantSource.toDynamicInstantProto(), consumer, resultBuilder);
+ processBindings(resultBuilder);
+ return new BoundDynamicTypeImpl(resultBuilder);
+ }
+
+ /**
+ * Adds pending dynamic type from the given {@link DynamicInstant} for future evaluation.
+ *
+ * <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
+ *
+ * @param instantSource The given instant dynamic type that should be evaluated.
+ * @param consumer The registered consumer for results of the evaluation. It will be called from
+ * UI thread.
+ * @hide
+ */
+ @NonNull
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ public BoundDynamicType bind(
+ @NonNull DynamicInstant instantSource,
+ @NonNull DynamicTypeValueReceiver<Instant> consumer) {
+ List<DynamicDataNode<?>> resultBuilder = new ArrayList<>();
+ bindRecursively(instantSource, consumer, resultBuilder);
+ mDynamicTypeNodes.addAll(resultBuilder);
+ return new BoundDynamicTypeImpl(resultBuilder);
+ }
+
+ /**
+ * Adds dynamic type from the given {@link DynamicBuilders.DynamicBool} for evaluation.
+ * Evaluation will start immediately.
*
* @param boolSource The given boolean dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
@@ -585,10 +612,6 @@
*
* <p>Evaluation of this dynamic type will start when {@link #processPendingBindings} is called.
*
- * <p>While the {@link BoundDynamicType} is not destroyed with {@link BoundDynamicType#close()}
- * by caller, results of evaluation will be sent through the given {@link
- * DynamicTypeValueReceiver}.
- *
* @param boolSource The given boolean dynamic type that should be evaluated.
* @param consumer The registered consumer for results of the evaluation. It will be called from
* UI thread.
@@ -720,7 +743,6 @@
case PLATFORM_SOURCE:
node = new PlatformInt32SourceNode(
int32Source.getPlatformSource(),
- mTimeDataSource,
mSensorGatewayDataSource,
consumer);
break;
@@ -786,6 +808,18 @@
Optional.empty());
break;
}
+ case DURATION_PART:
+ {
+ GetDurationPartOpNode durationPartOpNode =
+ new GetDurationPartOpNode(int32Source.getDurationPart(), consumer);
+ node = durationPartOpNode;
+
+ bindRecursively(
+ int32Source.getDurationPart().getInput(),
+ durationPartOpNode.getIncomingCallback(),
+ resultBuilder);
+ break;
+ }
case ANIMATABLE_FIXED:
if (!mEnableAnimations && animationFallbackValue.isPresent()) {
// Just assign static value if animations are disabled.
@@ -822,7 +856,7 @@
// animations won't be played and they would jump to the end value.
AnimatableDynamicInt32 dynamicNode = int32Source.getAnimatableDynamic();
DynamicAnimatedInt32Node animationNode =
- new DynamicAnimatedInt32Node(consumer, dynamicNode.getSpec(),
+ new DynamicAnimatedInt32Node(consumer, dynamicNode.getAnimationSpec(),
mAnimationQuotaManager);
node = animationNode;
@@ -843,6 +877,67 @@
}
/**
+ * Same as {@link #bind(DynamicBuilders.DynamicDuration, DynamicTypeValueReceiver)}, but instead
+ * of returning one {@link BoundDynamicType}, all {@link DynamicDataNode} produced by evaluating
+ * given dynamic type are added to the given list.
+ */
+ private void bindRecursively(
+ @NonNull DynamicDuration durationSource,
+ @NonNull DynamicTypeValueReceiver<Duration> consumer,
+ @NonNull List<DynamicDataNode<?>> resultBuilder) {
+ DynamicDataNode<?> node;
+
+ switch (durationSource.getInnerCase()) {
+ case BETWEEN:
+ BetweenInstancesNode betweenInstancesNode = new BetweenInstancesNode(consumer);
+ node = betweenInstancesNode;
+ bindRecursively(
+ durationSource.getBetween().getStartInclusive(),
+ betweenInstancesNode.getLhsIncomingCallback(),
+ resultBuilder);
+ bindRecursively(
+ durationSource.getBetween().getEndExclusive(),
+ betweenInstancesNode.getRhsIncomingCallback(),
+ resultBuilder);
+ break;
+ case INNER_NOT_SET:
+ throw new IllegalArgumentException("DynamicDuration has no inner source set");
+ default:
+ throw new IllegalArgumentException("Unknown DynamicDuration source type");
+ }
+
+ resultBuilder.add(node);
+ }
+
+ /**
+ * Same as {@link #bind(DynamicBuilders.DynamicInstant, DynamicTypeValueReceiver)}, but instead
+ * of returning one {@link BoundDynamicType}, all {@link DynamicDataNode} produced by evaluating
+ * given dynamic type are added to the given list.
+ */
+ private void bindRecursively(
+ @NonNull DynamicInstant instantSource,
+ @NonNull DynamicTypeValueReceiver<Instant> consumer,
+ @NonNull List<DynamicDataNode<?>> resultBuilder) {
+ DynamicDataNode<?> node;
+
+ switch (instantSource.getInnerCase()) {
+ case FIXED:
+ node = new FixedInstantNode(instantSource.getFixed(), consumer);
+ break;
+ case PLATFORM_SOURCE:
+ node = new PlatformTimeSourceNode(mTimeDataSource, consumer);
+ break;
+
+ case INNER_NOT_SET:
+ throw new IllegalArgumentException("DynamicInstant has no inner source set");
+ default:
+ throw new IllegalArgumentException("Unknown DynamicInstant source type");
+ }
+
+ resultBuilder.add(node);
+ }
+
+ /**
* Same as {@link #bind(DynamicBuilders.DynamicFloat, DynamicTypeValueReceiver)}, but instead of
* returning one {@link BoundDynamicType}, all {@link DynamicDataNode} produced by evaluating
* given dynamic type are added to the given list.
@@ -956,7 +1051,10 @@
AnimatableDynamicFloat dynamicNode = floatSource.getAnimatableDynamic();
DynamicAnimatedFloatNode animationNode =
new DynamicAnimatedFloatNode(
- consumer, dynamicNode.getSpec(), mAnimationQuotaManager);
+ consumer,
+ dynamicNode.getAnimationSpec(),
+ mAnimationQuotaManager
+ );
node = animationNode;
bindRecursively(
@@ -1037,7 +1135,10 @@
AnimatableDynamicColor dynamicNode = colorSource.getAnimatableDynamic();
DynamicAnimatedColorNode animationNode =
new DynamicAnimatedColorNode(
- consumer, dynamicNode.getSpec(), mAnimationQuotaManager);
+ consumer,
+ dynamicNode.getAnimationSpec(),
+ mAnimationQuotaManager
+ );
node = animationNode;
bindRecursively(
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/EpochTimePlatformDataSource.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/EpochTimePlatformDataSource.java
new file mode 100644
index 0000000..37c858e
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/EpochTimePlatformDataSource.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2023 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.wear.protolayout.expression.pipeline;
+
+import androidx.collection.SimpleArrayMap;
+import androidx.wear.protolayout.expression.pipeline.TimeGateway.TimeCallback;
+
+import java.time.Instant;
+import java.util.concurrent.Executor;
+
+/** Utility for time data source. */
+class EpochTimePlatformDataSource {
+ private final Executor mUiExecutor;
+ private final TimeGateway mGateway;
+ private final SimpleArrayMap<DynamicTypeValueReceiver<Instant>, TimeCallback>
+ mConsumerToTimeCallback = new SimpleArrayMap<>();
+
+ EpochTimePlatformDataSource(Executor uiExecutor, TimeGateway gateway) {
+ mUiExecutor = uiExecutor;
+ mGateway = gateway;
+ }
+
+ public void registerForData(DynamicTypeValueReceiver<Instant> consumer) {
+ TimeCallback timeCallback =
+ new TimeCallback() {
+ @Override
+ public void onPreUpdate() {
+ consumer.onPreUpdate();
+ }
+
+ @Override
+ public void onData() {
+ consumer.onData(Instant.now());
+ }
+ };
+ mGateway.registerForUpdates(mUiExecutor, timeCallback);
+ mConsumerToTimeCallback.put(consumer, timeCallback);
+ }
+
+ public void unregisterForData(DynamicTypeValueReceiver<Instant> consumer) {
+ TimeCallback timeCallback = mConsumerToTimeCallback.remove(consumer);
+ if (timeCallback != null) {
+ mGateway.unregisterForUpdates(timeCallback);
+ }
+ }
+}
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FloatNodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FloatNodes.java
index 73727de..4c1027b 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FloatNodes.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/FloatNodes.java
@@ -145,7 +145,7 @@
ValueAnimator.ofFloat(mProtoNode.getFromValue(), mProtoNode.getToValue());
animator.addUpdateListener(a -> mDownstream.onData((float) a.getAnimatedValue()));
- applyAnimationSpecToAnimator(animator, mProtoNode.getSpec());
+ applyAnimationSpecToAnimator(animator, mProtoNode.getAnimationSpec());
mQuotaAwareAnimator.updateAnimator(animator);
startOrSkipAnimator();
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/InstantNodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/InstantNodes.java
new file mode 100644
index 0000000..012469c
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/InstantNodes.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2023 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.wear.protolayout.expression.pipeline;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.wear.protolayout.expression.proto.FixedProto.FixedInstant;
+
+import java.time.Instant;
+
+/** Dynamic data nodes which yield instants. */
+class InstantNodes {
+ private InstantNodes() {}
+ /** Dynamic instant node that has a fixed value. */
+ static class FixedInstantNode implements DynamicDataSourceNode<Integer> {
+ private final Instant mValue;
+ private final DynamicTypeValueReceiver<Instant> mDownstream;
+
+ FixedInstantNode(FixedInstant protoNode, DynamicTypeValueReceiver<Instant> downstream) {
+ this.mValue = Instant.ofEpochSecond(protoNode.getEpochSeconds());
+ this.mDownstream = downstream;
+ }
+
+ @Override
+ @UiThread
+ public void preInit() {
+ mDownstream.onPreUpdate();
+ }
+
+ @Override
+ @UiThread
+ public void init() {
+ mDownstream.onData(mValue);
+ }
+
+ @Override
+ public void destroy() {}
+ }
+ /** Dynamic Instant node that gets value from the platform source. */
+ static class PlatformTimeSourceNode implements DynamicDataSourceNode<Integer> {
+ @Nullable private final EpochTimePlatformDataSource mEpochTimePlatformDataSource;
+ private final DynamicTypeValueReceiver<Instant> mDownstream;
+
+ PlatformTimeSourceNode(
+ @Nullable EpochTimePlatformDataSource epochTimePlatformDataSource,
+ DynamicTypeValueReceiver<Instant> downstream) {
+ this.mEpochTimePlatformDataSource = epochTimePlatformDataSource;
+ this.mDownstream = downstream;
+ }
+
+ @Override
+ @UiThread
+ public void preInit() {}
+
+ @Override
+ @UiThread
+ public void init() {
+ if (mEpochTimePlatformDataSource != null) {
+ mEpochTimePlatformDataSource.registerForData(mDownstream);
+ } else {
+ mDownstream.onInvalidated();
+ }
+ }
+
+ @Override
+ @UiThread
+ public void destroy() {
+ if (mEpochTimePlatformDataSource != null) {
+ mEpochTimePlatformDataSource.unregisterForData(mDownstream);
+ }
+ }
+ }
+}
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
index 4fc75c6..a2c9a94 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
@@ -17,24 +17,26 @@
package androidx.wear.protolayout.expression.pipeline;
import static androidx.wear.protolayout.expression.pipeline.AnimationsHelper.applyAnimationSpecToAnimator;
+import static java.lang.Math.abs;
import android.animation.ValueAnimator;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
-import androidx.wear.protolayout.expression.pipeline.PlatformDataSources.EpochTimePlatformDataSource;
import androidx.wear.protolayout.expression.pipeline.PlatformDataSources.PlatformDataSource;
import androidx.wear.protolayout.expression.pipeline.PlatformDataSources.SensorGatewayPlatformDataSource;
import androidx.wear.protolayout.expression.proto.AnimationParameterProto.AnimationSpec;
import androidx.wear.protolayout.expression.proto.DynamicProto.AnimatableFixedInt32;
import androidx.wear.protolayout.expression.proto.DynamicProto.ArithmeticInt32Op;
+import androidx.wear.protolayout.expression.proto.DynamicProto.DurationPartType;
import androidx.wear.protolayout.expression.proto.DynamicProto.FloatToInt32Op;
import androidx.wear.protolayout.expression.proto.DynamicProto.PlatformInt32Source;
import androidx.wear.protolayout.expression.proto.DynamicProto.PlatformInt32SourceType;
import androidx.wear.protolayout.expression.proto.DynamicProto.StateInt32Source;
+import androidx.wear.protolayout.expression.proto.DynamicProto.GetDurationPartOp;
import androidx.wear.protolayout.expression.proto.FixedProto.FixedInt32;
+import java.time.Duration;
/** Dynamic data nodes which yield integers. */
class Int32Nodes {
@@ -72,17 +74,14 @@
private static final String TAG = "PlatformInt32SourceNode";
@Nullable private final SensorGatewayPlatformDataSource mSensorGatewaySource;
- @Nullable private final EpochTimePlatformDataSource mEpochTimePlatformDataSource;
private final PlatformInt32Source mProtoNode;
private final DynamicTypeValueReceiver<Integer> mDownstream;
PlatformInt32SourceNode(
PlatformInt32Source protoNode,
- @Nullable EpochTimePlatformDataSource epochTimePlatformDataSource,
@Nullable SensorGatewayPlatformDataSource sensorGatewaySource,
DynamicTypeValueReceiver<Integer> downstream) {
this.mProtoNode = protoNode;
- this.mEpochTimePlatformDataSource = epochTimePlatformDataSource;
this.mSensorGatewaySource = sensorGatewaySource;
this.mDownstream = downstream;
}
@@ -128,8 +127,6 @@
case PLATFORM_INT32_SOURCE_TYPE_CURRENT_HEART_RATE:
case PLATFORM_INT32_SOURCE_TYPE_DAILY_STEP_COUNT:
return mSensorGatewaySource;
- case PLATFORM_INT32_SOURCE_TYPE_EPOCH_TIME_SECONDS:
- return mEpochTimePlatformDataSource;
}
Log.w(TAG, "Unknown PlatformInt32SourceType");
return null;
@@ -210,6 +207,44 @@
}
}
+ /** Dynamic integer node that gets duration part from a duration. */
+ static class GetDurationPartOpNode extends DynamicDataTransformNode<Duration, Integer> {
+
+ private static final String TAG = "GetDurationPartOpNode";
+
+ GetDurationPartOpNode(
+ GetDurationPartOp protoNode, DynamicTypeValueReceiver<Integer> downstream) {
+ super(downstream,
+ duration -> (int) getDurationPart(duration, protoNode.getDurationPart()));
+ }
+
+ private static long getDurationPart(Duration duration, DurationPartType durationPartType) {
+ switch (durationPartType) {
+ case DURATION_PART_TYPE_UNDEFINED:
+ case UNRECOGNIZED:
+ Log.e(TAG, "Unknown duration part type in GetDurationPartOpNode");
+ return 0;
+ case DURATION_PART_TYPE_DAYS:
+ return abs(duration.getSeconds() / (3600 * 24));
+ case DURATION_PART_TYPE_HOURS:
+ return abs((duration.getSeconds() / 3600) % 24);
+ case DURATION_PART_TYPE_MINUTES:
+ return abs((duration.getSeconds() / 60) % 60);
+ case DURATION_PART_TYPE_SECONDS:
+ return abs(duration.getSeconds() % 60);
+ case DURATION_PART_TYPE_TOTAL_DAYS:
+ return duration.toDays();
+ case DURATION_PART_TYPE_TOTAL_HOURS:
+ return duration.toHours();
+ case DURATION_PART_TYPE_TOTAL_MINUTES:
+ return duration.toMinutes();
+ case DURATION_PART_TYPE_TOTAL_SECONDS:
+ return duration.getSeconds();
+ }
+ throw new IllegalArgumentException("Unknown duration part");
+ }
+ }
+
/** Dynamic int32 node that gets animatable value from fixed source. */
static class AnimatableFixedInt32Node extends AnimatableNode
implements DynamicDataSourceNode<Integer> {
@@ -237,7 +272,7 @@
public void init() {
ValueAnimator animator =
ValueAnimator.ofInt(mProtoNode.getFromValue(), mProtoNode.getToValue());
- applyAnimationSpecToAnimator(animator, mProtoNode.getSpec());
+ applyAnimationSpecToAnimator(animator, mProtoNode.getAnimationSpec());
animator.addUpdateListener(a -> mDownstream.onData((Integer) a.getAnimatedValue()));
mQuotaAwareAnimator.updateAnimator(animator);
startOrSkipAnimator();
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/PlatformDataSources.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/PlatformDataSources.java
index 0f86713..b3a2ee2 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/PlatformDataSources.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/PlatformDataSources.java
@@ -22,8 +22,6 @@
import androidx.annotation.DoNotInline;
import androidx.annotation.RequiresApi;
import androidx.collection.ArrayMap;
-import androidx.collection.SimpleArrayMap;
-import androidx.wear.protolayout.expression.pipeline.TimeGateway.TimeCallback;
import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway.SensorDataType;
import androidx.wear.protolayout.expression.proto.DynamicProto.PlatformInt32SourceType;
@@ -43,48 +41,6 @@
PlatformInt32SourceType sourceType, DynamicTypeValueReceiver<Integer> consumer);
}
- /** Utility for time data source. */
- static class EpochTimePlatformDataSource implements PlatformDataSource {
- private final Executor mUiExecutor;
- private final TimeGateway mGateway;
- private final SimpleArrayMap<DynamicTypeValueReceiver<Integer>, TimeCallback>
- mConsumerToTimeCallback = new SimpleArrayMap<>();
-
- EpochTimePlatformDataSource(Executor uiExecutor, TimeGateway gateway) {
- mUiExecutor = uiExecutor;
- mGateway = gateway;
- }
-
- @Override
- public void registerForData(
- PlatformInt32SourceType sourceType, DynamicTypeValueReceiver<Integer> consumer) {
- TimeCallback timeCallback =
- new TimeCallback() {
- @Override
- public void onPreUpdate() {
- consumer.onPreUpdate();
- }
-
- @Override
- public void onData() {
- long currentEpochTimeSeconds = System.currentTimeMillis() / 1000;
- consumer.onData((int) currentEpochTimeSeconds);
- }
- };
- mGateway.registerForUpdates(mUiExecutor, timeCallback);
- mConsumerToTimeCallback.put(consumer, timeCallback);
- }
-
- @Override
- public void unregisterForData(
- PlatformInt32SourceType sourceType, DynamicTypeValueReceiver<Integer> consumer) {
- TimeCallback timeCallback = mConsumerToTimeCallback.remove(consumer);
- if (timeCallback != null) {
- mGateway.unregisterForUpdates(timeCallback);
- }
- }
- }
-
/** Utility for sensor data source. */
static class SensorGatewayPlatformDataSource implements PlatformDataSource {
private static final String TAG = "SensorGtwPltDataSource";
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/sensor/SensorGateway.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/sensor/SensorGateway.java
index 513f38d..1f16396 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/sensor/SensorGateway.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/sensor/SensorGateway.java
@@ -17,10 +17,12 @@
package androidx.wear.protolayout.expression.pipeline.sensor;
import android.Manifest;
+import android.os.Build.VERSION_CODES;
import androidx.annotation.AnyThread;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresPermission;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
@@ -54,6 +56,7 @@
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@Retention(RetentionPolicy.SOURCE)
+ @RequiresApi(VERSION_CODES.Q)
@IntDef({
SENSOR_DATA_TYPE_INVALID,
SENSOR_DATA_TYPE_HEART_RATE,
@@ -77,6 +80,7 @@
* each day, and any subscriptions to this data type will log the number of steps the user has
* done since 12:00AM local time.
*/
+ @RequiresApi(VERSION_CODES.Q)
@RequiresPermission(Manifest.permission.ACTIVITY_RECOGNITION)
int SENSOR_DATA_TYPE_DAILY_STEP_COUNT = 1;
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
index 7f9e3cb..d2ab0198 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java
@@ -27,8 +27,10 @@
import androidx.annotation.NonNull;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool;
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter;
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString;
@@ -45,6 +47,8 @@
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
@@ -151,6 +155,33 @@
test(DynamicInt32.constant(10).gte(11), false),
test(DynamicInt32.constant(10).gte(10), true),
test(DynamicInt32.constant(10).gte(5), true),
+ // Instant maximum value
+ test(DynamicInstant.withSecondsPrecision(Instant.MAX),
+ Instant.MAX.truncatedTo(ChronoUnit.SECONDS)),
+ // Duration Int overflow
+ test(
+ DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ .durationUntil(DynamicInstant.withSecondsPrecision(Instant.MAX))
+ .toIntSeconds(),
+ (int) Instant.MAX.getEpochSecond()),
+ // Positive duration
+ test(durationOfSeconds(123456L).toIntDays(), 1),
+ test(durationOfSeconds(123456L).toIntHours(), 34),
+ test(durationOfSeconds(123456L).toIntMinutes(), 2057),
+ test(durationOfSeconds(123456L).toIntSeconds(), 123456),
+ test(durationOfSeconds(123456L).getIntDaysPart(), 1),
+ test(durationOfSeconds(123456L).getHoursPart(), 10),
+ test(durationOfSeconds(123456L).getMinutesPart(), 17),
+ test(durationOfSeconds(123456L).getSecondsPart(), 36),
+ // Negative duration
+ test(durationOfSeconds(-123456L).toIntDays(), -1),
+ test(durationOfSeconds(-123456L).toIntHours(), -34),
+ test(durationOfSeconds(-123456L).toIntMinutes(), -2057),
+ test(durationOfSeconds(-123456L).toIntSeconds(), -123456),
+ test(durationOfSeconds(-123456L).getIntDaysPart(), 1),
+ test(durationOfSeconds(-123456L).getHoursPart(), 10),
+ test(durationOfSeconds(-123456L).getMinutesPart(), 17),
+ test(durationOfSeconds(-123456L).getSecondsPart(), 36),
test(
DynamicString.onCondition(DynamicBool.constant(true))
.use(constant("Hello"))
@@ -271,6 +302,17 @@
expectedValue);
}
+ private static DynamicTypeEvaluatorTest.TestCase<Instant> test(
+ DynamicInstant bindUnderTest, Instant instant) {
+ return new DynamicTypeEvaluatorTest.TestCase<>(
+ bindUnderTest.toDynamicInstantProto().toString(),
+ (evaluator, cb) -> {
+ evaluator.bind(bindUnderTest, cb);
+ evaluator.processPendingBindings();
+ },
+ instant);
+ }
+
private static DynamicTypeEvaluatorTest.TestCase<Float> test(
DynamicFloat bindUnderTest, Float expectedValue) {
return new DynamicTypeEvaluatorTest.TestCase<>(
@@ -341,6 +383,12 @@
}
}
+ private static DynamicDuration durationOfSeconds(long seconds) {
+ Instant now = Instant.now();
+ return DynamicInstant.withSecondsPrecision(now)
+ .durationUntil(DynamicInstant.withSecondsPrecision(now.plusSeconds(seconds)));
+ }
+
private static ImmutableMap<String, StateEntryValue> generateExampleState() {
return ImmutableMap.of(
"state_hello_world",
diff --git a/wear/protolayout/protolayout-expression/api/current.txt b/wear/protolayout/protolayout-expression/api/current.txt
index 49d68e38..1e3c3ea 100644
--- a/wear/protolayout/protolayout-expression/api/current.txt
+++ b/wear/protolayout/protolayout-expression/api/current.txt
@@ -104,6 +104,19 @@
method public default byte[] toDynamicColorByteArray();
}
+ public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
+ method public default byte[] toDynamicDurationByteArray();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntSeconds();
+ }
+
public static interface DynamicBuilders.DynamicFloat extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
@@ -156,6 +169,14 @@
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter with();
}
+ public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
+ method public default byte[] toDynamicInstantByteArray();
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
+ }
+
public static interface DynamicBuilders.DynamicInt32 extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
diff --git a/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
index 5ab6ba0..3c2d79b 100644
--- a/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
@@ -104,6 +104,19 @@
method public default byte[] toDynamicColorByteArray();
}
+ public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
+ method public default byte[] toDynamicDurationByteArray();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntSeconds();
+ }
+
public static interface DynamicBuilders.DynamicFloat extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
@@ -156,6 +169,14 @@
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter with();
}
+ public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
+ method public default byte[] toDynamicInstantByteArray();
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
+ }
+
public static interface DynamicBuilders.DynamicInt32 extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
diff --git a/wear/protolayout/protolayout-expression/api/restricted_current.txt b/wear/protolayout/protolayout-expression/api/restricted_current.txt
index 49d68e38..1e3c3ea 100644
--- a/wear/protolayout/protolayout-expression/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-expression/api/restricted_current.txt
@@ -104,6 +104,19 @@
method public default byte[] toDynamicColorByteArray();
}
+ public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
+ method public default byte[] toDynamicDurationByteArray();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntSeconds();
+ }
+
public static interface DynamicBuilders.DynamicFloat extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat animate(float, float, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
@@ -156,6 +169,14 @@
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter with();
}
+ public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
+ method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
+ method public default byte[] toDynamicInstantByteArray();
+ method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
+ }
+
public static interface DynamicBuilders.DynamicInt32 extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int);
method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 animate(int, int, androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec);
diff --git a/wear/protolayout/protolayout-expression/build.gradle b/wear/protolayout/protolayout-expression/build.gradle
index eb396f8..7bb1001 100644
--- a/wear/protolayout/protolayout-expression/build.gradle
+++ b/wear/protolayout/protolayout-expression/build.gradle
@@ -40,7 +40,7 @@
namespace "androidx.wear.protolayout.expression"
defaultConfig {
- minSdkVersion 25
+ minSdkVersion 26
}
buildTypes.all {
consumerProguardFiles "proguard-rules.pro"
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
index 110f68a..68edcea 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
@@ -31,15 +31,16 @@
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedBool;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedColor;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedFloat;
+import androidx.wear.protolayout.expression.FixedValueBuilders.FixedInstant;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedInt32;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedString;
import androidx.wear.protolayout.expression.StateEntryBuilders.StateEntryValue;
import androidx.wear.protolayout.expression.proto.DynamicProto;
import androidx.wear.protolayout.protobuf.ExtensionRegistryLite;
import androidx.wear.protolayout.protobuf.InvalidProtocolBufferException;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
/** Builders for dynamic primitive types used by layout elements. */
public final class DynamicBuilders {
@@ -249,6 +250,101 @@
static final int LOGICAL_OP_TYPE_OR = 2;
/**
+ * The duration part to retrieve using {@link GetDurationPartOp}.
+ *
+ * @since 1.2
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @IntDef({
+ DURATION_PART_TYPE_UNDEFINED,
+ DURATION_PART_TYPE_TOTAL_DAYS,
+ DURATION_PART_TYPE_TOTAL_HOURS,
+ DURATION_PART_TYPE_TOTAL_MINUTES,
+ DURATION_PART_TYPE_TOTAL_SECONDS,
+ DURATION_PART_TYPE_DAYS,
+ DURATION_PART_TYPE_HOURS,
+ DURATION_PART_TYPE_MINUTES,
+ DURATION_PART_TYPE_SECONDS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface DurationPartType {}
+
+ /**
+ * Undefined duration part type.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_UNDEFINED = 0;
+
+ /**
+ * Total number of days in a duration. The fraction part of the result will be truncated. This is
+ * based on the standard definition of a day as 24 hours. Notice that the duration can be
+ * negative, in which case total number of days will be also negative.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_TOTAL_DAYS = 1;
+
+ /**
+ * Total number of hours in a duration. The fraction part of the result will be truncated. Notice
+ * that the duration can be negative, in which case total number of hours will be also negative.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_TOTAL_HOURS = 2;
+
+ /**
+ * Total number of minutes in a duration. The fraction part of the result will be truncated.
+ * Notice that the duration can be negative, in which case total number of minutes will be also
+ * negative.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_TOTAL_MINUTES = 3;
+
+ /**
+ * Total number of seconds in a duration. Notice that the duration can be negative, in which case
+ * total number of seconds will be also negative.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_TOTAL_SECONDS = 4;
+
+ /**
+ * Number of days part in the duration. This represents the absolute value of the total number of
+ * days in the duration based on the 24 hours day definition. The fraction part of the result will
+ * be truncated.
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_DAYS = 5;
+
+ /**
+ * Number of hours part in the duration. This represents the absolute value of remaining hours
+ * when dividing total hours by hours in a day (24 hours).
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_HOURS = 6;
+
+ /**
+ * Number of minutes part in the duration. This represents the absolute value of remaining minutes
+ * when dividing total minutes by minutes in an hour (60 minutes).
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_MINUTES = 7;
+
+ /**
+ * Number of seconds part in the duration. This represents the absolute value of remaining seconds
+ * when dividing total seconds by seconds in a minute (60 seconds).
+ *
+ * @since 1.2
+ */
+ static final int DURATION_PART_TYPE_SECONDS = 8;
+
+ /**
* An arithmetic operation, operating on two Int32 instances. This implements simple binary
* operations of the form "result = LHS <op> RHS", where the available operation types are
* described in {@code ArithmeticOpType}.
@@ -922,9 +1018,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -981,8 +1077,8 @@
+ getFromValue()
+ ", toValue="
+ getToValue()
- + ", spec="
- + getSpec()
+ + ", animationSpec="
+ + getAnimationSpec()
+ "}";
}
@@ -1024,10 +1120,10 @@
* @since 1.2
*/
@NonNull
- public AnimatableFixedInt32.Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 3, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 3, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -1080,9 +1176,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -1134,7 +1230,12 @@
@Override
@NonNull
public String toString() {
- return "AnimatableDynamicInt32{" + "input=" + getInput() + ", spec=" + getSpec() + "}";
+ return "AnimatableDynamicInt32{"
+ + "input="
+ + getInput()
+ + ", animationSpec="
+ + getAnimationSpec()
+ + "}";
}
/** Builder for {@link AnimatableDynamicInt32}. */
@@ -1164,10 +1265,10 @@
* @since 1.2
*/
@NonNull
- public AnimatableDynamicInt32.Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 2, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 2, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -1189,18 +1290,16 @@
*
* <p>For example the following expression is equivalent to {@code result = ((a + b)*c)/d }:
*
- * <pre>
+ * <pre>{@code
* a.plus(b).times(c).div(d);
- * </pre>
+ * }</pre>
*
* More complex expressions can be created by nesting expressions. For example the following
* expression is equivalent to {@code result = (a + b)*(c - d) }:
*
- * <pre>
+ * <pre>{@code
* (a.plus(b)).times(c.minus(d));
- * </pre>
- *
- * .
+ * }</pre>
*
* @since 1.2
*/
@@ -1269,15 +1368,15 @@
*
* @param start The start value of the range.
* @param end The end value of the range.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- static DynamicInt32 animate(int start, int end, @NonNull AnimationSpec spec) {
+ static DynamicInt32 animate(int start, int end, @NonNull AnimationSpec animationSpec) {
return new AnimatableFixedInt32.Builder()
- .setFromValue(start)
- .setToValue(end)
- .setSpec(spec)
- .build();
+ .setFromValue(start)
+ .setToValue(end)
+ .setAnimationSpec(animationSpec)
+ .build();
}
/**
@@ -1300,25 +1399,28 @@
*
* @param stateKey The key to a {@link StateEntryValue} with an int value from the provider's
* state.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- static DynamicInt32 animate(@NonNull String stateKey, @NonNull AnimationSpec spec) {
+ static DynamicInt32 animate(@NonNull String stateKey, @NonNull AnimationSpec animationSpec) {
return new AnimatableDynamicInt32.Builder()
- .setInput(fromState(stateKey))
- .setSpec(spec)
- .build();
+ .setInput(fromState(stateKey))
+ .setAnimationSpec(animationSpec)
+ .build();
}
/**
* Returns a {@link DynamicInt32} that is bound to the value of this {@link DynamicInt32} and
* every time its value is changing, it animates from its current value to the new value.
*
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- default DynamicInt32 animate(@NonNull AnimationSpec spec) {
- return new AnimatableDynamicInt32.Builder().setInput(this).setSpec(spec).build();
+ default DynamicInt32 animate(@NonNull AnimationSpec animationSpec) {
+ return new AnimatableDynamicInt32.Builder()
+ .setInput(this)
+ .setAnimationSpec(animationSpec)
+ .build();
}
/**
@@ -1838,7 +1940,7 @@
@NonNull
default DynamicFloat rem(float other) {
return new ArithmeticFloatOp.Builder()
- .setInputLhs( this.asFloat())
+ .setInputLhs(this.asFloat())
.setInputRhs(DynamicFloat.constant(other))
.setOperationType(DynamicBuilders.ARITHMETIC_OP_TYPE_MODULO)
.build();
@@ -2115,6 +2217,9 @@
if (proto.hasFloatToInt()) {
return FloatToInt32Op.fromProto(proto.getFloatToInt());
}
+ if (proto.hasDurationPart()) {
+ return GetDurationPartOp.fromProto(proto.getDurationPart());
+ }
if (proto.hasAnimatableFixed()) {
return AnimatableFixedInt32.fromProto(proto.getAnimatableFixed());
}
@@ -3325,9 +3430,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -3367,8 +3472,8 @@
+ getFromValue()
+ ", toValue="
+ getToValue()
- + ", spec="
- + getSpec()
+ + ", animationSpec="
+ + getAnimationSpec()
+ "}";
}
@@ -3410,10 +3515,10 @@
* @since 1.2
*/
@NonNull
- public Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 3, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 3, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -3466,9 +3571,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -3503,7 +3608,12 @@
@Override
@NonNull
public String toString() {
- return "AnimatableDynamicFloat{" + "input=" + getInput() + ", spec=" + getSpec() + "}";
+ return "AnimatableDynamicFloat{"
+ + "input="
+ + getInput()
+ + ", animationSpec="
+ + getAnimationSpec()
+ + "}";
}
/** Builder for {@link AnimatableDynamicFloat}. */
@@ -3533,10 +3643,10 @@
* @since 1.2
*/
@NonNull
- public Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 3, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 3, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -3558,18 +3668,16 @@
*
* <p>For example the following expression is equivalent to {@code result = ((a + b)*c)/d }:
*
- * <pre>
+ * <pre>{@code
* a.plus(b).times(c).div(d);
- * </pre>
+ * }</pre>
*
* More complex expressions can be created by nesting expressions. For example the following
* expression is equivalent to {@code result = (a + b)*(c - d) }:
*
- * <pre>
+ * <pre>{@code
* (a.plus(b)).times(c.minus(d));
- * </pre>
- *
- * .
+ * }</pre>
*
* @since 1.2
*/
@@ -3639,14 +3747,14 @@
*
* @param start The start value of the range.
* @param end The end value of the range.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- static DynamicFloat animate(float start, float end, @NonNull AnimationSpec spec) {
+ static DynamicFloat animate(float start, float end, @NonNull AnimationSpec animationSpec) {
return new AnimatableFixedFloat.Builder()
.setFromValue(start)
.setToValue(end)
- .setSpec(spec)
+ .setAnimationSpec(animationSpec)
.build();
}
@@ -3670,13 +3778,13 @@
*
* @param stateKey The key to a {@link StateEntryValue} with a float value from the providers
* state.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- static DynamicFloat animate(@NonNull String stateKey, @NonNull AnimationSpec spec) {
+ static DynamicFloat animate(@NonNull String stateKey, @NonNull AnimationSpec animationSpec) {
return new AnimatableDynamicFloat.Builder()
.setInput(fromState(stateKey))
- .setSpec(spec)
+ .setAnimationSpec(animationSpec)
.build();
}
@@ -3684,11 +3792,14 @@
* Returns a {@link DynamicFloat} that is bound to the value of this {@link DynamicFloat} and
* every time its value is changing, it animates from its current value to the new value.
*
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- default DynamicFloat animate(@NonNull AnimationSpec spec) {
- return new AnimatableDynamicFloat.Builder().setInput(this).setSpec(spec).build();
+ default DynamicFloat animate(@NonNull AnimationSpec animationSpec) {
+ return new AnimatableDynamicFloat.Builder()
+ .setInput(this)
+ .setAnimationSpec(animationSpec)
+ .build();
}
/**
@@ -3730,8 +3841,6 @@
@SuppressWarnings("KotlinOperator")
@NonNull
default DynamicFloat plus(@NonNull DynamicFloat other) {
-
- // overloaded operators.
return new ArithmeticFloatOp.Builder()
.setInputLhs(this)
.setInputRhs(other)
@@ -4036,7 +4145,7 @@
}
/**
- * reates a {@link DynamicFloat} containing the reminder of dividing this {@link DynamicFloat}
+ * Creates a {@link DynamicFloat} containing the reminder of dividing this {@link DynamicFloat}
* by a float; As an example, the following is equal to {@code DynamicFloat.constant(1.5f)}
*
* <pre>
@@ -4060,7 +4169,7 @@
}
/**
- * reates a {@link DynamicFloat} containing the reminder of dividing this {@link DynamicFloat}
+ * Creates a {@link DynamicFloat} containing the reminder of dividing this {@link DynamicFloat}
* by a {@link DynamicInt32}; As an example, the following is equal to {@code
* DynamicFloat.constant(2f)}
*
@@ -5286,9 +5395,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -5328,8 +5437,8 @@
+ getFromArgb()
+ ", toArgb="
+ getToArgb()
- + ", spec="
- + getSpec()
+ + ", animationSpec="
+ + getAnimationSpec()
+ "}";
}
@@ -5371,10 +5480,10 @@
* @since 1.2
*/
@NonNull
- public Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 3, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 3, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -5427,9 +5536,9 @@
* @since 1.2
*/
@Nullable
- public AnimationSpec getSpec() {
- if (mImpl.hasSpec()) {
- return AnimationSpec.fromProto(mImpl.getSpec());
+ public AnimationSpec getAnimationSpec() {
+ if (mImpl.hasAnimationSpec()) {
+ return AnimationSpec.fromProto(mImpl.getAnimationSpec());
} else {
return null;
}
@@ -5464,7 +5573,12 @@
@Override
@NonNull
public String toString() {
- return "AnimatableDynamicColor{" + "input=" + getInput() + ", spec=" + getSpec() + "}";
+ return "AnimatableDynamicColor{"
+ + "input="
+ + getInput()
+ + ", animationSpec="
+ + getAnimationSpec()
+ + "}";
}
/** Builder for {@link AnimatableDynamicColor}. */
@@ -5494,10 +5608,10 @@
* @since 1.2
*/
@NonNull
- public Builder setSpec(@NonNull AnimationSpec spec) {
- mImpl.setSpec(spec.toProto());
+ public Builder setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mImpl.setAnimationSpec(animationSpec.toProto());
mFingerprint.recordPropertyUpdate(
- 3, checkNotNull(spec.getFingerprint()).aggregateValueAsInt());
+ 3, checkNotNull(animationSpec.getFingerprint()).aggregateValueAsInt());
return this;
}
@@ -5580,15 +5694,15 @@
*
* @param start The start value of the range.
* @param end The end value of the range.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
static DynamicColor animate(
- @ColorInt int start, @ColorInt int end, @NonNull AnimationSpec spec) {
+ @ColorInt int start, @ColorInt int end, @NonNull AnimationSpec animationSpec) {
return new AnimatableFixedColor.Builder()
.setFromArgb(start)
.setToArgb(end)
- .setSpec(spec)
+ .setAnimationSpec(animationSpec)
.build();
}
@@ -5597,7 +5711,7 @@
* the state value changes, this {@link DynamicColor} will animate from its current value to the
* new value (from the state).
*
- * @param stateKey The key to a {@link StateEntryValue} with a color value from the providers
+ * @param stateKey The key to a {@link StateEntryValue} with a color value from the provider's
* state.
*/
@NonNull
@@ -5610,15 +5724,15 @@
* the state value changes, this {@link DynamicColor} will animate from its current value to the
* new value (from the state).
*
- * @param stateKey The key to a {@link StateEntryValue} with a color value from the providers
+ * @param stateKey The key to a {@link StateEntryValue} with a color value from the provider's
* state.
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- static DynamicColor animate(@NonNull String stateKey, @NonNull AnimationSpec spec) {
+ static DynamicColor animate(@NonNull String stateKey, @NonNull AnimationSpec animationSpec) {
return new AnimatableDynamicColor.Builder()
.setInput(fromState(stateKey))
- .setSpec(spec)
+ .setAnimationSpec(animationSpec)
.build();
}
@@ -5626,11 +5740,14 @@
* Returns a {@link DynamicColor} that is bound to the value of this {@link DynamicColor} and
* every time its value is changing, it animates from its current value to the new value.
*
- * @param spec The animation parameters.
+ * @param animationSpec The animation parameters.
*/
@NonNull
- default DynamicColor animate(@NonNull AnimationSpec spec) {
- return new AnimatableDynamicColor.Builder().setInput(this).setSpec(spec).build();
+ default DynamicColor animate(@NonNull AnimationSpec animationSpec) {
+ return new AnimatableDynamicColor.Builder()
+ .setInput(this)
+ .setAnimationSpec(animationSpec)
+ .build();
}
/**
@@ -5690,6 +5807,677 @@
}
/**
+ * A dynamic time instant that sources its value from the platform.
+ *
+ * @since 1.2
+ */
+ static final class PlatformTimeSource implements DynamicInstant {
+ private final DynamicProto.PlatformTimeSource mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ PlatformTimeSource(DynamicProto.PlatformTimeSource impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static PlatformTimeSource fromProto(@NonNull DynamicProto.PlatformTimeSource proto) {
+ return new PlatformTimeSource(proto, null);
+ }
+
+ @NonNull
+ DynamicProto.PlatformTimeSource toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public DynamicProto.DynamicInstant toDynamicInstantProto() {
+ return DynamicProto.DynamicInstant.newBuilder().setPlatformSource(mImpl).build();
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "PlatformTimeSource";
+ }
+
+ /** Builder for {@link PlatformTimeSource}. */
+ public static final class Builder implements DynamicInstant.Builder {
+ private final DynamicProto.PlatformTimeSource.Builder mImpl =
+ DynamicProto.PlatformTimeSource.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(-1895976938);
+
+ public Builder() {}
+
+ @Override
+ @NonNull
+ public PlatformTimeSource build() {
+ return new PlatformTimeSource(mImpl.build(), mFingerprint);
+ }
+ }
+ }
+
+ /**
+ * Interface defining a dynamic time instant type.
+ *
+ * <p> {@link DynamicInstant} precision is seconds. Thus, any time or duration operation will
+ * operate on that precision level.
+ *
+ * @since 1.2
+ */
+ public interface DynamicInstant extends DynamicType {
+ /**
+ * Get the protocol buffer representation of this object.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ DynamicProto.DynamicInstant toDynamicInstantProto();
+
+ /**
+ * Creates a {@link DynamicInstant} from a byte array generated by {@link
+ * #toDynamicInstantByteArray()}.
+ */
+ @NonNull
+ static DynamicInstant fromByteArray(@NonNull byte[] byteArray) {
+ try {
+ return dynamicInstantFromProto(
+ DynamicProto.DynamicInstant.parseFrom(
+ byteArray, ExtensionRegistryLite.getEmptyRegistry()));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalArgumentException("Byte array could not be parsed into DynamicInstant", e);
+ }
+ }
+
+ /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+ @NonNull
+ default byte[] toDynamicInstantByteArray() {
+ return toDynamicInstantProto().toByteArray();
+ }
+
+
+ /**
+ * Creates a constant-valued {@link DynamicInstant} from an {@link Instant}. If {@link Instant}
+ * precision is greater than seconds, then any excess precision information will be dropped.
+ */
+ @NonNull
+ static DynamicInstant withSecondsPrecision(@NonNull Instant instant) {
+ return new FixedInstant.Builder().setEpochSeconds(instant.getEpochSecond()).build();
+ }
+
+ /**
+ * Creates a {@link DynamicInstant} that updates its value periodically from the system time.
+ */
+ @NonNull
+ static DynamicInstant platformTimeWithSecondsPrecision() {
+ return new PlatformTimeSource.Builder().build();
+ }
+
+ /**
+ * Returns duration between the two {@link DynamicInstant} instances as a {@link
+ * DynamicDuration}. The resulted duration is inclusive of the start instant and exclusive of
+ * the end; As an example, the following expression yields a duration object representing 10
+ * seconds:
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(10L))
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(20L)));
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicDuration} containing the result of the operation.
+ */
+ @NonNull
+ default DynamicDuration durationUntil(@NonNull DynamicInstant to) {
+ return new BetweenDuration.Builder().setStartInclusive(this).setEndExclusive(to).build();
+ }
+
+ /**
+ * Get the fingerprint for this object or null if unknown.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ Fingerprint getFingerprint();
+
+ /**
+ * Builder to create {@link DynamicInstant} objects.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ interface Builder {
+
+ /** Builds an instance with values accumulated in this Builder. */
+ @NonNull
+ DynamicInstant build();
+ }
+ }
+
+ /**
+ * Creates a new wrapper instance from the proto. Intended for testing purposes only. An object
+ * created using this method can't be added to any other wrapper.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public static DynamicInstant dynamicInstantFromProto(@NonNull DynamicProto.DynamicInstant proto) {
+ if (proto.hasFixed()) {
+ return FixedInstant.fromProto(proto.getFixed());
+ }
+ if (proto.hasPlatformSource()) {
+ return PlatformTimeSource.fromProto(proto.getPlatformSource());
+ }
+ throw new IllegalStateException("Proto was not a recognised instance of DynamicInstant");
+ }
+
+ /**
+ * A dynamic duration type that represents the duration between two dynamic time instants.
+ *
+ * @since 1.2
+ */
+ static final class BetweenDuration implements DynamicDuration {
+ private final DynamicProto.BetweenDuration mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ BetweenDuration(DynamicProto.BetweenDuration impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /**
+ * Gets the time instant value marking the start of the duration.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public DynamicInstant getStartInclusive() {
+ if (mImpl.hasStartInclusive()) {
+ return DynamicBuilders.dynamicInstantFromProto(mImpl.getStartInclusive());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the time instant value marking the end of the duration.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public DynamicInstant getEndExclusive() {
+ if (mImpl.hasEndExclusive()) {
+ return DynamicBuilders.dynamicInstantFromProto(mImpl.getEndExclusive());
+ } else {
+ return null;
+ }
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static BetweenDuration fromProto(@NonNull DynamicProto.BetweenDuration proto) {
+ return new BetweenDuration(proto, null);
+ }
+
+ @NonNull
+ DynamicProto.BetweenDuration toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public DynamicProto.DynamicDuration toDynamicDurationProto() {
+ return DynamicProto.DynamicDuration.newBuilder().setBetween(mImpl).build();
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "BetweenDuration{"
+ + "startInclusive="
+ + getStartInclusive()
+ + ", endExclusive="
+ + getEndExclusive()
+ + "}";
+ }
+
+ /** Builder for {@link BetweenDuration}. */
+ public static final class Builder implements DynamicDuration.Builder {
+ private final DynamicProto.BetweenDuration.Builder mImpl =
+ DynamicProto.BetweenDuration.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(-1615230958);
+
+ public Builder() {}
+
+ /**
+ * Sets the time instant value marking the start of the duration.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setStartInclusive(@NonNull DynamicInstant startInclusive) {
+ mImpl.setStartInclusive(startInclusive.toDynamicInstantProto());
+ mFingerprint.recordPropertyUpdate(
+ 1, checkNotNull(startInclusive.getFingerprint()).aggregateValueAsInt());
+ return this;
+ }
+
+ /**
+ * Sets the time instant value marking the end of the duration.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setEndExclusive(@NonNull DynamicInstant endExclusive) {
+ mImpl.setEndExclusive(endExclusive.toDynamicInstantProto());
+ mFingerprint.recordPropertyUpdate(
+ 2, checkNotNull(endExclusive.getFingerprint()).aggregateValueAsInt());
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public BetweenDuration build() {
+ return new BetweenDuration(mImpl.build(), mFingerprint);
+ }
+ }
+ }
+
+ /**
+ * Interface defining a dynamic duration type.
+ *
+ * @since 1.2
+ */
+ public interface DynamicDuration extends DynamicType {
+ /**
+ * Get the protocol buffer representation of this object.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ DynamicProto.DynamicDuration toDynamicDurationProto();
+
+ /**
+ * Creates a {@link DynamicDuration} from a byte array generated by {@link
+ * #toDynamicDurationByteArray()}.
+ */
+ @NonNull
+ static DynamicDuration fromByteArray(@NonNull byte[] byteArray) {
+ try {
+ return dynamicDurationFromProto(
+ DynamicProto.DynamicDuration.parseFrom(
+ byteArray, ExtensionRegistryLite.getEmptyRegistry()));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalArgumentException(
+ "Byte array could not be parsed into DynamicDuration", e);
+ }
+ }
+
+ /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+ @NonNull
+ default byte[] toDynamicDurationByteArray() {
+ return toDynamicDurationProto().toByteArray();
+ }
+
+
+ /**
+ * Returns the total number of days in a {@link DynamicDuration} as a {@link DynamicInt32}. The
+ * fraction part of the result will be truncated. This is based on the standard definition of a
+ * day as 24 hours. As an example, the following is equal to {@code DynamicInt32.constant(1)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .toIntDays();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ * Integer overflow can occur if the result of the operation is larger than {@link
+ * Integer#MAX_VALUE}.
+ */
+ @NonNull
+ default DynamicInt32 toIntDays() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_TOTAL_DAYS)
+ .build();
+ }
+
+ /**
+ * Returns the total number of hours in a {@link DynamicDuration} as a {@link DynamicInt32}. The
+ * fraction part of the result will be truncated. As an example, the following is equal to
+ * {@code DynamicInt32.constant(34)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .toIntHours();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ * Integer overflow can occur if the result of the operation is larger than {@link
+ * Integer#MAX_VALUE}.
+ */
+ @NonNull
+ default DynamicInt32 toIntHours() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_TOTAL_HOURS)
+ .build();
+ }
+
+ /**
+ * Returns the total number of minutes in a {@link DynamicDuration} as a {@link DynamicInt32}.
+ * The fraction part of the result will be truncated. As an example, the following is equal to
+ * {@code DynamicInt32.constant(2057)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .toIntMinutes();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ * Integer overflow can occur if the result of the operation is larger than {@link
+ * Integer#MAX_VALUE}.
+ */
+ @NonNull
+ default DynamicInt32 toIntMinutes() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_TOTAL_MINUTES)
+ .build();
+ }
+
+ /**
+ * Returns the total number of seconds in a {@link DynamicDuration} as a {@link DynamicInt32}.
+ * As an example, the following is equal to {@code DynamicInt32.constant(123456)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .toIntSeconds();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ * Integer overflow can occur if the result of the operation is larger than {@link
+ * Integer#MAX_VALUE}.
+ */
+ @NonNull
+ default DynamicInt32 toIntSeconds() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_TOTAL_SECONDS)
+ .build();
+ }
+
+ /**
+ * Returns the total number of days in a duration as a {@link DynamicInt32}. This represents the
+ * absolute value of the total number of days in the duration based on the 24 hours day
+ * definition. The fraction part of the result will be truncated; As an example, the following
+ * is equal to {@code DynamicInt32.constant(1)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .getIntDaysPart();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ * Integer overflow can occur if the result of the operation is larger than {@link
+ * Integer#MAX_VALUE}.
+ */
+ @NonNull
+ default DynamicInt32 getIntDaysPart() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_DAYS)
+ .build();
+ }
+
+ /**
+ * Returns the number of hours part in the duration as a {@link DynamicInt32}. This represents
+ * the absolute value of remaining hours when dividing total hours by hours in a day (24 hours);
+ * As an example, the following is equal to {@code DynamicInt32.constant(10)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .getHoursPart();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ */
+ @NonNull
+ default DynamicInt32 getHoursPart() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_HOURS)
+ .build();
+ }
+
+ /**
+ * Returns the number of minutes part in the duration as a {@link DynamicInt32}. This represents
+ * the absolute value of remaining minutes when dividing total minutes by minutes in an hour (60
+ * minutes). As an example, the following is equal to {@code DynamicInt32.constant(17)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .getMinutesPart();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ */
+ @NonNull
+ default DynamicInt32 getMinutesPart() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_MINUTES)
+ .build();
+ }
+
+ /**
+ * Returns the number of seconds part in the duration as a {@link DynamicInt32}. This represents
+ * the absolute value of remaining seconds when dividing total seconds by seconds in a minute
+ * (60 seconds); As an example, the following is equal to {@code DynamicInt32.constant(36)}
+ *
+ * <pre>
+ * DynamicInstant.withSecondsPrecision(Instant.EPOCH)
+ * .durationUntil(DynamicInstant.withSecondsPrecision(Instant.ofEpochSecond(123456L)))
+ * .getSecondsPart();
+ * </pre>
+ *
+ * @return a new instance of {@link DynamicInt32} containing the result of the operation.
+ */
+ @NonNull
+ default DynamicInt32 getSecondsPart() {
+ return new GetDurationPartOp.Builder()
+ .setInput(this)
+ .setDurationPart(DURATION_PART_TYPE_SECONDS)
+ .build();
+ }
+
+ /**
+ * Get the fingerprint for this object or null if unknown.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ Fingerprint getFingerprint();
+
+ /**
+ * Builder to create {@link DynamicDuration} objects.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ interface Builder {
+
+ /** Builds an instance with values accumulated in this Builder. */
+ @NonNull
+ DynamicDuration build();
+ }
+ }
+
+ /**
+ * Creates a new wrapper instance from the proto. Intended for testing purposes only. An object
+ * created using this method can't be added to any other wrapper.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public static DynamicDuration dynamicDurationFromProto(
+ @NonNull DynamicProto.DynamicDuration proto) {
+ if (proto.hasBetween()) {
+ return BetweenDuration.fromProto(proto.getBetween());
+ }
+ throw new IllegalStateException("Proto was not a recognised instance of DynamicDuration");
+ }
+
+ /**
+ * Retrieve the specified duration part of a {@link DynamicDuration} instance as a {@link
+ * DynamicInt32}.
+ *
+ * @since 1.2
+ */
+ static final class GetDurationPartOp implements DynamicInt32 {
+ private final DynamicProto.GetDurationPartOp mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ GetDurationPartOp(DynamicProto.GetDurationPartOp impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /**
+ * Gets the duration input.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public DynamicDuration getInput() {
+ if (mImpl.hasInput()) {
+ return DynamicBuilders.dynamicDurationFromProto(mImpl.getInput());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the duration part to retrieve.
+ *
+ * @since 1.2
+ */
+ @DurationPartType
+ public int getDurationPart() {
+ return mImpl.getDurationPart().getNumber();
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static GetDurationPartOp fromProto(@NonNull DynamicProto.GetDurationPartOp proto) {
+ return new GetDurationPartOp(proto, null);
+ }
+
+ @NonNull
+ DynamicProto.GetDurationPartOp toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public DynamicProto.DynamicInt32 toDynamicInt32Proto() {
+ return DynamicProto.DynamicInt32.newBuilder().setDurationPart(mImpl).build();
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "GetDurationPartOp{"
+ + "input="
+ + getInput()
+ + ", durationPart="
+ + getDurationPart()
+ + "}";
+ }
+
+ /** Builder for {@link GetDurationPartOp}. */
+ public static final class Builder implements DynamicInt32.Builder {
+ private final DynamicProto.GetDurationPartOp.Builder mImpl =
+ DynamicProto.GetDurationPartOp.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(-225941123);
+
+ public Builder() {}
+
+ /**
+ * Sets the duration input.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setInput(@NonNull DynamicDuration input) {
+ mImpl.setInput(input.toDynamicDurationProto());
+ mFingerprint.recordPropertyUpdate(
+ 1, checkNotNull(input.getFingerprint()).aggregateValueAsInt());
+ return this;
+ }
+
+ /**
+ * Sets the duration part to retrieve.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setDurationPart(@DurationPartType int durationPart) {
+ mImpl.setDurationPart(DynamicProto.DurationPartType.forNumber(durationPart));
+ mFingerprint.recordPropertyUpdate(2, durationPart);
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public GetDurationPartOp build() {
+ return new GetDurationPartOp(mImpl.build(), mFingerprint);
+ }
+ }
+ }
+
+ /**
* Interface to be used as a base type for all other dynamic types. This is not consumed by any
* Tile elements, it exists just as a marker interface for use internally in the Tiles library.
*/
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
index 4ca0ed2..7320b75 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
@@ -49,7 +49,7 @@
}
/**
- * Gets the value. Intended for testing purposes only.
+ * Gets the value.
*
* @since 1.2
*/
@@ -499,4 +499,86 @@
}
}
}
+
+ /**
+ * A fixed time instant type.
+ *
+ * @since 1.2
+ */
+ static final class FixedInstant implements DynamicBuilders.DynamicInstant {
+ private final FixedProto.FixedInstant mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ FixedInstant(FixedProto.FixedInstant impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /**
+ * Gets the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.
+ *
+ * @since 1.2
+ */
+ public long getEpochSeconds() {
+ return mImpl.getEpochSeconds();
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static FixedInstant fromProto(@NonNull FixedProto.FixedInstant proto) {
+ return new FixedInstant(proto, null);
+ }
+
+ @NonNull
+ FixedProto.FixedInstant toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public DynamicProto.DynamicInstant toDynamicInstantProto() {
+ return DynamicProto.DynamicInstant.newBuilder().setFixed(mImpl).build();
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "FixedInstant{" + "epochSeconds=" + getEpochSeconds() + "}";
+ }
+
+ /** Builder for {@link FixedInstant}. */
+ public static final class Builder implements DynamicBuilders.DynamicInstant.Builder {
+ private final FixedProto.FixedInstant.Builder mImpl = FixedProto.FixedInstant.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(-1986552556);
+
+ public Builder() {}
+
+ /**
+ * Sets the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setEpochSeconds(long epochSeconds) {
+ mImpl.setEpochSeconds(epochSeconds);
+ mFingerprint.recordPropertyUpdate(1, Long.hashCode(epochSeconds));
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public FixedInstant build() {
+ return new FixedInstant(mImpl.build(), mFingerprint);
+ }
+ }
+ }
}
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
index b3d3eda..34e1e00 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
@@ -74,12 +74,13 @@
DynamicColor animatedColor = DynamicColor.animate(startColor, endColor);
DynamicColor animatedColorWithSpec = DynamicColor.animate(startColor, endColor, SPEC);
- assertThat(animatedColor.toDynamicColorProto().getAnimatableFixed().hasSpec()).isFalse();
+ assertThat(animatedColor.toDynamicColorProto().getAnimatableFixed().hasAnimationSpec())
+ .isFalse();
assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableFixed().getFromArgb())
.isEqualTo(startColor);
assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableFixed().getToArgb())
.isEqualTo(endColor);
- assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableFixed().getSpec())
+ assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableFixed().getAnimationSpec())
.isEqualTo(SPEC.toProto());
}
@@ -93,7 +94,7 @@
.toString())
.isEqualTo(
"AnimatableFixedColor{"
- + "fromArgb=1, toArgb=2, spec=AnimationSpec{"
+ + "fromArgb=1, toArgb=2, animationSpec=AnimationSpec{"
+ "durationMillis=0, delayMillis=0, easing=null, repeatable=null}}");
}
@@ -104,11 +105,13 @@
DynamicColor animatedColor = DynamicColor.animate(STATE_KEY);
DynamicColor animatedColorWithSpec = DynamicColor.animate(STATE_KEY, SPEC);
- assertThat(animatedColor.toDynamicColorProto().getAnimatableDynamic().hasSpec()).isFalse();
+ assertThat(animatedColor.toDynamicColorProto().getAnimatableDynamic().hasAnimationSpec())
+ .isFalse();
assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableDynamic().getInput())
.isEqualTo(stateColor.toDynamicColorProto());
- assertThat(animatedColorWithSpec.toDynamicColorProto().getAnimatableDynamic().getSpec())
- .isEqualTo(SPEC.toProto());
+ assertThat(
+ animatedColorWithSpec.toDynamicColorProto().getAnimatableDynamic().getAnimationSpec()
+ ).isEqualTo(SPEC.toProto());
assertThat(animatedColor.toDynamicColorProto())
.isEqualTo(stateColor.animate().toDynamicColorProto());
}
@@ -121,7 +124,7 @@
.toString())
.isEqualTo(
"AnimatableDynamicColor{"
- + "input=StateColorSource{sourceKey=key}, spec=AnimationSpec{"
+ + "input=StateColorSource{sourceKey=key}, animationSpec=AnimationSpec{"
+ "durationMillis=0, delayMillis=1, easing=null, repeatable=null}}");
}
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
index 731406e..dc0344e 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
@@ -153,12 +153,13 @@
DynamicFloat animatedFloat = DynamicFloat.animate(startFloat, endFloat);
DynamicFloat animatedFloatWithSpec = DynamicFloat.animate(startFloat, endFloat, SPEC);
- assertThat(animatedFloat.toDynamicFloatProto().getAnimatableFixed().hasSpec()).isFalse();
+ assertThat(animatedFloat.toDynamicFloatProto().getAnimatableFixed().hasAnimationSpec())
+ .isFalse();
assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableFixed().getFromValue())
.isEqualTo(startFloat);
assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableFixed().getToValue())
.isEqualTo(endFloat);
- assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableFixed().getSpec())
+ assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableFixed().getAnimationSpec())
.isEqualTo(SPEC.toProto());
}
@@ -171,7 +172,7 @@
new AnimationSpec.Builder().setDelayMillis(0).build())
.toString())
.isEqualTo(
- "AnimatableFixedFloat{fromValue=1.0, toValue=2.0, spec=AnimationSpec{"
+ "AnimatableFixedFloat{fromValue=1.0, toValue=2.0, animationSpec=AnimationSpec{"
+ "durationMillis=0, delayMillis=0, easing=null, repeatable=null}}");
}
@@ -182,11 +183,13 @@
DynamicFloat animatedFloat = DynamicFloat.animate(STATE_KEY);
DynamicFloat animatedFloatWithSpec = DynamicFloat.animate(STATE_KEY, SPEC);
- assertThat(animatedFloat.toDynamicFloatProto().getAnimatableDynamic().hasSpec()).isFalse();
+ assertThat(animatedFloat.toDynamicFloatProto().getAnimatableDynamic().hasAnimationSpec())
+ .isFalse();
assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableDynamic().getInput())
.isEqualTo(stateFloat.toDynamicFloatProto());
- assertThat(animatedFloatWithSpec.toDynamicFloatProto().getAnimatableDynamic().getSpec())
- .isEqualTo(SPEC.toProto());
+ assertThat(
+ animatedFloatWithSpec.toDynamicFloatProto().getAnimatableDynamic().getAnimationSpec()
+ ).isEqualTo(SPEC.toProto());
assertThat(animatedFloat.toDynamicFloatProto())
.isEqualTo(stateFloat.animate().toDynamicFloatProto());
}
@@ -199,7 +202,7 @@
.toString())
.isEqualTo(
"AnimatableDynamicFloat{"
- + "input=StateFloatSource{sourceKey=key}, spec=AnimationSpec{"
+ + "input=StateFloatSource{sourceKey=key}, animationSpec=AnimationSpec{"
+ "durationMillis=0, delayMillis=1, easing=null, repeatable=null}}");
}
diff --git a/wear/protolayout/protolayout-proto/src/main/proto/dynamic.proto b/wear/protolayout/protolayout-proto/src/main/proto/dynamic.proto
index 52dfa35..67d6ff8 100644
--- a/wear/protolayout/protolayout-proto/src/main/proto/dynamic.proto
+++ b/wear/protolayout/protolayout-proto/src/main/proto/dynamic.proto
@@ -26,9 +26,6 @@
// "ACTIVITY_RECOGNITION" permission granted to it. If this permission is not
// present, this source type will never yield any data.
PLATFORM_INT32_SOURCE_TYPE_DAILY_STEP_COUNT = 2;
-
- // The current epoch time in seconds.
- PLATFORM_INT32_SOURCE_TYPE_EPOCH_TIME_SECONDS = 3;
}
// A dynamic Int32 which sources its data from some platform data source, e.g.
@@ -141,7 +138,7 @@
int32 to_value = 2;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 3;
+ AnimationSpec animation_spec = 3;
}
// A dynamic interpolation node. This will watch the value of its input and,
@@ -157,7 +154,7 @@
DynamicInt32 input = 1;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 2;
+ AnimationSpec animation_spec = 2;
}
// A dynamic int32 type.
@@ -189,6 +186,7 @@
StateInt32Source state_source = 4;
ConditionalInt32Op conditional_op = 5;
FloatToInt32Op float_to_int = 6;
+ GetDurationPartOp duration_part = 7;
AnimatableFixedInt32 animatable_fixed = 8;
AnimatableDynamicInt32 animatable_dynamic = 9;
}
@@ -319,7 +317,7 @@
float to_value = 2;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 3;
+ AnimationSpec animation_spec = 3;
}
// A dynamic interpolation node. This will watch the value of its input and,
@@ -335,7 +333,7 @@
DynamicFloat input = 1;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 3;
+ AnimationSpec animation_spec = 3;
}
// A dynamic float type.
@@ -490,7 +488,7 @@
uint32 to_argb = 2;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 3;
+ AnimationSpec animation_spec = 3;
}
// A dynamic interpolation node. This will watch the value of its input and,
@@ -506,7 +504,7 @@
DynamicColor input = 1;
// The animation parameters for duration, delay, etc.
- AnimationSpec spec = 3;
+ AnimationSpec animation_spec = 3;
}
// A dynamic color type.
@@ -518,3 +516,86 @@
AnimatableDynamicColor animatable_dynamic = 4;
}
}
+
+// A dynamic time instant that sources its value from the platform.
+message PlatformTimeSource {}
+
+// A dynamic time instant type.
+message DynamicInstant {
+ oneof inner {
+ FixedInstant fixed = 1;
+ PlatformTimeSource platform_source = 2;
+ }
+}
+
+// A dynamic duration type that represents the duration between two dynamic time
+// instants.
+message BetweenDuration {
+ // The time instant value marking the start of the duration.
+ DynamicInstant start_inclusive = 1;
+
+ // The time instant value marking the end of the duration.
+ DynamicInstant end_exclusive = 2;
+}
+
+// A dynamic duration type.
+message DynamicDuration {
+ oneof inner {
+ BetweenDuration between = 1;
+ }
+}
+
+// The duration part to retrieve using GetDurationPartOp.
+enum DurationPartType {
+ // Undefined duration part type.
+ DURATION_PART_TYPE_UNDEFINED = 0;
+
+ // Total number of days in a duration. The fraction part of the result will be
+ // truncated. This is based on the standard definition of a day as 24 hours.
+ // Notice that the duration can be negative, in which case total number of
+ // days will be also negative.
+ DURATION_PART_TYPE_TOTAL_DAYS = 1;
+
+ // Total number of hours in a duration. The fraction part of the result will
+ // be truncated. Notice that the duration can be negative, in which case total
+ // number of hours will be also negative.
+ DURATION_PART_TYPE_TOTAL_HOURS = 2;
+
+ // Total number of minutes in a duration. The fraction part of the result will
+ // be truncated. Notice that the duration can be negative, in which case total
+ // number of minutes will be also negative.
+ DURATION_PART_TYPE_TOTAL_MINUTES = 3;
+
+ // Total number of seconds in a duration. Notice that the duration can be
+ // negative, in which case total number of seconds will be also negative.
+ DURATION_PART_TYPE_TOTAL_SECONDS = 4;
+
+ // Number of days part in the duration. This represents the absolute value of
+ // the total number of days in the duration based on the 24 hours day
+ // definition. The fraction part of the result will be truncated.
+ DURATION_PART_TYPE_DAYS = 5;
+
+ // Number of hours part in the duration. This represents the absolute value of
+ // remaining hours when dividing total hours by hours in a day (24 hours).
+ DURATION_PART_TYPE_HOURS = 6;
+
+ // Number of minutes part in the duration. This represents the absolute value
+ // of remaining minutes when dividing total minutes by minutes in an hour (60
+ // minutes).
+ DURATION_PART_TYPE_MINUTES = 7;
+
+ // Number of seconds part in the duration. This represents the absolute value
+ // of remaining seconds when dividing total seconds by seconds in a minute (60
+ // seconds).
+ DURATION_PART_TYPE_SECONDS = 8;
+}
+
+// Retrieve the specified duration part of a DynamicDuration instance as a
+// DynamicInt32.
+message GetDurationPartOp {
+ // The duration input.
+ DynamicDuration input = 1;
+
+ // The duration part to retrieve.
+ DurationPartType duration_part = 2;
+}
diff --git a/wear/protolayout/protolayout-proto/src/main/proto/fixed.proto b/wear/protolayout/protolayout-proto/src/main/proto/fixed.proto
index f09c002..bc87d47 100644
--- a/wear/protolayout/protolayout-proto/src/main/proto/fixed.proto
+++ b/wear/protolayout/protolayout-proto/src/main/proto/fixed.proto
@@ -36,3 +36,10 @@
// The color value, in ARGB format.
uint32 argb = 1;
}
+
+// A fixed time instant type.
+message FixedInstant {
+ // The number of seconds that have elapsed since 00:00:00 UTC on 1 January
+ // 1970.
+ int64 epoch_seconds = 1;
+}
diff --git a/wear/protolayout/protolayout/api/current.txt b/wear/protolayout/protolayout/api/current.txt
index 708d1ef..497290d 100644
--- a/wear/protolayout/protolayout/api/current.txt
+++ b/wear/protolayout/protolayout/api/current.txt
@@ -177,9 +177,7 @@
method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
- method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
- method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
}
public static interface DimensionBuilders.ContainerDimension {
@@ -219,14 +217,6 @@
method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
}
- public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
- }
-
- public static final class DimensionBuilders.ExpandedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
- ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
- }
-
public static interface DimensionBuilders.ImageDimension {
}
@@ -263,14 +253,6 @@
method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
}
- public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension {
- }
-
- public static final class DimensionBuilders.WrappedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder {
- ctor public DimensionBuilders.WrappedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp build();
- }
-
public final class LayoutElementBuilders {
field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
field public static final int ARC_ANCHOR_END = 3; // 0x3
@@ -857,10 +839,26 @@
}
public final class ResourceBuilders {
+ field public static final int ANIMATED_IMAGE_FORMAT_AVD = 1; // 0x1
+ field public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0; // 0x0
field public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
field public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
}
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method @DrawableRes public int getResourceId();
+ method public androidx.wear.protolayout.TriggerBuilders.Trigger? getStartTrigger();
+ }
+
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setStartTrigger(androidx.wear.protolayout.TriggerBuilders.Trigger);
+ }
+
public static final class ResourceBuilders.AndroidImageResourceByResId {
method @DrawableRes public int getResourceId();
}
@@ -871,15 +869,33 @@
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
}
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getProgress();
+ method @DrawableRes public int getResourceId();
+ }
+
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setProgress(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ }
+
public static final class ResourceBuilders.ImageResource {
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId? getAndroidAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId? getAndroidSeekableAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource? getInlineResource();
}
public static final class ResourceBuilders.ImageResource.Builder {
ctor public ResourceBuilders.ImageResource.Builder();
method public androidx.wear.protolayout.ResourceBuilders.ImageResource build();
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId);
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidSeekableAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.protolayout.ResourceBuilders.InlineImageResource);
}
@@ -964,6 +980,32 @@
method public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.protolayout.TimelineBuilders.TimeInterval);
}
+ public final class TriggerBuilders {
+ method public static androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ method public static androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger createOnLoadTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool? getTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger.Builder {
+ ctor public TriggerBuilders.OnConditionMetTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger build();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger.Builder setTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger.Builder {
+ ctor public TriggerBuilders.OnLoadTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger build();
+ }
+
+ public static interface TriggerBuilders.Trigger {
+ }
+
public final class TypeBuilders {
}
diff --git a/wear/protolayout/protolayout/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
index 07b1006..0d15cce 100644
--- a/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
@@ -189,9 +189,7 @@
method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
- method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
- method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
}
public static interface DimensionBuilders.ContainerDimension {
@@ -231,14 +229,6 @@
method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
}
- public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
- }
-
- public static final class DimensionBuilders.ExpandedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
- ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
- }
-
public static interface DimensionBuilders.ImageDimension {
}
@@ -275,14 +265,6 @@
method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
}
- public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension {
- }
-
- public static final class DimensionBuilders.WrappedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder {
- ctor public DimensionBuilders.WrappedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp build();
- }
-
public final class LayoutElementBuilders {
field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
field public static final int ARC_ANCHOR_END = 3; // 0x3
@@ -885,10 +867,26 @@
}
public final class ResourceBuilders {
+ field public static final int ANIMATED_IMAGE_FORMAT_AVD = 1; // 0x1
+ field public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0; // 0x0
field public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
field public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
}
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method @DrawableRes public int getResourceId();
+ method public androidx.wear.protolayout.TriggerBuilders.Trigger? getStartTrigger();
+ }
+
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setStartTrigger(androidx.wear.protolayout.TriggerBuilders.Trigger);
+ }
+
public static final class ResourceBuilders.AndroidImageResourceByResId {
method @DrawableRes public int getResourceId();
}
@@ -899,15 +897,33 @@
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
}
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getProgress();
+ method @DrawableRes public int getResourceId();
+ }
+
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setProgress(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ }
+
public static final class ResourceBuilders.ImageResource {
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId? getAndroidAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId? getAndroidSeekableAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource? getInlineResource();
}
public static final class ResourceBuilders.ImageResource.Builder {
ctor public ResourceBuilders.ImageResource.Builder();
method public androidx.wear.protolayout.ResourceBuilders.ImageResource build();
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId);
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidSeekableAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.protolayout.ResourceBuilders.InlineImageResource);
}
@@ -928,10 +944,8 @@
}
public static final class ResourceBuilders.Resources {
- method @androidx.wear.protolayout.expression.ProtoLayoutExperimental public static androidx.wear.protolayout.ResourceBuilders.Resources? fromByteArray(byte[]);
method public java.util.Map<java.lang.String!,androidx.wear.protolayout.ResourceBuilders.ImageResource!> getIdToImageMapping();
method public String getVersion();
- method @androidx.wear.protolayout.expression.ProtoLayoutExperimental public byte[] toByteArray();
}
public static final class ResourceBuilders.Resources.Builder {
@@ -994,6 +1008,32 @@
method public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.protolayout.TimelineBuilders.TimeInterval);
}
+ public final class TriggerBuilders {
+ method public static androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ method public static androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger createOnLoadTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool? getTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger.Builder {
+ ctor public TriggerBuilders.OnConditionMetTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger build();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger.Builder setTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger.Builder {
+ ctor public TriggerBuilders.OnLoadTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger build();
+ }
+
+ public static interface TriggerBuilders.Trigger {
+ }
+
public final class TypeBuilders {
}
diff --git a/wear/protolayout/protolayout/api/restricted_current.txt b/wear/protolayout/protolayout/api/restricted_current.txt
index 708d1ef..497290d 100644
--- a/wear/protolayout/protolayout/api/restricted_current.txt
+++ b/wear/protolayout/protolayout/api/restricted_current.txt
@@ -177,9 +177,7 @@
method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
- method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
- method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
}
public static interface DimensionBuilders.ContainerDimension {
@@ -219,14 +217,6 @@
method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
}
- public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
- }
-
- public static final class DimensionBuilders.ExpandedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
- ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
- }
-
public static interface DimensionBuilders.ImageDimension {
}
@@ -263,14 +253,6 @@
method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
}
- public static final class DimensionBuilders.WrappedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension {
- }
-
- public static final class DimensionBuilders.WrappedDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder {
- ctor public DimensionBuilders.WrappedDimensionProp.Builder();
- method public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp build();
- }
-
public final class LayoutElementBuilders {
field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
field public static final int ARC_ANCHOR_END = 3; // 0x3
@@ -857,10 +839,26 @@
}
public final class ResourceBuilders {
+ field public static final int ANIMATED_IMAGE_FORMAT_AVD = 1; // 0x1
+ field public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0; // 0x0
field public static final int IMAGE_FORMAT_RGB_565 = 1; // 0x1
field public static final int IMAGE_FORMAT_UNDEFINED = 0; // 0x0
}
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method @DrawableRes public int getResourceId();
+ method public androidx.wear.protolayout.TriggerBuilders.Trigger? getStartTrigger();
+ }
+
+ public static final class ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder setStartTrigger(androidx.wear.protolayout.TriggerBuilders.Trigger);
+ }
+
public static final class ResourceBuilders.AndroidImageResourceByResId {
method @DrawableRes public int getResourceId();
}
@@ -871,15 +869,33 @@
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId.Builder setResourceId(@DrawableRes int);
}
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId {
+ method public int getAnimatedImageFormat();
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? getProgress();
+ method @DrawableRes public int getResourceId();
+ }
+
+ public static final class ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder {
+ ctor public ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId build();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setAnimatedImageFormat(int);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setProgress(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder setResourceId(@DrawableRes int);
+ }
+
public static final class ResourceBuilders.ImageResource {
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId? getAndroidAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId? getAndroidResourceByResId();
+ method public androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId? getAndroidSeekableAnimatedResourceByResId();
method public androidx.wear.protolayout.ResourceBuilders.InlineImageResource? getInlineResource();
}
public static final class ResourceBuilders.ImageResource.Builder {
ctor public ResourceBuilders.ImageResource.Builder();
method public androidx.wear.protolayout.ResourceBuilders.ImageResource build();
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidImageResourceByResId);
+ method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setAndroidSeekableAnimatedResourceByResId(androidx.wear.protolayout.ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId);
method public androidx.wear.protolayout.ResourceBuilders.ImageResource.Builder setInlineResource(androidx.wear.protolayout.ResourceBuilders.InlineImageResource);
}
@@ -964,6 +980,32 @@
method public androidx.wear.protolayout.TimelineBuilders.TimelineEntry.Builder setValidity(androidx.wear.protolayout.TimelineBuilders.TimeInterval);
}
+ public final class TriggerBuilders {
+ method public static androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger createOnConditionMetTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ method public static androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger createOnLoadTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ method public androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool? getTrigger();
+ }
+
+ public static final class TriggerBuilders.OnConditionMetTrigger.Builder {
+ ctor public TriggerBuilders.OnConditionMetTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger build();
+ method public androidx.wear.protolayout.TriggerBuilders.OnConditionMetTrigger.Builder setTrigger(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger implements androidx.wear.protolayout.TriggerBuilders.Trigger {
+ }
+
+ public static final class TriggerBuilders.OnLoadTrigger.Builder {
+ ctor public TriggerBuilders.OnLoadTrigger.Builder();
+ method public androidx.wear.protolayout.TriggerBuilders.OnLoadTrigger build();
+ }
+
+ public static interface TriggerBuilders.Trigger {
+ }
+
public final class TypeBuilders {
}
diff --git a/wear/protolayout/protolayout/build.gradle b/wear/protolayout/protolayout/build.gradle
index e622d23..0cc935b 100644
--- a/wear/protolayout/protolayout/build.gradle
+++ b/wear/protolayout/protolayout/build.gradle
@@ -41,7 +41,7 @@
namespace "androidx.wear.protolayout"
defaultConfig {
- minSdkVersion 25
+ minSdkVersion 26
}
buildTypes.all {
consumerProguardFiles "proguard-rules.pro"
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
index e900f65..0a6f3b0 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2022 The Android Open Source Project
+ * Copyright 2022 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.
@@ -20,8 +20,6 @@
import static androidx.annotation.Dimension.SP;
import android.annotation.SuppressLint;
-import android.content.Context;
-import android.util.DisplayMetrics;
import androidx.annotation.Dimension;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
@@ -30,14 +28,12 @@
import androidx.annotation.RestrictTo.Scope;
import androidx.wear.protolayout.expression.Fingerprint;
import androidx.wear.protolayout.proto.DimensionProto;
+import androidx.wear.protolayout.proto.TypesProto;
/** Builders for dimensions for layout elements. */
public final class DimensionBuilders {
private DimensionBuilders() {}
- private static final ExpandedDimensionProp EXPAND = new ExpandedDimensionProp.Builder().build();
- private static final WrappedDimensionProp WRAP = new WrappedDimensionProp.Builder().build();
-
/** Shortcut for building a {@link DpProp} using a measurement in DP. */
@NonNull
public static DpProp dp(@Dimension(unit = DP) float valueDp) {
@@ -68,25 +64,10 @@
return new DegreesProp.Builder().setValue(valueDegrees).build();
}
- /**
- * Shortcut for building an {@link ExpandedDimensionProp} that will expand to the size of its
- * parent.
+ /** A type for linear dimensions, measured in dp.
+ *
+ * @since 1.0
*/
- @NonNull
- public static ExpandedDimensionProp expand() {
- return EXPAND;
- }
-
- /**
- * Shortcut for building an {@link WrappedDimensionProp} that will shrink to the size of its
- * children.
- */
- @NonNull
- public static WrappedDimensionProp wrap() {
- return WRAP;
- }
-
- /** A type for linear dimensions, measured in dp. */
public static final class DpProp implements ContainerDimension, ImageDimension, SpacerDimension {
private final DimensionProto.DpProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -96,7 +77,11 @@
this.mFingerprint = fingerprint;
}
- /** Gets the value, in dp. Intended for testing purposes only. */
+ /**
+ * Gets the value, in dp.
+ *
+ * @since 1.0
+ */
@Dimension(unit = DP)
public float getValue() {
return mImpl.getValue();
@@ -148,11 +133,15 @@
public static final class Builder
implements ContainerDimension.Builder, ImageDimension.Builder, SpacerDimension.Builder {
private final DimensionProto.DpProp.Builder mImpl = DimensionProto.DpProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(752970309);
+ private final Fingerprint mFingerprint = new Fingerprint(756413087);
public Builder() {}
- /** Sets the value, in dp. */
+ /**
+ * Sets the value, in dp.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setValue(@Dimension(unit = DP) float value) {
mImpl.setValue(value);
@@ -168,7 +157,11 @@
}
}
- /** A type for font sizes, measured in sp. */
+ /**
+ * A type for font sizes, measured in sp.
+ *
+ * @since 1.0
+ */
public static final class SpProp {
private final DimensionProto.SpProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -178,7 +171,11 @@
this.mFingerprint = fingerprint;
}
- /** Gets the value, in sp. Intended for testing purposes only. */
+ /**
+ * Gets the value, in sp.
+ *
+ * @since 1.0
+ */
@Dimension(unit = SP)
public float getValue() {
return mImpl.getValue();
@@ -208,11 +205,15 @@
/** Builder for {@link SpProp} */
public static final class Builder {
private final DimensionProto.SpProp.Builder mImpl = DimensionProto.SpProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(-2144685857);
+ private final Fingerprint mFingerprint = new Fingerprint(631793260);
public Builder() {}
- /** Sets the value, in sp. */
+ /**
+ * Sets the value, in sp.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setValue(@Dimension(unit = SP) float value) {
mImpl.setValue(value);
@@ -228,7 +229,11 @@
}
}
- /** A type for font spacing, measured in em. */
+ /**
+ * A type for font spacing, measured in em.
+ *
+ * @since 1.0
+ */
public static final class EmProp {
private final DimensionProto.EmProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -238,7 +243,11 @@
this.mFingerprint = fingerprint;
}
- /** Gets the value, in em. Intended for testing purposes only. */
+ /**
+ * Gets the value, in em.
+ *
+ * @since 1.0
+ */
public float getValue() {
return mImpl.getValue();
}
@@ -267,11 +276,15 @@
/** Builder for {@link EmProp} */
public static final class Builder {
private final DimensionProto.EmProp.Builder mImpl = DimensionProto.EmProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(1628313311);
+ private final Fingerprint mFingerprint = new Fingerprint(-659639046);
public Builder() {}
- /** Sets the value, in em. */
+ /**
+ * Sets the value, in em.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setValue(float value) {
mImpl.setValue(value);
@@ -287,7 +300,11 @@
}
}
- /** A type for angular dimensions, measured in degrees. */
+ /**
+ * A type for angular dimensions, measured in degrees.
+ *
+ * @since 1.0
+ */
public static final class DegreesProp {
private final DimensionProto.DegreesProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -297,7 +314,11 @@
this.mFingerprint = fingerprint;
}
- /** Gets the value, in degrees. Intended for testing purposes only. */
+ /**
+ * Gets the value, in degrees.
+ *
+ * @since 1.0
+ */
public float getValue() {
return mImpl.getValue();
}
@@ -327,11 +348,15 @@
public static final class Builder {
private final DimensionProto.DegreesProp.Builder mImpl =
DimensionProto.DegreesProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(405060347);
+ private final Fingerprint mFingerprint = new Fingerprint(-1927567665);
public Builder() {}
- /** Sets the value, in degrees. */
+ /**
+ * Sets the value, in degrees.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setValue(float value) {
mImpl.setValue(value);
@@ -349,7 +374,11 @@
/**
* A type for a dimension that fills all the space it can (i.e. MATCH_PARENT in Android parlance).
+ *
+ * @since 1.0
+ * @hide
*/
+ @RestrictTo(Scope.LIBRARY_GROUP)
public static final class ExpandedDimensionProp implements ContainerDimension, ImageDimension {
private final DimensionProto.ExpandedDimensionProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -360,6 +389,19 @@
this.mFingerprint = fingerprint;
}
+ /**
+ * Gets the layout weight (a dimensionless scalar value) for this element. This will only affect
+ * the width of children of a {@link androidx.wear.protolayout.LayoutElementBuilders.Row} or the
+ * height of children of a {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By
+ * default, all children have equal weight. Where applicable, the width or height of the element
+ * is proportional to the sum of the weights of its siblings.
+ *
+ * @since 1.2
+ */
+ public float getLayoutWeight() {
+ return mImpl.getLayoutWeight().getValue();
+ }
+
/** @hide */
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@@ -399,10 +441,27 @@
implements ContainerDimension.Builder, ImageDimension.Builder {
private final DimensionProto.ExpandedDimensionProp.Builder mImpl =
DimensionProto.ExpandedDimensionProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(1053378170);
+ private final Fingerprint mFingerprint = new Fingerprint(-997720604);
public Builder() {}
+ /**
+ * Sets the layout weight (a dimensionless scalar value) for this element. This will only
+ * affect the width of children of a {@link
+ * androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a {@link
+ * androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all children have
+ * equal weight. Where applicable, the width or height of the element is proportional to the
+ * sum of the weights of its siblings.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setLayoutWeight(float layoutWeight) {
+ mImpl.setLayoutWeight(TypesProto.FloatProp.newBuilder().setValue(layoutWeight));
+ mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(layoutWeight));
+ return this;
+ }
+
@Override
@NonNull
public ExpandedDimensionProp build() {
@@ -414,7 +473,11 @@
/**
* A type for a dimension that sizes itself to the size of its children (i.e. WRAP_CONTENT in
* Android parlance).
+ *
+ * @since 1.0
+ * @hide
*/
+ @RestrictTo(Scope.LIBRARY_GROUP)
public static final class WrappedDimensionProp implements ContainerDimension {
private final DimensionProto.WrappedDimensionProp mImpl;
@Nullable private final Fingerprint mFingerprint;
@@ -425,6 +488,16 @@
this.mFingerprint = fingerprint;
}
+ /**
+ * Gets the minimum size of this dimension. If not set, then there is no minimum size.
+ *
+ * @since 1.2
+ */
+ @Dimension(unit = DP)
+ public float getMinimumSizeDp() {
+ return mImpl.getMinimumSize().getValue();
+ }
+
/** @hide */
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@@ -455,10 +528,22 @@
public static final class Builder implements ContainerDimension.Builder {
private final DimensionProto.WrappedDimensionProp.Builder mImpl =
DimensionProto.WrappedDimensionProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(-113456542);
+ private final Fingerprint mFingerprint = new Fingerprint(1118918114);
public Builder() {}
+ /**
+ * Sets the minimum size of this dimension. If not set, then there is no minimum size.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setMinimumSizeDp(@Dimension(unit = DP) float minimumSize) {
+ mImpl.setMinimumSize(DimensionProto.DpProp.newBuilder().setValue(minimumSize));
+ mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(minimumSize));
+ return this;
+ }
+
@Override
@NonNull
public WrappedDimensionProp build() {
@@ -475,6 +560,8 @@
* specifying an element's size using common ratios (e.g. width=4, height=3), or to allow an
* element to be resized proportionally based on the size of an underlying asset (e.g. an 800x600
* image being added to a smaller container and resized accordingly).
+ *
+ * @since 1.0
*/
public static final class ProportionalDimensionProp implements ImageDimension {
private final DimensionProto.ProportionalDimensionProp mImpl;
@@ -487,8 +574,9 @@
}
/**
- * Gets the width to be used when calculating the aspect ratio to preserve. Intended for testing
- * purposes only.
+ * Gets the width to be used when calculating the aspect ratio to preserve.
+ *
+ * @since 1.0
*/
@IntRange(from = 0)
public int getAspectRatioWidth() {
@@ -496,8 +584,9 @@
}
/**
- * Gets the height to be used when calculating the aspect ratio ratio to preserve. Intended for
- * testing purposes only.
+ * Gets the height to be used when calculating the aspect ratio ratio to preserve.
+ *
+ * @since 1.0
*/
@IntRange(from = 0)
public int getAspectRatioHeight() {
@@ -535,11 +624,15 @@
public static final class Builder implements ImageDimension.Builder {
private final DimensionProto.ProportionalDimensionProp.Builder mImpl =
DimensionProto.ProportionalDimensionProp.newBuilder();
- private final Fingerprint mFingerprint = new Fingerprint(-2079046835);
+ private final Fingerprint mFingerprint = new Fingerprint(1725027476);
public Builder() {}
- /** Sets the width to be used when calculating the aspect ratio to preserve. */
+ /**
+ * Sets the width to be used when calculating the aspect ratio to preserve.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setAspectRatioWidth(@IntRange(from = 0) int aspectRatioWidth) {
mImpl.setAspectRatioWidth(aspectRatioWidth);
@@ -547,7 +640,11 @@
return this;
}
- /** Sets the height to be used when calculating the aspect ratio ratio to preserve. */
+ /**
+ * Sets the height to be used when calculating the aspect ratio ratio to preserve.
+ *
+ * @since 1.0
+ */
@NonNull
public Builder setAspectRatioHeight(@IntRange(from = 0) int aspectRatioHeight) {
mImpl.setAspectRatioHeight(aspectRatioHeight);
@@ -563,7 +660,11 @@
}
}
- /** Interface defining a dimension that can be applied to a container. */
+ /**
+ * Interface defining a dimension that can be applied to a container.
+ *
+ * @since 1.0
+ */
public interface ContainerDimension {
/**
* Get the protocol buffer representation of this object.
@@ -608,7 +709,11 @@
throw new IllegalStateException("Proto was not a recognised instance of ContainerDimension");
}
- /** Interface defining a dimension that can be applied to an image. */
+ /**
+ * Interface defining a dimension that can be applied to an image.
+ *
+ * @since 1.0
+ */
public interface ImageDimension {
/**
* Get the protocol buffer representation of this object.
@@ -652,7 +757,11 @@
throw new IllegalStateException("Proto was not a recognised instance of ImageDimension");
}
- /** Interface defining a dimension that can be applied to a spacer. */
+ /**
+ * Interface defining a dimension that can be applied to a spacer.
+ *
+ * @since 1.0
+ */
public interface SpacerDimension {
/**
* Get the protocol buffer representation of this object.
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
index 8e23d72..76dbb60 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2022 The Android Open Source Project
+ * Copyright 2022 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.
@@ -19,6 +19,7 @@
import static androidx.annotation.Dimension.PX;
import android.annotation.SuppressLint;
+
import androidx.annotation.Dimension;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
@@ -26,10 +27,12 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
-import androidx.wear.protolayout.expression.ProtoLayoutExperimental;
+import androidx.wear.protolayout.TriggerBuilders.Trigger;
+import androidx.wear.protolayout.expression.DynamicBuilders;
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat;
import androidx.wear.protolayout.proto.ResourceProto;
import androidx.wear.protolayout.protobuf.ByteString;
-import androidx.wear.protolayout.protobuf.InvalidProtocolBufferException;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
@@ -39,376 +42,733 @@
/** Builders for the resources for a layout. */
public final class ResourceBuilders {
- private ResourceBuilders() {}
-
- /**
- * Format describing the contents of an image data byte array.
- *
- * @hide
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @IntDef({IMAGE_FORMAT_UNDEFINED, IMAGE_FORMAT_RGB_565})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ImageFormat {}
-
- /** An undefined image format. */
- public static final int IMAGE_FORMAT_UNDEFINED = 0;
-
- /**
- * An image format where each pixel is stored on 2 bytes, with red using 5 bits, green using 6
- * bits and blue using 5 bits of precision.
- */
- public static final int IMAGE_FORMAT_RGB_565 = 1;
-
- /** An image resource which maps to an Android drawable by resource ID. */
- public static final class AndroidImageResourceByResId {
- private final ResourceProto.AndroidImageResourceByResId mImpl;
-
- private AndroidImageResourceByResId(ResourceProto.AndroidImageResourceByResId impl) {
- this.mImpl = impl;
- }
+ private ResourceBuilders() {}
/**
- * Gets the Android resource ID of this image. This must refer to a drawable under R.drawable.
- * Intended for testing purposes only.
- */
- @DrawableRes
- public int getResourceId() {
- return mImpl.getResourceId();
- }
-
- @NonNull
- static AndroidImageResourceByResId fromProto(
- @NonNull ResourceProto.AndroidImageResourceByResId proto) {
- return new AndroidImageResourceByResId(proto);
- }
-
- @NonNull
- ResourceProto.AndroidImageResourceByResId toProto() {
- return mImpl;
- }
-
- /** Builder for {@link AndroidImageResourceByResId} */
- public static final class Builder {
- private final ResourceProto.AndroidImageResourceByResId.Builder mImpl =
- ResourceProto.AndroidImageResourceByResId.newBuilder();
-
- public Builder() {}
-
- /**
- * Sets the Android resource ID of this image. This must refer to a drawable under R.drawable.
- */
- @NonNull
- public Builder setResourceId(@DrawableRes int resourceId) {
- mImpl.setResourceId(resourceId);
- return this;
- }
-
- /** Builds an instance from accumulated values. */
- @NonNull
- public AndroidImageResourceByResId build() {
- return AndroidImageResourceByResId.fromProto(mImpl.build());
- }
- }
- }
-
- /**
- * An image resource whose data is fully inlined, with no dependency on a system or app resource.
- */
- public static final class InlineImageResource {
- private final ResourceProto.InlineImageResource mImpl;
-
- private InlineImageResource(ResourceProto.InlineImageResource impl) {
- this.mImpl = impl;
- }
-
- /** Gets the byte array representing the image. Intended for testing purposes only. */
- @NonNull
- public byte[] getData() {
- return mImpl.getData().toByteArray();
- }
-
- /**
- * Gets the native width of the image, in pixels. Only required for formats (e.g.
- * IMAGE_FORMAT_RGB_565) where the image data does not include size. Intended for testing
- * purposes only.
- */
- @Dimension(unit = PX)
- public int getWidthPx() {
- return mImpl.getWidthPx();
- }
-
- /**
- * Gets the native height of the image, in pixels. Only required for formats (e.g.
- * IMAGE_FORMAT_RGB_565) where the image data does not include size. Intended for testing
- * purposes only.
- */
- @Dimension(unit = PX)
- public int getHeightPx() {
- return mImpl.getHeightPx();
- }
-
- /**
- * Gets the format of the byte array data representing the image. May be left unspecified or set
- * to IMAGE_FORMAT_UNDEFINED in which case the platform will attempt to extract this from the
- * raw image data. If the platform does not support the format, the image will not be decoded or
- * displayed. Intended for testing purposes only.
- */
- @ImageFormat
- public int getFormat() {
- return mImpl.getFormat().getNumber();
- }
-
- @NonNull
- static InlineImageResource fromProto(@NonNull ResourceProto.InlineImageResource proto) {
- return new InlineImageResource(proto);
- }
-
- @NonNull
- ResourceProto.InlineImageResource toProto() {
- return mImpl;
- }
-
- /** Builder for {@link InlineImageResource} */
- public static final class Builder {
- private final ResourceProto.InlineImageResource.Builder mImpl =
- ResourceProto.InlineImageResource.newBuilder();
-
- public Builder() {}
-
- /** Sets the byte array representing the image. */
- @NonNull
- public Builder setData(@NonNull byte[] data) {
- mImpl.setData(ByteString.copyFrom(data));
- return this;
- }
-
- /**
- * Sets the native width of the image, in pixels. Only required for formats (e.g.
- * IMAGE_FORMAT_RGB_565) where the image data does not include size.
- */
- @NonNull
- public Builder setWidthPx(@Dimension(unit = PX) int widthPx) {
- mImpl.setWidthPx(widthPx);
- return this;
- }
-
- /**
- * Sets the native height of the image, in pixels. Only required for formats (e.g.
- * IMAGE_FORMAT_RGB_565) where the image data does not include size.
- */
- @NonNull
- public Builder setHeightPx(@Dimension(unit = PX) int heightPx) {
- mImpl.setHeightPx(heightPx);
- return this;
- }
-
- /**
- * Sets the format of the byte array data representing the image. May be left unspecified or
- * set to IMAGE_FORMAT_UNDEFINED in which case the platform will attempt to extract this from
- * the raw image data. If the platform does not support the format, the image will not be
- * decoded or displayed.
- */
- @NonNull
- public Builder setFormat(@ImageFormat int format) {
- mImpl.setFormat(ResourceProto.ImageFormat.forNumber(format));
- return this;
- }
-
- /** Builds an instance from accumulated values. */
- @NonNull
- public InlineImageResource build() {
- return InlineImageResource.fromProto(mImpl.build());
- }
- }
- }
-
- /**
- * An image resource, which can be used by layouts. This holds multiple underlying resource types,
- * which the underlying runtime will pick according to what it thinks is appropriate.
- */
- public static final class ImageResource {
- private final ResourceProto.ImageResource mImpl;
-
- private ImageResource(ResourceProto.ImageResource impl) {
- this.mImpl = impl;
- }
-
- /**
- * Gets an image resource that maps to an Android drawable by resource ID. Intended for testing
- * purposes only.
- */
- @Nullable
- public AndroidImageResourceByResId getAndroidResourceByResId() {
- if (mImpl.hasAndroidResourceByResId()) {
- return AndroidImageResourceByResId.fromProto(mImpl.getAndroidResourceByResId());
- } else {
- return null;
- }
- }
-
- /**
- * Gets an image resource that contains the image data inline. Intended for testing purposes
- * only.
- */
- @Nullable
- public InlineImageResource getInlineResource() {
- if (mImpl.hasInlineResource()) {
- return InlineImageResource.fromProto(mImpl.getInlineResource());
- } else {
- return null;
- }
- }
-
- @NonNull
- static ImageResource fromProto(@NonNull ResourceProto.ImageResource proto) {
- return new ImageResource(proto);
- }
-
- @NonNull
- ResourceProto.ImageResource toProto() {
- return mImpl;
- }
-
- /** Builder for {@link ImageResource} */
- public static final class Builder {
- private final ResourceProto.ImageResource.Builder mImpl =
- ResourceProto.ImageResource.newBuilder();
-
- public Builder() {}
-
- /** Sets an image resource that maps to an Android drawable by resource ID. */
- @NonNull
- public Builder setAndroidResourceByResId(
- @NonNull AndroidImageResourceByResId androidResourceByResId) {
- mImpl.setAndroidResourceByResId(androidResourceByResId.toProto());
- return this;
- }
-
- /** Sets an image resource that contains the image data inline. */
- @NonNull
- public Builder setInlineResource(@NonNull InlineImageResource inlineResource) {
- mImpl.setInlineResource(inlineResource.toProto());
- return this;
- }
-
- /** Builds an instance from accumulated values. */
- @NonNull
- public ImageResource build() {
- return ImageResource.fromProto(mImpl.build());
- }
- }
- }
-
- /** The resources for a layout. */
- public static final class Resources {
- private final ResourceProto.Resources mImpl;
-
- private Resources(ResourceProto.Resources impl) {
- this.mImpl = impl;
- }
-
- /**
- * Gets the version of this {@link Resources} instance.
+ * Format describing the contents of an image data byte array.
*
- * <p>Each tile specifies the version of resources it requires. After fetching a tile, the
- * renderer will use the resources version specified by the tile to separately fetch the
- * resources.
- *
- * <p>This value must match the version of the resources required by the tile for the tile to
- * render successfully, and must match the resource version specified in {@link
- * androidx.wear.tiles.RequestBuilders.ResourcesRequest} which triggered this request. Intended
- * for testing purposes only.
- */
- @NonNull
- public String getVersion() {
- return mImpl.getVersion();
- }
-
- /**
- * Gets a map of resource_ids to images, which can be used by layouts. Intended for testing
- * purposes only.
- */
- @NonNull
- public Map<String, ImageResource> getIdToImageMapping() {
- Map<String, ImageResource> map = new HashMap<>();
- for (Entry<String, ResourceProto.ImageResource> entry : mImpl.getIdToImageMap().entrySet()) {
- map.put(entry.getKey(), ImageResource.fromProto(entry.getValue()));
- }
- return Collections.unmodifiableMap(map);
- }
-
- /** Converts to byte array representation. */
- @NonNull
- @ProtoLayoutExperimental
- public byte[] toByteArray() {
- return mImpl.toByteArray();
- }
-
- /** Converts from byte array representation. */
- @SuppressWarnings("ProtoParseWithRegistry")
- @Nullable
- @ProtoLayoutExperimental
- public static Resources fromByteArray(@NonNull byte[] byteArray) {
- try {
- return fromProto(ResourceProto.Resources.parseFrom(byteArray));
- } catch (InvalidProtocolBufferException e) {
- return null;
- }
- }
-
- @NonNull
- static Resources fromProto(@NonNull ResourceProto.Resources proto) {
- return new Resources(proto);
- }
-
- /**
- * Returns the internal proto instance.
- *
+ * @since 1.0
* @hide
*/
- @RestrictTo(Scope.LIBRARY_GROUP)
- @NonNull
- public ResourceProto.Resources toProto() {
- return mImpl;
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @IntDef({IMAGE_FORMAT_UNDEFINED, IMAGE_FORMAT_RGB_565})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImageFormat {}
+
+ /**
+ * An undefined image format.
+ *
+ * @since 1.0
+ */
+ public static final int IMAGE_FORMAT_UNDEFINED = 0;
+
+ /**
+ * An image format where each pixel is stored on 2 bytes, with red using 5 bits, green using 6
+ * bits and blue using 5 bits of precision.
+ *
+ * @since 1.0
+ */
+ public static final int IMAGE_FORMAT_RGB_565 = 1;
+
+ /**
+ * Format describing the contents of an animated image.
+ *
+ * @since 1.2
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @IntDef({ANIMATED_IMAGE_FORMAT_UNDEFINED, ANIMATED_IMAGE_FORMAT_AVD})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AnimatedImageFormat {}
+
+ /**
+ * An undefined image format.
+ *
+ * @since 1.2
+ */
+ public static final int ANIMATED_IMAGE_FORMAT_UNDEFINED = 0;
+
+ /**
+ * Android AnimatedVectorDrawable.
+ *
+ * @since 1.2
+ */
+ public static final int ANIMATED_IMAGE_FORMAT_AVD = 1;
+
+ /**
+ * An image resource which maps to an Android drawable by resource ID.
+ *
+ * @since 1.0
+ */
+ public static final class AndroidImageResourceByResId {
+ private final ResourceProto.AndroidImageResourceByResId mImpl;
+
+ AndroidImageResourceByResId(ResourceProto.AndroidImageResourceByResId impl) {
+ this.mImpl = impl;
+ }
+
+ /**
+ * Gets the Android resource ID of this image. This must refer to a drawable under
+ * R.drawable.
+ *
+ * @since 1.0
+ */
+ @DrawableRes
+ public int getResourceId() {
+ return mImpl.getResourceId();
+ }
+
+ @NonNull
+ static AndroidImageResourceByResId fromProto(
+ @NonNull ResourceProto.AndroidImageResourceByResId proto) {
+ return new AndroidImageResourceByResId(proto);
+ }
+
+ @NonNull
+ ResourceProto.AndroidImageResourceByResId toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link AndroidImageResourceByResId} */
+ public static final class Builder {
+ private final ResourceProto.AndroidImageResourceByResId.Builder mImpl =
+ ResourceProto.AndroidImageResourceByResId.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets the Android resource ID of this image. This must refer to a drawable under
+ * R.drawable.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setResourceId(@DrawableRes int resourceId) {
+ mImpl.setResourceId(resourceId);
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public AndroidImageResourceByResId build() {
+ return AndroidImageResourceByResId.fromProto(mImpl.build());
+ }
+ }
}
- /** Builder for {@link Resources} */
- public static final class Builder {
- private final ResourceProto.Resources.Builder mImpl = ResourceProto.Resources.newBuilder();
+ /**
+ * An image resource whose data is fully inlined, with no dependency on a system or app
+ * resource.
+ *
+ * @since 1.0
+ */
+ public static final class InlineImageResource {
+ private final ResourceProto.InlineImageResource mImpl;
- public Builder() {}
+ InlineImageResource(ResourceProto.InlineImageResource impl) {
+ this.mImpl = impl;
+ }
- /**
- * Sets the version of this {@link Resources} instance.
- *
- * <p>Each tile specifies the version of resources it requires. After fetching a tile, the
- * renderer will use the resources version specified by the tile to separately fetch the
- * resources.
- *
- * <p>This value must match the version of the resources required by the tile for the tile to
- * render successfully, and must match the resource version specified in {@link
- * androidx.wear.tiles.RequestBuilders.ResourcesRequest} which triggered this request.
- */
- @NonNull
- public Builder setVersion(@NonNull String version) {
- mImpl.setVersion(version);
- return this;
- }
+ /**
+ * Gets the byte array representing the image.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public byte[] getData() {
+ return mImpl.getData().toByteArray();
+ }
- /** Adds an entry into a map of resource_ids to images, which can be used by layouts. */
- @SuppressLint("MissingGetterMatchingBuilder")
- @NonNull
- public Builder addIdToImageMapping(@NonNull String id, @NonNull ImageResource image) {
- mImpl.putIdToImage(id, image.toProto());
- return this;
- }
+ /**
+ * Gets the native width of the image, in pixels. Only required for formats (e.g.
+ * IMAGE_FORMAT_RGB_565) where the image data does not include size.
+ *
+ * @since 1.0
+ */
+ @Dimension(unit = PX)
+ public int getWidthPx() {
+ return mImpl.getWidthPx();
+ }
- /** Builds an instance from accumulated values. */
- @NonNull
- public Resources build() {
- return Resources.fromProto(mImpl.build());
- }
+ /**
+ * Gets the native height of the image, in pixels. Only required for formats (e.g.
+ * IMAGE_FORMAT_RGB_565) where the image data does not include size.
+ *
+ * @since 1.0
+ */
+ @Dimension(unit = PX)
+ public int getHeightPx() {
+ return mImpl.getHeightPx();
+ }
+
+ /**
+ * Gets the format of the byte array data representing the image. May be left unspecified or
+ * set to IMAGE_FORMAT_UNDEFINED in which case the platform will attempt to extract this
+ * from the raw image data. If the platform does not support the format, the image will not
+ * be decoded or displayed.
+ *
+ * @since 1.0
+ */
+ @ImageFormat
+ public int getFormat() {
+ return mImpl.getFormat().getNumber();
+ }
+
+ @NonNull
+ static InlineImageResource fromProto(@NonNull ResourceProto.InlineImageResource proto) {
+ return new InlineImageResource(proto);
+ }
+
+ @NonNull
+ ResourceProto.InlineImageResource toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link InlineImageResource} */
+ public static final class Builder {
+ private final ResourceProto.InlineImageResource.Builder mImpl =
+ ResourceProto.InlineImageResource.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets the byte array representing the image.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setData(@NonNull byte[] data) {
+ mImpl.setData(ByteString.copyFrom(data));
+ return this;
+ }
+
+ /**
+ * Sets the native width of the image, in pixels. Only required for formats (e.g.
+ * IMAGE_FORMAT_RGB_565) where the image data does not include size.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setWidthPx(@Dimension(unit = PX) int widthPx) {
+ mImpl.setWidthPx(widthPx);
+ return this;
+ }
+
+ /**
+ * Sets the native height of the image, in pixels. Only required for formats (e.g.
+ * IMAGE_FORMAT_RGB_565) where the image data does not include size.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setHeightPx(@Dimension(unit = PX) int heightPx) {
+ mImpl.setHeightPx(heightPx);
+ return this;
+ }
+
+ /**
+ * Sets the format of the byte array data representing the image. May be left
+ * unspecified or set to IMAGE_FORMAT_UNDEFINED in which case the platform will attempt
+ * to extract this from the raw image data. If the platform does not support the format,
+ * the image will not be decoded or displayed.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setFormat(@ImageFormat int format) {
+ mImpl.setFormat(ResourceProto.ImageFormat.forNumber(format));
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public InlineImageResource build() {
+ return InlineImageResource.fromProto(mImpl.build());
+ }
+ }
}
- }
+
+ /**
+ * A non-seekable animated image resource that maps to an Android drawable by resource ID. The
+ * animation is started with given trigger, fire and forget.
+ *
+ * @since 1.2
+ */
+ public static final class AndroidAnimatedImageResourceByResId {
+ private final ResourceProto.AndroidAnimatedImageResourceByResId mImpl;
+
+ AndroidAnimatedImageResourceByResId(
+ ResourceProto.AndroidAnimatedImageResourceByResId impl) {
+ this.mImpl = impl;
+ }
+
+ /**
+ * Gets the format for the animated image.
+ *
+ * @since 1.2
+ */
+ @AnimatedImageFormat
+ public int getAnimatedImageFormat() {
+ return mImpl.getFormat().getNumber();
+ }
+
+ /**
+ * Gets the Android resource ID, e.g. R.drawable.foo.
+ *
+ * @since 1.2
+ */
+ @DrawableRes
+ public int getResourceId() {
+ return mImpl.getResourceId();
+ }
+
+ /**
+ * Gets the trigger to start the animation.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public Trigger getStartTrigger() {
+ if (mImpl.hasTrigger()) {
+ return TriggerBuilders.triggerFromProto(mImpl.getTrigger());
+ } else {
+ return null;
+ }
+ }
+
+ @NonNull
+ static AndroidAnimatedImageResourceByResId fromProto(
+ @NonNull ResourceProto.AndroidAnimatedImageResourceByResId proto) {
+ return new AndroidAnimatedImageResourceByResId(proto);
+ }
+
+ @NonNull
+ ResourceProto.AndroidAnimatedImageResourceByResId toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link AndroidAnimatedImageResourceByResId} */
+ public static final class Builder {
+ private final ResourceProto.AndroidAnimatedImageResourceByResId.Builder mImpl =
+ ResourceProto.AndroidAnimatedImageResourceByResId.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets the format for the animated image.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setAnimatedImageFormat(@AnimatedImageFormat int format) {
+ mImpl.setFormat(ResourceProto.AnimatedImageFormat.forNumber(format));
+ return this;
+ }
+
+ /**
+ * Sets the Android resource ID, e.g. R.drawable.foo.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setResourceId(@DrawableRes int resourceId) {
+ mImpl.setResourceId(resourceId);
+ return this;
+ }
+
+ /**
+ * Sets the trigger to start the animation.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setStartTrigger(@NonNull Trigger trigger) {
+ mImpl.setTrigger(trigger.toTriggerProto());
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public AndroidAnimatedImageResourceByResId build() {
+ return AndroidAnimatedImageResourceByResId.fromProto(mImpl.build());
+ }
+ }
+ }
+
+ /**
+ * A seekable animated image resource that maps to an Android drawable by resource ID. The
+ * animation progress is bound to the provided dynamic float.
+ *
+ * @since 1.2
+ */
+ public static final class AndroidSeekableAnimatedImageResourceByResId {
+ private final ResourceProto.AndroidSeekableAnimatedImageResourceByResId mImpl;
+
+ AndroidSeekableAnimatedImageResourceByResId(
+ ResourceProto.AndroidSeekableAnimatedImageResourceByResId impl) {
+ this.mImpl = impl;
+ }
+
+ /**
+ * Gets the format for the animated image.
+ *
+ * @since 1.2
+ */
+ @AnimatedImageFormat
+ public int getAnimatedImageFormat() {
+ return mImpl.getFormat().getNumber();
+ }
+
+ /**
+ * Gets the Android resource ID, e.g. R.drawable.foo.
+ *
+ * @since 1.2
+ */
+ @DrawableRes
+ public int getResourceId() {
+ return mImpl.getResourceId();
+ }
+
+ /**
+ * Gets a {@link DynamicFloat}, normally transformed from certain states with the data
+ * binding pipeline to control the progress of the animation. Its value is required to fall
+ * in the range of [0.0, 1.0]. Any values outside this range would be clamped. When the
+ * first value of the {@link DynamicFloat} arrives, the animation starts from progress 0 to
+ * that value. After that it plays from current progress to the new value on subsequent
+ * updates.
+ * If not set, the animation will play on load (similar to a non-seekable animated).
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public DynamicFloat getProgress() {
+ if (mImpl.hasProgress()) {
+ return DynamicBuilders.dynamicFloatFromProto(mImpl.getProgress());
+ } else {
+ return null;
+ }
+ }
+
+ @NonNull
+ static AndroidSeekableAnimatedImageResourceByResId fromProto(
+ @NonNull ResourceProto.AndroidSeekableAnimatedImageResourceByResId proto) {
+ return new AndroidSeekableAnimatedImageResourceByResId(proto);
+ }
+
+ @NonNull
+ ResourceProto.AndroidSeekableAnimatedImageResourceByResId toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link AndroidSeekableAnimatedImageResourceByResId} */
+ public static final class Builder {
+ private final ResourceProto.AndroidSeekableAnimatedImageResourceByResId.Builder mImpl =
+ ResourceProto.AndroidSeekableAnimatedImageResourceByResId.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets the format for the animated image.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setAnimatedImageFormat(@AnimatedImageFormat int format) {
+ mImpl.setFormat(ResourceProto.AnimatedImageFormat.forNumber(format));
+ return this;
+ }
+
+ /**
+ * Sets the Android resource ID, e.g. R.drawable.foo.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setResourceId(@DrawableRes int resourceId) {
+ mImpl.setResourceId(resourceId);
+ return this;
+ }
+
+ /**
+ * Sets a {@link DynamicFloat}, normally transformed from certain states with the data
+ * binding pipeline to control the progress of the animation. Its value is required to
+ * fall in the range of [0.0, 1.0]. Any values outside this range would be clamped. When
+ * the first value of the {@link DynamicFloat} arrives, the animation starts from
+ * progress 0 to that value. After that it plays from current progress to the new value
+ * on subsequent updates.
+ * If not set, the animation will play on load (similar to a non-seekable animated).
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setProgress(@NonNull DynamicFloat progress) {
+ mImpl.setProgress(progress.toDynamicFloatProto());
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public AndroidSeekableAnimatedImageResourceByResId build() {
+ return AndroidSeekableAnimatedImageResourceByResId.fromProto(mImpl.build());
+ }
+ }
+ }
+
+ /**
+ * An image resource, which can be used by layouts. This holds multiple underlying resource
+ * types, which the underlying runtime will pick according to what it thinks is appropriate.
+ *
+ * @since 1.0
+ */
+ public static final class ImageResource {
+ private final ResourceProto.ImageResource mImpl;
+
+ ImageResource(ResourceProto.ImageResource impl) {
+ this.mImpl = impl;
+ }
+
+ /**
+ * Gets an image resource that maps to an Android drawable by resource ID.
+ *
+ * @since 1.0
+ */
+ @Nullable
+ public AndroidImageResourceByResId getAndroidResourceByResId() {
+ if (mImpl.hasAndroidResourceByResId()) {
+ return AndroidImageResourceByResId.fromProto(mImpl.getAndroidResourceByResId());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets an image resource that contains the image data inline.
+ *
+ * @since 1.0
+ */
+ @Nullable
+ public InlineImageResource getInlineResource() {
+ if (mImpl.hasInlineResource()) {
+ return InlineImageResource.fromProto(mImpl.getInlineResource());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets a non-seekable animated image resource that maps to an Android drawable by resource
+ * ID. The animation is started with given trigger, fire and forget.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public AndroidAnimatedImageResourceByResId getAndroidAnimatedResourceByResId() {
+ if (mImpl.hasAndroidAnimatedResourceByResId()) {
+ return AndroidAnimatedImageResourceByResId.fromProto(
+ mImpl.getAndroidAnimatedResourceByResId());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets a seekable animated image resource that maps to an Android drawable by resource ID.
+ * The animation progress is bound to the provided dynamic float.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public AndroidSeekableAnimatedImageResourceByResId
+ getAndroidSeekableAnimatedResourceByResId() {
+ if (mImpl.hasAndroidSeekableAnimatedResourceByResId()) {
+ return AndroidSeekableAnimatedImageResourceByResId.fromProto(
+ mImpl.getAndroidSeekableAnimatedResourceByResId());
+ } else {
+ return null;
+ }
+ }
+
+ @NonNull
+ static ImageResource fromProto(@NonNull ResourceProto.ImageResource proto) {
+ return new ImageResource(proto);
+ }
+
+ @NonNull
+ ResourceProto.ImageResource toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link ImageResource} */
+ public static final class Builder {
+ private final ResourceProto.ImageResource.Builder mImpl =
+ ResourceProto.ImageResource.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets an image resource that maps to an Android drawable by resource ID.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setAndroidResourceByResId(
+ @NonNull AndroidImageResourceByResId androidResourceByResId) {
+ mImpl.setAndroidResourceByResId(androidResourceByResId.toProto());
+ return this;
+ }
+
+ /**
+ * Sets an image resource that contains the image data inline.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setInlineResource(@NonNull InlineImageResource inlineResource) {
+ mImpl.setInlineResource(inlineResource.toProto());
+ return this;
+ }
+
+ /**
+ * Sets a non-seekable animated image resource that maps to an Android drawable by
+ * resource ID. The animation is started with given trigger, fire and forget.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setAndroidAnimatedResourceByResId(
+ @NonNull AndroidAnimatedImageResourceByResId androidAnimatedResourceByResId) {
+ mImpl.setAndroidAnimatedResourceByResId(androidAnimatedResourceByResId.toProto());
+ return this;
+ }
+
+ /**
+ * Sets a seekable animated image resource that maps to an Android drawable by resource
+ * ID. The animation progress is bound to the provided dynamic float.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setAndroidSeekableAnimatedResourceByResId(
+ @NonNull
+ AndroidSeekableAnimatedImageResourceByResId
+ androidSeekableAnimatedResourceByResId) {
+ mImpl.setAndroidSeekableAnimatedResourceByResId(
+ androidSeekableAnimatedResourceByResId.toProto());
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public ImageResource build() {
+ return ImageResource.fromProto(mImpl.build());
+ }
+ }
+ }
+
+ /**
+ * The resources for a layout.
+ *
+ * @since 1.0
+ */
+ public static final class Resources {
+ private final ResourceProto.Resources mImpl;
+
+ Resources(ResourceProto.Resources impl) {
+ this.mImpl = impl;
+ }
+
+ /**
+ * Gets the version of this {@link Resources} instance.
+ *
+ * <p>Each layout specifies the version of resources it requires. After fetching a layout,
+ * the renderer will use the resources version specified by the layout to separately fetch
+ * the resources.
+ *
+ * <p>This value must match the version of the resources required by the layout for the
+ * layout to render successfully, and must match the resource version specified in
+ * ResourcesRequest which triggered this request.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public String getVersion() {
+ return mImpl.getVersion();
+ }
+
+ /**
+ * Gets a map of resource_ids to images, which can be used by layouts.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Map<String, ImageResource> getIdToImageMapping() {
+ Map<String, ImageResource> map = new HashMap<>();
+ for (Entry<String, ResourceProto.ImageResource> entry :
+ mImpl.getIdToImageMap().entrySet()) {
+ map.put(entry.getKey(), ImageResource.fromProto(entry.getValue()));
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ @NonNull
+ static Resources fromProto(@NonNull ResourceProto.Resources proto) {
+ return new Resources(proto);
+ }
+
+ /**
+ * Returns the internal proto instance.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public ResourceProto.Resources toProto() {
+ return mImpl;
+ }
+
+ /** Builder for {@link Resources} */
+ public static final class Builder {
+ private final ResourceProto.Resources.Builder mImpl =
+ ResourceProto.Resources.newBuilder();
+
+ public Builder() {}
+
+ /**
+ * Sets the version of this {@link Resources} instance.
+ *
+ * <p>Each layout specifies the version of resources it requires. After fetching a
+ * layout, the renderer will use the resources version specified by the layout to
+ * separately fetch the resources.
+ *
+ * <p>This value must match the version of the resources required by the layout for the
+ * layout to render successfully, and must match the resource version specified in
+ * ResourcesRequest which triggered this request.
+ *
+ * @since 1.0
+ */
+ @NonNull
+ public Builder setVersion(@NonNull String version) {
+ mImpl.setVersion(version);
+ return this;
+ }
+
+ /**
+ * Adds an entry into a map of resource_ids to images, which can be used by layouts.
+ *
+ * @since 1.0
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder addIdToImageMapping(@NonNull String id, @NonNull ImageResource image) {
+ mImpl.putIdToImage(id, image.toProto());
+ return this;
+ }
+
+ /** Builds an instance from accumulated values. */
+ @NonNull
+ public Resources build() {
+ return Resources.fromProto(mImpl.build());
+ }
+ }
+ }
}
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java
new file mode 100644
index 0000000..675364c
--- /dev/null
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/TriggerBuilders.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2022 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.wear.protolayout;
+
+import static androidx.wear.protolayout.expression.Preconditions.checkNotNull;
+
+import android.annotation.SuppressLint;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.expression.DynamicBuilders;
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.TriggerProto;
+
+/** Builders for triggers that can be used to start an animation. */
+public final class TriggerBuilders {
+ private TriggerBuilders() {}
+
+ /** Shortcut for building an {@link OnLoadTrigger}. */
+ @NonNull
+ public static OnLoadTrigger createOnLoadTrigger() {
+ return new OnLoadTrigger.Builder().build();
+ }
+
+ /** Shortcut for building an {@link OnConditionMetTrigger}. */
+ @NonNull
+ public static OnConditionMetTrigger createOnConditionMetTrigger(
+ @NonNull DynamicBool dynamicBool) {
+ return new OnConditionMetTrigger.Builder().setTrigger(dynamicBool).build();
+ }
+
+ /**
+ * Triggers immediately when the layout is loaded / reloaded.
+ *
+ * @since 1.2
+ */
+ public static final class OnLoadTrigger implements Trigger {
+ private final TriggerProto.OnLoadTrigger mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ OnLoadTrigger(TriggerProto.OnLoadTrigger impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static OnLoadTrigger fromProto(@NonNull TriggerProto.OnLoadTrigger proto) {
+ return new OnLoadTrigger(proto, null);
+ }
+
+ @NonNull
+ TriggerProto.OnLoadTrigger toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public TriggerProto.Trigger toTriggerProto() {
+ return TriggerProto.Trigger.newBuilder().setOnLoadTrigger(mImpl).build();
+ }
+
+ /** Builder for {@link OnLoadTrigger}. */
+ public static final class Builder implements Trigger.Builder {
+ private final TriggerProto.OnLoadTrigger.Builder mImpl =
+ TriggerProto.OnLoadTrigger.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(-1262805599);
+
+ public Builder() {}
+
+ @Override
+ @NonNull
+ public OnLoadTrigger build() {
+ return new OnLoadTrigger(mImpl.build(), mFingerprint);
+ }
+ }
+ }
+
+ /**
+ * Triggers *every time* the condition switches from false to true. If the condition is true
+ * initially, that will fire the trigger on load.
+ *
+ * @since 1.2
+ */
+ public static final class OnConditionMetTrigger implements Trigger {
+ private final TriggerProto.OnConditionTrigger mImpl;
+ @Nullable private final Fingerprint mFingerprint;
+
+ OnConditionMetTrigger(TriggerProto.OnConditionTrigger impl, @Nullable Fingerprint fingerprint) {
+ this.mImpl = impl;
+ this.mFingerprint = fingerprint;
+ }
+
+ /**
+ * Gets dynamic boolean used as trigger. Intended for testing purposes only.
+ *
+ * @since 1.2
+ */
+ @Nullable
+ public DynamicBool getTrigger() {
+ if (mImpl.hasDynamicBool()) {
+ return DynamicBuilders.dynamicBoolFromProto(mImpl.getDynamicBool());
+ } else {
+ return null;
+ }
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ public Fingerprint getFingerprint() {
+ return mFingerprint;
+ }
+
+ @NonNull
+ static OnConditionMetTrigger fromProto(@NonNull TriggerProto.OnConditionTrigger proto) {
+ return new OnConditionMetTrigger(proto, null);
+ }
+
+ @NonNull
+ TriggerProto.OnConditionTrigger toProto() {
+ return mImpl;
+ }
+
+ /** @hide */
+ @Override
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public TriggerProto.Trigger toTriggerProto() {
+ return TriggerProto.Trigger.newBuilder().setOnConditionTrigger(mImpl).build();
+ }
+
+ /** Builder for {@link OnConditionMetTrigger}. */
+ public static final class Builder implements Trigger.Builder {
+ private final TriggerProto.OnConditionTrigger.Builder mImpl =
+ TriggerProto.OnConditionTrigger.newBuilder();
+ private final Fingerprint mFingerprint = new Fingerprint(1952746052);
+
+ public Builder() {}
+
+ /**
+ * Sets dynamic boolean used as trigger.
+ *
+ * @since 1.2
+ */
+ @NonNull
+ public Builder setTrigger(@NonNull DynamicBool dynamicBool) {
+ mImpl.setDynamicBool(dynamicBool.toDynamicBoolProto());
+ mFingerprint.recordPropertyUpdate(
+ 1, checkNotNull(dynamicBool.getFingerprint()).aggregateValueAsInt());
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public OnConditionMetTrigger build() {
+ return new OnConditionMetTrigger(mImpl.build(), mFingerprint);
+ }
+ }
+ }
+
+ /**
+ * Interface defining the triggers that can be fired. These triggers can be used to allow
+ * acting on events. For example some animations can be set to start based on a trigger.
+ *
+ * @since 1.2
+ */
+ public interface Trigger {
+ /**
+ * Get the protocol buffer representation of this object.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ TriggerProto.Trigger toTriggerProto();
+
+ /**
+ * Get the fingerprint for this object or null if unknown.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ Fingerprint getFingerprint();
+
+ /** Builder to create {@link Trigger} objects.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ interface Builder {
+
+ /** Builds an instance with values accumulated in this Builder. */
+ @NonNull
+ Trigger build();
+ }
+ }
+
+ @NonNull
+ static Trigger triggerFromProto(@NonNull TriggerProto.Trigger proto) {
+ if (proto.hasOnLoadTrigger()) {
+ return OnLoadTrigger.fromProto(proto.getOnLoadTrigger());
+ }
+ if (proto.hasOnConditionTrigger()) {
+ return OnConditionMetTrigger.fromProto(proto.getOnConditionTrigger());
+ }
+ throw new IllegalStateException("Proto was not a recognised instance of Trigger");
+ }
+}
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java
new file mode 100644
index 0000000..2f54d7b
--- /dev/null
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2023 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.wear.protolayout;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.wear.protolayout.proto.DimensionProto;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class DimensionBuildersTest {
+
+ @Test
+ public void expandedLayoutWeight() {
+ float layoutWeight = 3.14f;
+ DimensionBuilders.ContainerDimension dimensionProp =
+ new DimensionBuilders.ExpandedDimensionProp.Builder().setLayoutWeight(layoutWeight)
+ .build();
+
+ DimensionProto.ContainerDimension dimensionProto =
+ dimensionProp.toContainerDimensionProto();
+ assertThat(dimensionProto.getExpandedDimension().getLayoutWeight().getValue())
+ .isWithin(.001f).of(layoutWeight);
+ }
+
+
+ @Test
+ public void wrappedMinSize() {
+ int minSizeDp = 42;
+ DimensionBuilders.ContainerDimension dimensionProp =
+ new DimensionBuilders.WrappedDimensionProp.Builder().setMinimumSizeDp(minSizeDp)
+ .build();
+
+ DimensionProto.ContainerDimension dimensionProto =
+ dimensionProp.toContainerDimensionProto();
+ assertThat(dimensionProto.getWrappedDimension().getMinimumSize().getValue())
+ .isEqualTo(minSizeDp);
+ }
+}
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java
new file mode 100644
index 0000000..59f2df8
--- /dev/null
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2023 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.wear.protolayout;
+
+import static androidx.wear.protolayout.ResourceBuilders.ANIMATED_IMAGE_FORMAT_AVD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.wear.protolayout.expression.DynamicBuilders;
+import androidx.wear.protolayout.proto.ResourceProto;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class ResourceBuildersTest {
+ private static final int RESOURCE_ID = 10;
+ private static final int FORMAT = ANIMATED_IMAGE_FORMAT_AVD;
+
+ @Test
+ public void avd() {
+ ResourceBuilders.AndroidAnimatedImageResourceByResId avd =
+ new ResourceBuilders.AndroidAnimatedImageResourceByResId.Builder()
+ .setResourceId(RESOURCE_ID)
+ .setAnimatedImageFormat(FORMAT)
+ .setStartTrigger(TriggerBuilders.createOnLoadTrigger())
+ .build();
+
+ ResourceProto.AndroidAnimatedImageResourceByResId avdProto = avd.toProto();
+
+ assertThat(avdProto.getResourceId()).isEqualTo(RESOURCE_ID);
+ assertThat(avdProto.getFormat().getNumber()).isEqualTo(FORMAT);
+ assertThat(avdProto.getTrigger().hasOnLoadTrigger()).isTrue();
+ }
+
+ @Test
+ public void seekableAvd() {
+ String stateKey = "state-key";
+ ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId avd =
+ new ResourceBuilders.AndroidSeekableAnimatedImageResourceByResId.Builder()
+ .setResourceId(RESOURCE_ID)
+ .setAnimatedImageFormat(FORMAT)
+ .setProgress(DynamicBuilders.DynamicFloat.fromState(stateKey))
+ .build();
+
+ ResourceProto.AndroidSeekableAnimatedImageResourceByResId avdProto = avd.toProto();
+
+ assertThat(avdProto.getResourceId()).isEqualTo(RESOURCE_ID);
+ assertThat(avdProto.getFormat().getNumber()).isEqualTo(FORMAT);
+ assertThat(avdProto.getProgress().getStateSource().getSourceKey()).isEqualTo(stateKey);
+ }
+}
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/TriggerBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/TriggerBuildersTest.java
new file mode 100644
index 0000000..5b3260e
--- /dev/null
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/TriggerBuildersTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 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.wear.protolayout;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.wear.protolayout.expression.DynamicBuilders;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class TriggerBuildersTest {
+
+ @Test
+ public void onLoadTrigger() {
+ TriggerBuilders.OnLoadTrigger onLoadTrigger = TriggerBuilders.createOnLoadTrigger();
+
+ assertThat(onLoadTrigger.toTriggerProto().hasOnLoadTrigger()).isTrue();
+ }
+
+
+ @Test
+ public void onConditionTrigger() {
+ DynamicBuilders.DynamicBool condition = DynamicBuilders.DynamicBool.fromState("state");
+
+ TriggerBuilders.OnConditionMetTrigger onConditionMetTrigger =
+ TriggerBuilders.createOnConditionMetTrigger(
+ condition);
+
+ assertThat(
+ onConditionMetTrigger.toTriggerProto().getOnConditionTrigger().getDynamicBool())
+ .isEqualTo(condition.toDynamicBoolProto());
+ }
+}
diff --git a/wear/watchface/watchface-client-guava/api/current.txt b/wear/watchface/watchface-client-guava/api/current.txt
index 4c88746..1b8efee 100644
--- a/wear/watchface/watchface-client-guava/api/current.txt
+++ b/wear/watchface/watchface-client-guava/api/current.txt
@@ -11,9 +11,9 @@
method public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient();
method public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId);
method @Deprecated public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
- method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
+ method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData);
- method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener);
field public static final androidx.wear.watchface.client.ListenableWatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt b/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
index 4c88746..1b8efee 100644
--- a/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
@@ -11,9 +11,9 @@
method public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient();
method public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId);
method @Deprecated public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
- method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
+ method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData);
- method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener);
field public static final androidx.wear.watchface.client.ListenableWatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client-guava/api/restricted_current.txt b/wear/watchface/watchface-client-guava/api/restricted_current.txt
index 4c88746..1b8efee 100644
--- a/wear/watchface/watchface-client-guava/api/restricted_current.txt
+++ b/wear/watchface/watchface-client-guava/api/restricted_current.txt
@@ -11,9 +11,9 @@
method public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient();
method public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId);
method @Deprecated public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
- method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
+ method public suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>);
method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData);
- method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.InteractiveWatchFaceClient> listenableGetOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener);
field public static final androidx.wear.watchface.client.ListenableWatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
index 338f592..e3de152 100644
--- a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
@@ -19,6 +19,7 @@
import android.content.ComponentName
import android.content.Context
import androidx.concurrent.futures.ResolvableFuture
+import androidx.core.util.Consumer
import androidx.wear.watchface.Renderer
import androidx.wear.watchface.client.WatchFaceControlClient.ServiceNotBoundException
import androidx.wear.watchface.complications.data.ComplicationData
@@ -26,7 +27,6 @@
import androidx.wear.watchface.utility.AsyncTraceEvent
import com.google.common.util.concurrent.ListenableFuture
import java.util.concurrent.Executor
-import java.util.function.Consumer
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
diff --git a/wear/watchface/watchface-client/api/current.txt b/wear/watchface/watchface-client/api/current.txt
index b7a6bc0..04a3c4c 100644
--- a/wear/watchface/watchface-client/api/current.txt
+++ b/wear/watchface/watchface-client/api/current.txt
@@ -190,7 +190,7 @@
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
- method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
+ method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
method public default boolean hasComplicationDataCache();
field public static final androidx.wear.watchface.client.WatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client/api/public_plus_experimental_current.txt b/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
index ff5390c..16c73b9 100644
--- a/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
@@ -131,7 +131,7 @@
public interface InteractiveWatchFaceClient extends java.lang.AutoCloseable {
method @AnyThread public void addClientDisconnectListener(androidx.wear.watchface.client.InteractiveWatchFaceClient.ClientDisconnectListener listener, java.util.concurrent.Executor executor);
- method @androidx.wear.watchface.client.WatchFaceClientExperimental public default void addOnWatchFaceColorsListener(java.util.concurrent.Executor executor, java.util.function.Consumer<androidx.wear.watchface.WatchFaceColors> listener);
+ method @androidx.wear.watchface.client.WatchFaceClientExperimental public default void addOnWatchFaceColorsListener(java.util.concurrent.Executor executor, androidx.core.util.Consumer<androidx.wear.watchface.WatchFaceColors> listener);
method public void addOnWatchFaceReadyListener(java.util.concurrent.Executor executor, androidx.wear.watchface.client.InteractiveWatchFaceClient.OnWatchFaceReadyListener listener);
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default Integer? getComplicationIdAt(@Px int x, @Px int y) throws android.os.RemoteException;
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.ComplicationSlotState> getComplicationSlotsState() throws android.os.RemoteException;
@@ -144,7 +144,7 @@
method @AnyThread public boolean isConnectionAlive();
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public void performAmbientTick() throws android.os.RemoteException;
method @AnyThread public void removeClientDisconnectListener(androidx.wear.watchface.client.InteractiveWatchFaceClient.ClientDisconnectListener listener);
- method @androidx.wear.watchface.client.WatchFaceClientExperimental public default void removeOnWatchFaceColorsListener(java.util.function.Consumer<androidx.wear.watchface.WatchFaceColors> listener);
+ method @androidx.wear.watchface.client.WatchFaceClientExperimental public default void removeOnWatchFaceColorsListener(androidx.core.util.Consumer<androidx.wear.watchface.WatchFaceColors> listener);
method public void removeOnWatchFaceReadyListener(androidx.wear.watchface.client.InteractiveWatchFaceClient.OnWatchFaceReadyListener listener);
method @RequiresApi(27) @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public android.graphics.Bitmap renderWatchFaceToBitmap(androidx.wear.watchface.RenderParameters renderParameters, java.time.Instant instant, androidx.wear.watchface.style.UserStyle? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? idAndComplicationData) throws android.os.RemoteException;
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public void sendTouchEvent(@Px int xPosition, @Px int yPosition, @androidx.wear.watchface.TapType int tapType) throws android.os.RemoteException;
@@ -199,7 +199,7 @@
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
- method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
+ method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
method public default boolean hasComplicationDataCache();
field public static final androidx.wear.watchface.client.WatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client/api/restricted_current.txt b/wear/watchface/watchface-client/api/restricted_current.txt
index b7a6bc0..04a3c4c 100644
--- a/wear/watchface/watchface-client/api/restricted_current.txt
+++ b/wear/watchface/watchface-client/api/restricted_current.txt
@@ -190,7 +190,7 @@
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
- method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, java.util.function.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
+ method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public default suspend Object? getOrCreateInteractiveWatchFaceClient(String instanceId, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, java.util.concurrent.Executor previewImageUpdateRequestedExecutor, androidx.core.util.Consumer<java.lang.String> previewImageUpdateRequestedListener, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient>) throws android.os.RemoteException;
method public default boolean hasComplicationDataCache();
field public static final androidx.wear.watchface.client.WatchFaceControlClient.Companion Companion;
}
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
index 365da36..b723da6 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
@@ -34,6 +34,7 @@
import android.view.SurfaceHolder
import androidx.annotation.CallSuper
import androidx.annotation.RequiresApi
+import androidx.core.util.Consumer
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
@@ -98,7 +99,6 @@
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
-import java.util.function.Consumer
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
index 566abd4..394bcfa 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
@@ -25,6 +25,7 @@
import androidx.annotation.IntDef
import androidx.annotation.Px
import androidx.annotation.RequiresApi
+import androidx.core.util.Consumer
import androidx.wear.watchface.ComplicationSlot
import androidx.wear.watchface.ComplicationSlotBoundsType
import androidx.wear.watchface.ComplicationSlotsManager
@@ -52,7 +53,6 @@
import androidx.wear.watchface.utility.TraceEvent
import java.time.Instant
import java.util.concurrent.Executor
-import java.util.function.Consumer
/** @hide */
@IntDef(value = [DisconnectReasons.ENGINE_DIED, DisconnectReasons.ENGINE_DETACHED])
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
index fad38e4..e9177de 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
@@ -23,6 +23,7 @@
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
+import androidx.core.util.Consumer
import androidx.annotation.Px
import androidx.annotation.RestrictTo
import androidx.wear.watchface.Renderer
@@ -44,7 +45,6 @@
import androidx.wear.watchface.utility.AsyncTraceEvent
import androidx.wear.watchface.utility.TraceEvent
import java.util.concurrent.Executor
-import java.util.function.Consumer
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.CompletableDeferred
diff --git a/wear/watchface/watchface-complications-data-source/api/current.txt b/wear/watchface/watchface-complications-data-source/api/current.txt
index 73e5e61..d348447 100644
--- a/wear/watchface/watchface-complications-data-source/api/current.txt
+++ b/wear/watchface/watchface-complications-data-source/api/current.txt
@@ -52,14 +52,17 @@
}
public final class ComplicationRequest {
+ ctor @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired, Boolean? isForSafeWatchFace);
ctor public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired);
ctor @Deprecated public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType);
method public int getComplicationInstanceId();
method public androidx.wear.watchface.complications.data.ComplicationType getComplicationType();
+ method public Boolean? isForSafeWatchFace();
method public boolean isImmediateResponseRequired();
property public final int complicationInstanceId;
property public final androidx.wear.watchface.complications.data.ComplicationType complicationType;
property public final boolean immediateResponseRequired;
+ property public final Boolean? isForSafeWatchFace;
}
public final class TimeInterval {
diff --git a/wear/watchface/watchface-complications-data-source/api/public_plus_experimental_current.txt b/wear/watchface/watchface-complications-data-source/api/public_plus_experimental_current.txt
index 73e5e61..d348447 100644
--- a/wear/watchface/watchface-complications-data-source/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-complications-data-source/api/public_plus_experimental_current.txt
@@ -52,14 +52,17 @@
}
public final class ComplicationRequest {
+ ctor @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired, Boolean? isForSafeWatchFace);
ctor public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired);
ctor @Deprecated public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType);
method public int getComplicationInstanceId();
method public androidx.wear.watchface.complications.data.ComplicationType getComplicationType();
+ method public Boolean? isForSafeWatchFace();
method public boolean isImmediateResponseRequired();
property public final int complicationInstanceId;
property public final androidx.wear.watchface.complications.data.ComplicationType complicationType;
property public final boolean immediateResponseRequired;
+ property public final Boolean? isForSafeWatchFace;
}
public final class TimeInterval {
diff --git a/wear/watchface/watchface-complications-data-source/api/restricted_current.txt b/wear/watchface/watchface-complications-data-source/api/restricted_current.txt
index 73e5e61..d348447 100644
--- a/wear/watchface/watchface-complications-data-source/api/restricted_current.txt
+++ b/wear/watchface/watchface-complications-data-source/api/restricted_current.txt
@@ -52,14 +52,17 @@
}
public final class ComplicationRequest {
+ ctor @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired, Boolean? isForSafeWatchFace);
ctor public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType, boolean immediateResponseRequired);
ctor @Deprecated public ComplicationRequest(int complicationInstanceId, androidx.wear.watchface.complications.data.ComplicationType complicationType);
method public int getComplicationInstanceId();
method public androidx.wear.watchface.complications.data.ComplicationType getComplicationType();
+ method public Boolean? isForSafeWatchFace();
method public boolean isImmediateResponseRequired();
property public final int complicationInstanceId;
property public final androidx.wear.watchface.complications.data.ComplicationType complicationType;
property public final boolean immediateResponseRequired;
+ property public final Boolean? isForSafeWatchFace;
}
public final class TimeInterval {
diff --git a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
index 2450fd86..6197888 100644
--- a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
+++ b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
@@ -31,6 +31,7 @@
import android.support.wearable.complications.IComplicationManager
import android.support.wearable.complications.IComplicationProvider
import androidx.annotation.MainThread
+import androidx.annotation.RequiresApi
import androidx.annotation.RestrictTo
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationDataExpressionEvaluator
@@ -60,12 +61,34 @@
* deadline). This will only be `true` within a
* [ComplicationDataSourceService.onStartImmediateComplicationRequests]
* [ComplicationDataSourceService.onStopImmediateComplicationRequests] pair.
+ * @param isForSafeWatchFace Whether this request is on behalf of a 'safe' watch face as defined by
+ * the [ComplicationDataSourceService.METADATA_KEY_SAFE_WATCH_FACES] meta data in the data
+ * source's manifest. The data source may choose to serve different results for a 'safe' watch
+ * face. If the data source does not have the privileged permission
+ * `com.google.wear.permission.GET_IS_FOR_SAFE_WATCH_FACE`, then this must be null.
*/
-public class ComplicationRequest(
+public class ComplicationRequest
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+constructor(
complicationInstanceId: Int,
complicationType: ComplicationType,
- immediateResponseRequired: Boolean
+ immediateResponseRequired: Boolean,
+ @Suppress("AutoBoxing")
+ isForSafeWatchFace: Boolean?
) {
+ /** Constructs a [ComplicationRequest] without setting [isForSafeWatchFace]. */
+ @Suppress("NewApi")
+ constructor(
+ complicationInstanceId: Int,
+ complicationType: ComplicationType,
+ immediateResponseRequired: Boolean,
+ ) : this(
+ complicationInstanceId,
+ complicationType,
+ immediateResponseRequired,
+ isForSafeWatchFace = false
+ )
+
/**
* The system's id for the requested complication which is a unique value for the tuple
* [Watch face ComponentName, complication slot ID].
@@ -86,6 +109,23 @@
@get:JvmName("isImmediateResponseRequired")
public val immediateResponseRequired = immediateResponseRequired
+ /**
+ * Intended for OEM use, returns whether this request is on behalf of a 'safe' watch face as
+ * defined by the [ComplicationDataSourceService.METADATA_KEY_SAFE_WATCH_FACES] meta data in the
+ * data source's manifest. The data source may choose to serve different results for a 'safe'
+ * watch face.
+ *
+ * If the [ComplicationDataSourceService.METADATA_KEY_SAFE_WATCH_FACES] meta data is not defined
+ * then this will be false.
+ *
+ * If the DataSourceService does not have the privileged permission
+ * `com.google.wear.permission.GET_IS_FOR_SAFE_WATCH_FACE`, then this will be null.
+ */
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @get:JvmName("isForSafeWatchFace")
+ @get:Suppress("AutoBoxing")
+ public val isForSafeWatchFace: Boolean? = isForSafeWatchFace
+
@Deprecated("Use a constructor that specifies responseNeededSoon.")
constructor(
complicationInstanceId: Int,
@@ -140,7 +180,7 @@
* also register a separate [METADATA_KEY_IMMEDIATE_UPDATE_PERIOD_MILLISECONDS] meta data tag which
* supports sampling at up to 1Hz when the watch face is visible and non-ambient, however this also
* requires the DataSourceService to have the privileged permission
- * com.google.android.wearable.permission.USE_IMMEDIATE_COMPLICATION_UPDATE.
+ * `com.google.android.wearable.permission.USE_IMMEDIATE_COMPLICATION_UPDATE`.
*
* ```
* <meta-data android:name=
@@ -251,7 +291,7 @@
* deadline is 20 seconds. [ComplicationRequest.immediateResponseRequired] will only ever be
* `true` if [METADATA_KEY_IMMEDIATE_UPDATE_PERIOD_MILLISECONDS] is present in the manifest, and
* the provider has the privileged permission
- * com.google.android.wearable.permission.USE_IMMEDIATE_COMPLICATION_UPDATE, and the
+ * `com.google.android.wearable.permission.USE_IMMEDIATE_COMPLICATION_UPDATE`, and the
* complication is visible and non-ambient.
*
* @param request The details about the complication that has been requested.
@@ -350,14 +390,26 @@
private inner class IComplicationProviderWrapper : IComplicationProvider.Stub() {
@SuppressLint("SyntheticAccessor")
override fun onUpdate(complicationInstanceId: Int, type: Int, manager: IBinder) {
+ onUpdate2(complicationInstanceId, type, isForSafeWatchFace = false, manager)
+ }
+
+ @SuppressLint("SyntheticAccessor")
+ override fun onUpdate2(
+ complicationInstanceId: Int,
+ type: Int,
+ isForSafeWatchFace: Boolean,
+ manager: IBinder
+ ) {
val expectedDataType = fromWireType(type)
val iComplicationManager = IComplicationManager.Stub.asInterface(manager)
mainThreadHandler.post {
onComplicationRequest(
+ @Suppress("NewApi")
ComplicationRequest(
complicationInstanceId,
expectedDataType,
- immediateResponseRequired = false
+ immediateResponseRequired = false,
+ isForSafeWatchFace = isForSafeWatchFace
),
object : ComplicationRequestListener {
override fun onComplicationData(complicationData: ComplicationData?) {
@@ -553,6 +605,16 @@
override fun onSynchronousComplicationRequest(
complicationInstanceId: Int,
type: Int
+ ) = onSynchronousComplicationRequest2(
+ complicationInstanceId,
+ isForSafeWatchFace = false,
+ type
+ )
+
+ override fun onSynchronousComplicationRequest2(
+ complicationInstanceId: Int,
+ isForSafeWatchFace: Boolean,
+ type: Int
): android.support.wearable.complications.ComplicationData? {
val expectedDataType = fromWireType(type)
val complicationType = fromWireType(type)
@@ -561,10 +623,12 @@
null
mainThreadHandler.post {
[email protected](
+ @Suppress("NewApi")
ComplicationRequest(
complicationInstanceId,
complicationType,
- immediateResponseRequired = true
+ immediateResponseRequired = true,
+ isForSafeWatchFace = isForSafeWatchFace
),
object : ComplicationRequestListener {
override fun onComplicationData(complicationData: ComplicationData?) {
@@ -717,6 +781,11 @@
* called, to declare a specific watch face as safe. An entry can also be a package name, as
* if [ComponentName.getPackageName] had been called, in which case any watch face under the
* app with that package name will be considered safe for this complication data source.
+ *
+ * From Android T, if this provider has the privileged permission
+ * com.google.wear.permission.GET_IS_FOR_SAFE_WATCH_FACEl, then
+ * [ComplicationRequest.isForSafeWatchFace] will be true if the request is on behalf of a
+ * watch face in this list.
*/
// TODO(b/192233205): Migrate value to androidx.
public const val METADATA_KEY_SAFE_WATCH_FACES: String =
diff --git a/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceServiceTest.kt b/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceServiceTest.kt
index a568b67..901fd9d 100644
--- a/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceServiceTest.kt
+++ b/wear/watchface/watchface-complications-data-source/src/test/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceServiceTest.kt
@@ -15,13 +15,13 @@
*/
package androidx.wear.watchface.complications.datasource
+import android.support.wearable.complications.ComplicationData as WireComplicationData
import android.content.Intent
import android.content.res.Resources
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.RemoteException
-import android.support.wearable.complications.ComplicationData as WireComplicationData
import android.support.wearable.complications.IComplicationManager
import android.support.wearable.complications.IComplicationProvider
import android.util.Log
@@ -172,6 +172,25 @@
}
@Test
+ fun testOnComplicationRequest_isForSafeWatchFace() {
+ mService.responseData = LongTextComplicationData.Builder(
+ PlainComplicationText.Builder("hello").build(),
+ ComplicationText.EMPTY
+ ).build()
+ val id = 123
+
+ @Suppress("NewApi") // onUpdate2
+ mProvider.onUpdate2(
+ id, ComplicationType.LONG_TEXT.toWireComplicationType(),
+ /* isForSafeWatchFace= */ true, mLocalManager
+ )
+
+ assertThat(mUpdateComplicationDataLatch.await(1000, TimeUnit.MILLISECONDS)).isTrue()
+ @Suppress("NewApi") // isForSafeWatchFace
+ assertThat(mService.lastRequest!!.isForSafeWatchFace).isTrue()
+ }
+
+ @Test
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
fun testOnComplicationRequestWithExpression_doesNotEvaluateExpression() {
mService.responseData =
@@ -453,6 +472,45 @@
}
}
+ @Test
+ @Suppress("NewApi") // onSynchronousComplicationRequest2
+ fun testImmediateRequest_isForSafeWatchFace() {
+ val id = 123
+ mService.responseData = LongTextComplicationData.Builder(
+ PlainComplicationText.Builder("hello").build(),
+ ComplicationText.EMPTY
+ ).build()
+ val thread = HandlerThread("testThread")
+ try {
+ thread.start()
+ val threadHandler = Handler(thread.looper)
+ val response =
+ AtomicReference<android.support.wearable.complications.ComplicationData>()
+ val doneLatch = CountDownLatch(1)
+ threadHandler.post {
+ try {
+ @Suppress("NewApi") // onSynchronousComplicationRequest2
+ response.set(
+ mProvider.onSynchronousComplicationRequest2(
+ id,
+ /* isForSafeWatchFace= */ true,
+ ComplicationType.LONG_TEXT.toWireComplicationType()
+ )
+ )
+ doneLatch.countDown()
+ } catch (e: RemoteException) {
+ // Should not happen
+ }
+ }
+
+ assertThat(doneLatch.await(1000, TimeUnit.MILLISECONDS)).isTrue()
+ @Suppress("NewApi") // isForSafeWatchFace
+ assertThat(mService.lastRequest!!.isForSafeWatchFace).isTrue()
+ } finally {
+ thread.quitSafely()
+ }
+ }
+
private fun runUiThreadTasksWhileAwaitingDataLatch(timeout: Long) {
// Allowing UI thread to execute while we wait for the data latch.
var attempts: Long = 0
diff --git a/wear/watchface/watchface-complications-data/src/main/aidl/android/support/wearable/complications/IComplicationProvider.aidl b/wear/watchface/watchface-complications-data/src/main/aidl/android/support/wearable/complications/IComplicationProvider.aidl
index e496132..d5e8eba 100644
--- a/wear/watchface/watchface-complications-data/src/main/aidl/android/support/wearable/complications/IComplicationProvider.aidl
+++ b/wear/watchface/watchface-complications-data/src/main/aidl/android/support/wearable/complications/IComplicationProvider.aidl
@@ -15,7 +15,7 @@
/**
* API version number. This should be incremented every time a new method is added.
*/
- const int API_VERSION = 2;
+ const int API_VERSION = 3;
/**
* Called when a complication data update is requested for the given complication id.
@@ -132,4 +132,30 @@
* @since API version 2.
*/
ComplicationData onSynchronousComplicationRequest(int complicationInstanceId, int type) = 7;
+
+ /**
+ * Same as {@link #onUpdate}, but specifies isForSafeWatchFace.
+ *
+ * @param complicationInstanceId The system's id for the updated complication which is a unique
+ * value for the tuple [Watch face ComponentName, complication slot ID].
+ * @param type The type of complication requested
+ * @param manager The binder for IComplicationManager
+ * @param isForSafeWatchFace Whether this request is on behalf of a safe watchface as defined by
+ * the data source.
+ * @since API version 3.
+ */
+ void onUpdate2(int complicationInstanceId, int type, boolean isForSafeWatchFace,
+ IBinder manager) = 8;
+
+ /**
+ * Same as {@link #onSynchronousComplicationRequest2}, but specifies isForSafeWatchFace.
+ *
+ * @param complicationInstanceId The system's id for the requested complication which is a
+ * @param type The type of complication requested
+ * unique value for the tuple [Watch face ComponentName, complication slot ID].
+ * @return The updated ComplicationData or null if no update is necessary
+ * @since API version 3.
+ */
+ ComplicationData onSynchronousComplicationRequest2(int complicationInstanceId,
+ boolean isForSafeWatchFace, int type) = 9;
}
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
index ae7dd7e..b18b07e 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluator.kt
@@ -20,6 +20,7 @@
import android.support.wearable.complications.ComplicationData as WireComplicationData
import android.support.wearable.complications.ComplicationText as WireComplicationText
import androidx.annotation.RestrictTo
+import androidx.core.util.Consumer
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat
import androidx.wear.protolayout.expression.pipeline.BoundDynamicType
import androidx.wear.protolayout.expression.pipeline.DynamicTypeEvaluator
@@ -27,7 +28,6 @@
import androidx.wear.protolayout.expression.pipeline.ObservableStateStore
import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway
import java.util.concurrent.Executor
-import java.util.function.Consumer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
@@ -62,7 +62,6 @@
@JvmOverloads
constructor(
val unevaluatedData: WireComplicationData,
- private val executor: Executor,
private val listener: Consumer<WireComplicationData>,
stateStore: ObservableStateStore = ObservableStateStore(emptyMap()),
sensorGateway: SensorGateway? = null,
@@ -70,8 +69,11 @@
private val evaluator =
ComplicationDataExpressionEvaluator(unevaluatedData, stateStore, sensorGateway)
- /** @see ComplicationDataExpressionEvaluator.init */
- fun init() {
+ /**
+ * @see ComplicationDataExpressionEvaluator.init, [executor] is used in place of
+ * `coroutineScope`.
+ */
+ fun init(executor: Executor) {
evaluator.init()
evaluator.data
.filterNotNull()
@@ -101,13 +103,15 @@
* Parses the expression and starts blocking evaluation.
*
* This needs to be called exactly once.
+ *
+ * @param coroutineScope used for background evaluation
*/
- fun init() {
+ fun init(coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main)) {
// Add all the receivers before we start binding them because binding can synchronously
// trigger the receiver, which would update the data before all the fields are evaluated.
initStateReceivers()
initEvaluator()
- monitorState()
+ monitorState(coroutineScope)
}
/**
@@ -184,13 +188,13 @@
}
/** Monitors [state] changes and updates [data]. */
- private fun monitorState() {
+ private fun monitorState(coroutineScope: CoroutineScope) {
state
.onEach {
if (it.invalid.isNotEmpty()) _data.value = INVALID_DATA
else if (it.pending.isEmpty()) _data.value = it.data
}
- .launchIn(CoroutineScope(Dispatchers.Main))
+ .launchIn(coroutineScope)
}
/**
diff --git a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
index 47e9331..5834c42 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/ComplicationDataExpressionEvaluatorTest.kt
@@ -20,6 +20,7 @@
import android.support.wearable.complications.ComplicationText as WireComplicationText
import android.util.Log
import androidx.core.content.ContextCompat
+import androidx.core.util.Consumer
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString
@@ -29,7 +30,6 @@
import androidx.wear.watchface.complications.data.ComplicationDataExpressionEvaluator.Companion.hasExpression
import com.google.common.truth.Expect
import com.google.common.truth.Truth.assertThat
-import java.util.function.Consumer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
@@ -334,31 +334,22 @@
@Test
fun compat_notInitialized_listenerNotInvoked() {
- ComplicationDataExpressionEvaluator.Compat(
- DATA_WITH_NO_EXPRESSION,
- ContextCompat.getMainExecutor(getApplicationContext()),
- listener,
- )
- .use {
- runUiThreadTasks()
+ ComplicationDataExpressionEvaluator.Compat(DATA_WITH_NO_EXPRESSION, listener).use {
+ runUiThreadTasks()
- verify(listener, never()).accept(any())
- }
+ verify(listener, never()).accept(any())
+ }
}
@Test
fun compat_noExpression_listenerInvokedWithData() {
- ComplicationDataExpressionEvaluator.Compat(
- DATA_WITH_NO_EXPRESSION,
- ContextCompat.getMainExecutor(getApplicationContext()),
- listener,
- )
- .use { evaluator ->
- evaluator.init()
- runUiThreadTasks()
+ ComplicationDataExpressionEvaluator.Compat(DATA_WITH_NO_EXPRESSION, listener).use {
+ evaluator ->
+ evaluator.init(ContextCompat.getMainExecutor(getApplicationContext()))
+ runUiThreadTasks()
- verify(listener, times(1)).accept(DATA_WITH_NO_EXPRESSION)
- }
+ verify(listener, times(1)).accept(DATA_WITH_NO_EXPRESSION)
+ }
}
private companion object {
diff --git a/window/extensions/extensions/api/current.txt b/window/extensions/extensions/api/current.txt
index f0c699b..6988f4b 100644
--- a/window/extensions/extensions/api/current.txt
+++ b/window/extensions/extensions/api/current.txt
@@ -4,6 +4,7 @@
public interface WindowExtensions {
method public default androidx.window.extensions.embedding.ActivityEmbeddingComponent? getActivityEmbeddingComponent();
method public default int getVendorApiLevel();
+ method public default androidx.window.extensions.area.WindowAreaComponent? getWindowAreaComponent();
method public androidx.window.extensions.layout.WindowLayoutComponent? getWindowLayoutComponent();
}
@@ -13,6 +14,22 @@
}
+package androidx.window.extensions.area {
+
+ public interface WindowAreaComponent {
+ method public void addRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void endRearDisplaySession();
+ method public void removeRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void startRearDisplaySession(android.app.Activity, androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ field public static final int SESSION_STATE_ACTIVE = 1; // 0x1
+ field public static final int SESSION_STATE_INACTIVE = 0; // 0x0
+ field public static final int STATUS_AVAILABLE = 2; // 0x2
+ field public static final int STATUS_UNAVAILABLE = 1; // 0x1
+ field public static final int STATUS_UNSUPPORTED = 0; // 0x0
+ }
+
+}
+
package androidx.window.extensions.embedding {
public interface ActivityEmbeddingComponent {
@@ -52,6 +69,7 @@
method @ColorInt public int getAnimationBackgroundColor();
method public int getLayoutDirection();
method public androidx.window.extensions.embedding.SplitAttributes.SplitType getSplitType();
+ field @ColorInt public static final int DEFAULT_ANIMATION_BACKGROUND_COLOR = 0; // 0x0
}
public static final class SplitAttributes.Builder {
diff --git a/window/extensions/extensions/api/public_plus_experimental_current.txt b/window/extensions/extensions/api/public_plus_experimental_current.txt
index f0c699b..6988f4b 100644
--- a/window/extensions/extensions/api/public_plus_experimental_current.txt
+++ b/window/extensions/extensions/api/public_plus_experimental_current.txt
@@ -4,6 +4,7 @@
public interface WindowExtensions {
method public default androidx.window.extensions.embedding.ActivityEmbeddingComponent? getActivityEmbeddingComponent();
method public default int getVendorApiLevel();
+ method public default androidx.window.extensions.area.WindowAreaComponent? getWindowAreaComponent();
method public androidx.window.extensions.layout.WindowLayoutComponent? getWindowLayoutComponent();
}
@@ -13,6 +14,22 @@
}
+package androidx.window.extensions.area {
+
+ public interface WindowAreaComponent {
+ method public void addRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void endRearDisplaySession();
+ method public void removeRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void startRearDisplaySession(android.app.Activity, androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ field public static final int SESSION_STATE_ACTIVE = 1; // 0x1
+ field public static final int SESSION_STATE_INACTIVE = 0; // 0x0
+ field public static final int STATUS_AVAILABLE = 2; // 0x2
+ field public static final int STATUS_UNAVAILABLE = 1; // 0x1
+ field public static final int STATUS_UNSUPPORTED = 0; // 0x0
+ }
+
+}
+
package androidx.window.extensions.embedding {
public interface ActivityEmbeddingComponent {
@@ -52,6 +69,7 @@
method @ColorInt public int getAnimationBackgroundColor();
method public int getLayoutDirection();
method public androidx.window.extensions.embedding.SplitAttributes.SplitType getSplitType();
+ field @ColorInt public static final int DEFAULT_ANIMATION_BACKGROUND_COLOR = 0; // 0x0
}
public static final class SplitAttributes.Builder {
diff --git a/window/extensions/extensions/api/restricted_current.txt b/window/extensions/extensions/api/restricted_current.txt
index f0c699b..6988f4b 100644
--- a/window/extensions/extensions/api/restricted_current.txt
+++ b/window/extensions/extensions/api/restricted_current.txt
@@ -4,6 +4,7 @@
public interface WindowExtensions {
method public default androidx.window.extensions.embedding.ActivityEmbeddingComponent? getActivityEmbeddingComponent();
method public default int getVendorApiLevel();
+ method public default androidx.window.extensions.area.WindowAreaComponent? getWindowAreaComponent();
method public androidx.window.extensions.layout.WindowLayoutComponent? getWindowLayoutComponent();
}
@@ -13,6 +14,22 @@
}
+package androidx.window.extensions.area {
+
+ public interface WindowAreaComponent {
+ method public void addRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void endRearDisplaySession();
+ method public void removeRearDisplayStatusListener(androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ method public void startRearDisplaySession(android.app.Activity, androidx.window.extensions.core.util.function.Consumer<java.lang.Integer!>);
+ field public static final int SESSION_STATE_ACTIVE = 1; // 0x1
+ field public static final int SESSION_STATE_INACTIVE = 0; // 0x0
+ field public static final int STATUS_AVAILABLE = 2; // 0x2
+ field public static final int STATUS_UNAVAILABLE = 1; // 0x1
+ field public static final int STATUS_UNSUPPORTED = 0; // 0x0
+ }
+
+}
+
package androidx.window.extensions.embedding {
public interface ActivityEmbeddingComponent {
@@ -52,6 +69,7 @@
method @ColorInt public int getAnimationBackgroundColor();
method public int getLayoutDirection();
method public androidx.window.extensions.embedding.SplitAttributes.SplitType getSplitType();
+ field @ColorInt public static final int DEFAULT_ANIMATION_BACKGROUND_COLOR = 0; // 0x0
}
public static final class SplitAttributes.Builder {
diff --git a/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java b/window/extensions/extensions/src/androidTest/java/androidx/window/extensions/embedding/SplitAttributesTest.java
similarity index 93%
rename from window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java
rename to window/extensions/extensions/src/androidTest/java/androidx/window/extensions/embedding/SplitAttributesTest.java
index 76a1107..0bd4c63 100644
--- a/window/extensions/extensions/src/test/java/androidx/window/extensions/embedding/SplitAttributesTest.java
+++ b/window/extensions/extensions/src/androidTest/java/androidx/window/extensions/embedding/SplitAttributesTest.java
@@ -36,17 +36,17 @@
final SplitAttributes layout1 = new SplitAttributes.Builder()
.setSplitType(splitEqually())
.setLayoutDirection(LayoutDirection.LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
.build();
final SplitAttributes layout2 = new SplitAttributes.Builder()
.setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
.setLayoutDirection(LayoutDirection.LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
.build();
final SplitAttributes layout3 = new SplitAttributes.Builder()
.setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
.setLayoutDirection(LayoutDirection.TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.DEFAULT_ANIMATION_BACKGROUND_COLOR)
.build();
final SplitAttributes layout4 = new SplitAttributes.Builder()
.setSplitType(new SplitAttributes.SplitType.HingeSplitType(splitEqually()))
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/WindowExtensions.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/WindowExtensions.java
index 97a1a86..240e2dc 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/WindowExtensions.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/WindowExtensions.java
@@ -20,6 +20,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.window.extensions.area.WindowAreaComponent;
import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
import androidx.window.extensions.layout.WindowLayoutComponent;
@@ -61,6 +62,7 @@
*/
@RestrictTo(LIBRARY_GROUP)
int VENDOR_API_LEVEL_1 = 1;
+
// TODO(b/241323716) Removed after we have annotation to check API level
/**
* A vendor API level constant. It helps to unify the format of documenting {@code @since}
@@ -109,4 +111,15 @@
default ActivityEmbeddingComponent getActivityEmbeddingComponent() {
return null;
}
+
+ /**
+ * Returns the OEM implementation of {@link WindowAreaComponent} if it is supported on
+ * the device, {@code null} otherwise. The implementation must match the API level reported in
+ * {@link WindowExtensions}.
+ * @return the OEM implementation of {@link WindowAreaComponent}
+ */
+ @Nullable
+ default WindowAreaComponent getWindowAreaComponent() {
+ return null;
+ }
}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java
new file mode 100644
index 0000000..422e972
--- /dev/null
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/area/WindowAreaComponent.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2023 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.extensions.area;
+
+import android.app.Activity;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.window.extensions.WindowExtensions;
+import androidx.window.extensions.core.util.function.Consumer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The interface definition that will be used by the WindowManager library to get custom
+ * OEM-provided behavior around moving windows between displays or display areas on a device.
+ *
+ * Currently the only behavior supported is RearDisplay Mode, where the window
+ * is moved to the display that faces the same direction as the rear camera.
+ *
+ * <p>This interface should be implemented by OEM and deployed to the target devices.
+ * @see WindowExtensions#getWindowLayoutComponent()
+ */
+public interface WindowAreaComponent {
+
+ /**
+ * WindowArea status constant to signify that the feature is
+ * unsupported on this device. Could be due to the device not supporting that
+ * specific feature.
+ */
+ int STATUS_UNSUPPORTED = 0;
+
+ /**
+ * WindowArea status constant to signify that the feature is
+ * currently unavailable but is supported on this device. This value could signify
+ * that the current device state does not support the specific feature or another
+ * process is currently enabled in that feature.
+ */
+ int STATUS_UNAVAILABLE = 1;
+
+ /**
+ * WindowArea status constant to signify that the feature is
+ * available to be entered or enabled.
+ */
+ int STATUS_AVAILABLE = 2;
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ @IntDef({
+ STATUS_UNSUPPORTED,
+ STATUS_UNAVAILABLE,
+ STATUS_AVAILABLE
+ })
+ @interface WindowAreaStatus {}
+
+ /**
+ * Session state constant to represent there being no active session
+ * currently in progress. Used by the library to call the correct callbacks if
+ * a session is ended.
+ */
+ int SESSION_STATE_INACTIVE = 0;
+
+ /**
+ * Session state constant to represent that there is an
+ * active session currently in progress. Used by the library to
+ * know when to return the session object to the developer when the
+ * session is created and active.
+ */
+ int SESSION_STATE_ACTIVE = 1;
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ @IntDef({
+ SESSION_STATE_ACTIVE,
+ SESSION_STATE_INACTIVE
+ })
+ @interface WindowAreaSessionState {}
+
+ /**
+ * Adds a listener interested in receiving updates on the RearDisplayStatus
+ * of the device. Because this is being called from the OEM provided
+ * extensions, the library will post the result of the listener on the executor
+ * provided by the developer.
+ *
+ * The listener provided will receive values that
+ * correspond to the [WindowAreaStatus] value that aligns with the current status
+ * of the rear display.
+ * @param consumer interested in receiving updates to WindowAreaStatus.
+ */
+ void addRearDisplayStatusListener(@NonNull Consumer<@WindowAreaStatus Integer> consumer);
+
+ /**
+ * Removes a listener no longer interested in receiving updates.
+ * @param consumer no longer interested in receiving updates to WindowAreaStatus
+ */
+ void removeRearDisplayStatusListener(@NonNull Consumer<@WindowAreaStatus Integer> consumer);
+
+ /**
+ * Creates and starts a rear display session and sends state updates to the
+ * consumer provided. This consumer will receive a constant represented by
+ * [WindowAreaSessionState] to represent the state of the current rear display
+ * session. We will translate the values from the {@link Consumer} to a developer-friendly
+ * interface in the developer facing API.
+ *
+ * Because this is being called from the OEM provided extensions, the library
+ * will post the result of the listener on the executor provided by the developer.
+ *
+ * @param activity to allow that the OEM implementation will use as a base
+ * context and to identify the source display area of the request.
+ * The reference to the activity instance must not be stored in the OEM
+ * implementation to prevent memory leaks.
+ * @param consumer to provide updates to the client on the status of the session
+ * @throws UnsupportedOperationException if this method is called when RearDisplay
+ * mode is not available. This could be to an incompatible device state or when
+ * another process is currently in this mode.
+ */
+ void startRearDisplaySession(@NonNull Activity activity,
+ @NonNull Consumer<@WindowAreaSessionState Integer> consumer);
+
+ /**
+ * Ends a RearDisplaySession and sends [STATE_INACTIVE] to the consumer
+ * provided in the {@code startRearDisplaySession} method. This method is only
+ * called through the {@code RearDisplaySession} provided to the developer.
+ */
+ void endRearDisplaySession();
+}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
index 59f8a02..e4f1e81 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitAttributes.java
@@ -23,6 +23,7 @@
import static androidx.window.extensions.embedding.SplitAttributes.LayoutDirection.TOP_TO_BOTTOM;
import android.annotation.SuppressLint;
+import android.graphics.Color;
import androidx.annotation.ColorInt;
import androidx.annotation.FloatRange;
@@ -66,6 +67,19 @@
* Since {@link androidx.window.extensions.WindowExtensions#VENDOR_API_LEVEL_2}
*/
public class SplitAttributes {
+
+ /**
+ * The default value for animation background color, which means to use the current theme window
+ * background color.
+ *
+ * Only opaque color is supported, so {@code 0} is used as the default. Any other non-opaque
+ * color will be treated as the default.
+ *
+ * @see Builder#setAnimationBackgroundColor(int)
+ */
+ @ColorInt
+ public static final int DEFAULT_ANIMATION_BACKGROUND_COLOR = 0;
+
/**
* The type of window split, which defines the proportion of the parent
* window occupied by the primary and secondary activity containers.
@@ -413,6 +427,9 @@
* Gets the {@link ColorInt} to use for the background color during the
* animation of the split involving this {@code SplitAttributes} object.
*
+ * The default is {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}, which means
+ * to use the current theme window background color.
+ *
* @return The animation background {@code ColorInt}.
*/
@ColorInt
@@ -423,10 +440,9 @@
/**
* Builder for creating an instance of {@link SplitAttributes}.
*
- * The default split type is an equal split between primary and secondary
- * containers. The default layout direction is based on locale. The default
- * animation background color is 0, which specifies the theme window
- * background color.
+ * - The default split type is an equal split between primary and secondary containers.
+ * - The default layout direction is based on locale.
+ * - The default animation background color is to use the current theme window background color.
*/
public static final class Builder {
@NonNull
@@ -481,16 +497,23 @@
* animation of the split involving this {@code SplitAttributes} object
* if the animation requires a background.
*
- * The default value is 0, which specifies the theme window background
- * color.
+ * Only opaque color is supported.
+ *
+ * The default value is {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}, which
+ * means to use the current theme window background color. Any non-opaque
+ * animation color will be treated as
+ * {@link #DEFAULT_ANIMATION_BACKGROUND_COLOR}.
*
* @param color A packed color int of the form {@code AARRGGBB} for the
- * animation background color.
+ * animation background color.
* @return This {@code Builder}.
*/
@NonNull
public Builder setAnimationBackgroundColor(@ColorInt int color) {
- mAnimationBackgroundColor = color;
+ // Any non-opaque color will be treated as the default.
+ mAnimationBackgroundColor = Color.alpha(color) != 255
+ ? DEFAULT_ANIMATION_BACKGROUND_COLOR
+ : color;
return this;
}
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
index 717039b..33b8bb7 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/embedding/SplitInfo.java
@@ -24,6 +24,7 @@
/** Describes a split of two containers with activities. */
public class SplitInfo {
+
@NonNull
private final ActivityStack mPrimaryActivityStack;
@NonNull
diff --git a/window/extensions/extensions/src/main/java/androidx/window/extensions/layout/WindowLayoutComponent.java b/window/extensions/extensions/src/main/java/androidx/window/extensions/layout/WindowLayoutComponent.java
index 5573abb..9ed7d17 100644
--- a/window/extensions/extensions/src/main/java/androidx/window/extensions/layout/WindowLayoutComponent.java
+++ b/window/extensions/extensions/src/main/java/androidx/window/extensions/layout/WindowLayoutComponent.java
@@ -40,10 +40,11 @@
*/
public interface WindowLayoutComponent {
/**
- * @deprecated Use {@link #addWindowLayoutInfoListener(Context,Consumer)}
+ * @deprecated Use {@link #addWindowLayoutInfoListener(Context, Consumer)}
* starting with {@link WindowExtensions#VENDOR_API_LEVEL_2}. Only used if
* {@link #addWindowLayoutInfoListener(Context, Consumer)} can't be
* called on {@link WindowExtensions#VENDOR_API_LEVEL_1}.
+ * Since {@link WindowExtensions#VENDOR_API_LEVEL_1}
*/
@Deprecated
void addWindowLayoutInfoListener(@NonNull Activity activity,
@@ -54,6 +55,7 @@
* {@link WindowExtensions#VENDOR_API_LEVEL_2}. Only used if
* {@link #removeWindowLayoutInfoListener(Consumer)} can't be called on
* {@link WindowExtensions#VENDOR_API_LEVEL_1}.
+ * Since {@link WindowExtensions#VENDOR_API_LEVEL_1}
*/
@Deprecated
void removeWindowLayoutInfoListener(
@@ -61,7 +63,11 @@
// TODO(b/264546746): Remove addWindowLayoutInfoListener(Context, java.util.function.Consumer)
// after apps update to the latest WM Jetpack library.
- /** @deprecated Use {@link #addWindowLayoutInfoListener(Context, Consumer)} instead */
+
+ /**
+ * @deprecated Use {@link #addWindowLayoutInfoListener(Context, Consumer)} instead
+ * Since {@link WindowExtensions#VENDOR_API_LEVEL_2}
+ */
@SuppressWarnings("PairedRegistration")
// The paired method for unregistering is also removeWindowLayoutInfoListener.
@Deprecated
diff --git a/window/window-demos/demo/build.gradle b/window/window-demos/demo/build.gradle
index e579b7f..bc8df52 100644
--- a/window/window-demos/demo/build.gradle
+++ b/window/window-demos/demo/build.gradle
@@ -87,4 +87,4 @@
type = LibraryType.SAMPLES
inceptionYear = "2023"
description = "Samples for the WM Jetpack Library"
-}
\ No newline at end of file
+}
diff --git a/window/window-demos/demo/src/main/AndroidManifest.xml b/window/window-demos/demo/src/main/AndroidManifest.xml
index 36b547be..932003e 100644
--- a/window/window-demos/demo/src/main/AndroidManifest.xml
+++ b/window/window-demos/demo/src/main/AndroidManifest.xml
@@ -58,6 +58,16 @@
android:exported="false"
android:configChanges="orientation|screenSize|screenLayout|screenSize"
android:label="@string/window_metrics"/>
+ <activity android:name=".area.RearDisplayActivityConfigChanges"
+ android:exported="true"
+ android:configChanges=
+ "orientation|screenLayout|screenSize|layoutDirection|smallestScreenSize"
+ android:label="@string/rear_display">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name=".embedding.SplitActivityA"
android:exported="true"
diff --git a/window/window-demos/demo/src/main/java/androidx/window/demo/area/RearDisplayActivityConfigChanges.kt b/window/window-demos/demo/src/main/java/androidx/window/demo/area/RearDisplayActivityConfigChanges.kt
new file mode 100644
index 0000000..edb2ed1
--- /dev/null
+++ b/window/window-demos/demo/src/main/java/androidx/window/demo/area/RearDisplayActivityConfigChanges.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2023 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.demo.area
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.util.Consumer
+import androidx.window.area.WindowAreaController
+import androidx.window.area.WindowAreaSession
+import androidx.window.area.WindowAreaSessionCallback
+import androidx.window.area.WindowAreaStatus
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.demo.common.infolog.InfoLogAdapter
+import androidx.window.demo.databinding.ActivityRearDisplayBinding
+import androidx.window.java.area.WindowAreaControllerJavaAdapter
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+import java.util.concurrent.Executor
+
+/**
+ * Demo Activity that showcases listening for RearDisplay Status
+ * as well as enabling/disabling RearDisplay mode. This Activity
+ * implements [WindowAreaSessionCallback] for simplicity.
+ *
+ * This Activity overrides configuration changes for simplicity.
+ */
+@OptIn(ExperimentalWindowApi::class)
+class RearDisplayActivityConfigChanges : AppCompatActivity(), WindowAreaSessionCallback {
+
+ private lateinit var windowAreaController: WindowAreaControllerJavaAdapter
+ private var rearDisplaySession: WindowAreaSession? = null
+ private val infoLogAdapter = InfoLogAdapter()
+ private lateinit var binding: ActivityRearDisplayBinding
+ private lateinit var executor: Executor
+
+ private val rearDisplayStatusListener = Consumer<WindowAreaStatus> { status ->
+ infoLogAdapter.append(getCurrentTimeString(), status.toString())
+ infoLogAdapter.notifyDataSetChanged()
+ updateRearDisplayButton(status)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityRearDisplayBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ executor = ContextCompat.getMainExecutor(this)
+ windowAreaController = WindowAreaControllerJavaAdapter(WindowAreaController.getOrCreate())
+
+ binding.rearStatusRecyclerView.adapter = infoLogAdapter
+
+ binding.rearDisplayButton.setOnClickListener {
+ if (rearDisplaySession != null) {
+ rearDisplaySession?.close()
+ } else {
+ windowAreaController.startRearDisplayModeSession(
+ this,
+ executor,
+ this)
+ }
+ }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ windowAreaController.addRearDisplayStatusListener(
+ executor,
+ rearDisplayStatusListener
+ )
+ }
+
+ override fun onStop() {
+ super.onStop()
+ windowAreaController.removeRearDisplayStatusListener(rearDisplayStatusListener)
+ }
+
+ override fun onSessionStarted(session: WindowAreaSession) {
+ rearDisplaySession = session
+ infoLogAdapter.append(getCurrentTimeString(), "RearDisplay Session has been started")
+ infoLogAdapter.notifyDataSetChanged()
+ }
+
+ override fun onSessionEnded() {
+ rearDisplaySession = null
+ infoLogAdapter.append(getCurrentTimeString(), "RearDisplay Session has ended")
+ infoLogAdapter.notifyDataSetChanged()
+ }
+
+ private fun updateRearDisplayButton(status: WindowAreaStatus) {
+ if (rearDisplaySession != null) {
+ binding.rearDisplayButton.isEnabled = true
+ binding.rearDisplayButton.text = "Disable RearDisplay Mode"
+ return
+ }
+ when (status) {
+ WindowAreaStatus.UNSUPPORTED -> {
+ binding.rearDisplayButton.isEnabled = false
+ binding.rearDisplayButton.text = "RearDisplay is not supported on this device"
+ }
+ WindowAreaStatus.UNAVAILABLE -> {
+ binding.rearDisplayButton.isEnabled = false
+ binding.rearDisplayButton.text = "RearDisplay is not currently available"
+ }
+ WindowAreaStatus.AVAILABLE -> {
+ binding.rearDisplayButton.isEnabled = true
+ binding.rearDisplayButton.text = "Enable RearDisplay Mode"
+ }
+ }
+ }
+
+ private fun getCurrentTimeString(): String {
+ val sdf = SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault())
+ val currentDate = sdf.format(Date())
+ return currentDate.toString()
+ }
+
+ private companion object {
+ private val TAG = RearDisplayActivityConfigChanges::class.java.simpleName
+ }
+}
\ No newline at end of file
diff --git a/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/DemoActivityEmbeddingController.kt b/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/DemoActivityEmbeddingController.kt
index 0d3771e..69542ac 100644
--- a/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/DemoActivityEmbeddingController.kt
+++ b/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/DemoActivityEmbeddingController.kt
@@ -16,8 +16,8 @@
package androidx.window.demo.embedding
-import androidx.annotation.ColorInt
import androidx.annotation.GuardedBy
+import androidx.window.embedding.SplitAttributes
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
@@ -27,16 +27,14 @@
private val lock = Object()
@GuardedBy("lock")
- @ColorInt
- private var _animationBackgroundColor = 0
+ private var _animationBackgroundColor = SplitAttributes.BackgroundColor.DEFAULT
/** Animation background color to use when the animation requires a background. */
- var animationBackgroundColor: Int
- @ColorInt
+ var animationBackgroundColor: SplitAttributes.BackgroundColor
get() = synchronized(lock) {
_animationBackgroundColor
}
- set(@ColorInt value) = synchronized(lock) {
+ set(value) = synchronized(lock) {
_animationBackgroundColor = value
}
diff --git a/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/SplitDeviceStateActivityBase.kt b/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/SplitDeviceStateActivityBase.kt
index 5f686b2..56850b4 100644
--- a/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/SplitDeviceStateActivityBase.kt
+++ b/window/window-demos/demo/src/main/java/androidx/window/demo/embedding/SplitDeviceStateActivityBase.kt
@@ -410,12 +410,12 @@
const val SUFFIX_REVERSED = "_reversed"
const val SUFFIX_AND_HORIZONTAL_LAYOUT_IN_TABLETOP = "_and_horizontal_layout_in_tabletop"
const val SUFFIX_AND_FULLSCREEN_IN_BOOK_MODE = "_and_fullscreen_in_book_mode"
- val ANIMATION_BACKGROUND_COLORS_TEXT = arrayOf("BLACK", "BLUE", "GREEN", "YELLOW")
+ val ANIMATION_BACKGROUND_COLORS_TEXT = arrayOf("DEFAULT", "BLUE", "GREEN", "YELLOW")
val ANIMATION_BACKGROUND_COLORS_VALUE = arrayOf(
- Color.BLACK,
- Color.BLUE,
- Color.GREEN,
- Color.YELLOW
+ SplitAttributes.BackgroundColor.DEFAULT,
+ SplitAttributes.BackgroundColor.color(Color.BLUE),
+ SplitAttributes.BackgroundColor.color(Color.GREEN),
+ SplitAttributes.BackgroundColor.color(Color.YELLOW)
)
/**
diff --git a/window/window-java/api/public_plus_experimental_current.txt b/window/window-java/api/public_plus_experimental_current.txt
index 39c35ac..ded945be 100644
--- a/window/window-java/api/public_plus_experimental_current.txt
+++ b/window/window-java/api/public_plus_experimental_current.txt
@@ -1,4 +1,15 @@
// Signature format: 4.0
+package androidx.window.java.area {
+
+ @androidx.window.core.ExperimentalWindowApi public final class WindowAreaControllerJavaAdapter implements androidx.window.area.WindowAreaController {
+ ctor public WindowAreaControllerJavaAdapter(androidx.window.area.WindowAreaController controller);
+ method public void addRearDisplayStatusListener(java.util.concurrent.Executor executor, androidx.core.util.Consumer<androidx.window.area.WindowAreaStatus> consumer);
+ method public void removeRearDisplayStatusListener(androidx.core.util.Consumer<androidx.window.area.WindowAreaStatus> consumer);
+ method public void startRearDisplayModeSession(android.app.Activity activity, java.util.concurrent.Executor executor, androidx.window.area.WindowAreaSessionCallback windowAreaSessionCallback);
+ }
+
+}
+
package androidx.window.java.layout {
public final class WindowInfoTrackerCallbackAdapter implements androidx.window.layout.WindowInfoTracker {
diff --git a/window/window-java/src/androidTest/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapterTest.kt b/window/window-java/src/androidTest/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapterTest.kt
index 74b3d87..bd6ae04 100644
--- a/window/window-java/src/androidTest/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapterTest.kt
+++ b/window/window-java/src/androidTest/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapterTest.kt
@@ -18,6 +18,7 @@
import android.app.Activity
import android.content.Context
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.java.TestConsumer
import androidx.window.layout.FoldingFeature
import androidx.window.layout.WindowInfoTracker
@@ -35,6 +36,7 @@
* from the kotlin coroutine API to listeners and callbacks.
* @see WindowInfoTracker
*/
+@OptIn(ExperimentalWindowApi::class)
public class WindowInfoTrackerCallbackAdapterTest {
@Test
diff --git a/window/window-java/src/main/java/androidx/window/java/area/WindowAreaControllerJavaAdapter.kt b/window/window-java/src/main/java/androidx/window/java/area/WindowAreaControllerJavaAdapter.kt
new file mode 100644
index 0000000..692d565
--- /dev/null
+++ b/window/window-java/src/main/java/androidx/window/java/area/WindowAreaControllerJavaAdapter.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2023 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.java.area
+
+import android.app.Activity
+import androidx.core.util.Consumer
+import androidx.window.area.WindowAreaSessionCallback
+import androidx.window.area.WindowAreaStatus
+import androidx.window.area.WindowAreaController
+import androidx.window.core.ExperimentalWindowApi
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import java.util.concurrent.Executor
+import java.util.concurrent.locks.ReentrantLock
+import kotlin.concurrent.withLock
+
+/**
+ * An adapted interface for [WindowAreaController] that provides the information and
+ * functionality around RearDisplay Mode via a callback shaped API.
+ */
+@ExperimentalWindowApi
+class WindowAreaControllerJavaAdapter(
+ private val controller: WindowAreaController
+) : WindowAreaController by controller {
+
+ /**
+ * A [ReentrantLock] to protect against concurrent access to [consumerToJobMap].
+ */
+ private val lock = ReentrantLock()
+ private val consumerToJobMap = mutableMapOf<Consumer<*>, Job>()
+
+ /**
+ * Registers a listener to consume [WindowAreaStatus] values defined as
+ * [WindowAreaStatus.UNSUPPORTED], [WindowAreaStatus.UNAVAILABLE], and
+ * [WindowAreaStatus.AVAILABLE]. The values provided through this listener should be used
+ * to determine if you are able to enable rear display Mode at that time. You can use these
+ * values to modify your UI to show/hide controls and determine when to enable features
+ * that use rear display Mode. You should only try and enter rear display mode when your
+ * [consumer] is provided a value of [WindowAreaStatus.AVAILABLE].
+ *
+ * The [consumer] will be provided an initial value on registration, as well as any change
+ * to the status as they occur. This could happen due to hardware device state changes, or if
+ * another process has enabled RearDisplay Mode.
+ *
+ * @see WindowAreaController.rearDisplayStatus
+ */
+ fun addRearDisplayStatusListener(
+ executor: Executor,
+ consumer: Consumer<WindowAreaStatus>
+ ) {
+ val statusFlow = controller.rearDisplayStatus()
+ lock.withLock {
+ if (consumerToJobMap[consumer] == null) {
+ val scope = CoroutineScope(executor.asCoroutineDispatcher())
+ consumerToJobMap[consumer] = scope.launch {
+ statusFlow.collect { consumer.accept(it) }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes a listener of [WindowAreaStatus] values
+ * @see WindowAreaController.rearDisplayStatus
+ */
+ fun removeRearDisplayStatusListener(consumer: Consumer<WindowAreaStatus>) {
+ lock.withLock {
+ consumerToJobMap[consumer]?.cancel()
+ consumerToJobMap.remove(consumer)
+ }
+ }
+
+ /**
+ * Starts a RearDisplay Mode session and provides updates through the
+ * [WindowAreaSessionCallback] provided. Due to the nature of moving your Activity to a
+ * different display, your Activity will likely go through a configuration change. Because of
+ * this, if your Activity does not override configuration changes, this method should be called
+ * from a component that outlives the Activity lifecycle such as a
+ * [androidx.lifecycle.ViewModel]. If your Activity does override
+ * configuration changes, it is safe to call this method inside your Activity.
+ *
+ * This method should only be called if you have received a [WindowAreaStatus.AVAILABLE]
+ * value from the listener provided through the [addRearDisplayStatusListener] method. If
+ * you try and enable RearDisplay mode without it being available, you will receive an
+ * [UnsupportedOperationException].
+ *
+ * The [windowAreaSessionCallback] provided will receive a call to
+ * [WindowAreaSessionCallback.onSessionStarted] after your Activity has been moved to the
+ * display corresponding to this mode. RearDisplay mode will stay active until the session
+ * provided through [WindowAreaSessionCallback.onSessionStarted] is closed, or there is a device
+ * state change that makes RearDisplay mode incompatible such as if the device is closed so the
+ * outer-display is no longer in line with the rear camera. When this occurs,
+ * [WindowAreaSessionCallback.onSessionEnded] is called to notify you the session has been
+ * ended.
+ *
+ * @see addRearDisplayStatusListener
+ * @throws UnsupportedOperationException if you try and start a RearDisplay session when
+ * your [WindowAreaController.rearDisplayStatus] does not return a value of
+ * [WindowAreaStatus.AVAILABLE]
+ */
+ fun startRearDisplayModeSession(
+ activity: Activity,
+ executor: Executor,
+ windowAreaSessionCallback: WindowAreaSessionCallback
+ ) {
+ controller.rearDisplayMode(activity, executor, windowAreaSessionCallback)
+ }
+}
\ No newline at end of file
diff --git a/window/window-java/src/main/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.kt b/window/window-java/src/main/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.kt
index 5966d28..35b10d3 100644
--- a/window/window-java/src/main/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.kt
+++ b/window/window-java/src/main/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.kt
@@ -21,6 +21,7 @@
import androidx.annotation.UiContext
import androidx.core.util.Consumer
import android.inputmethodservice.InputMethodService
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.WindowInfoTracker
import androidx.window.layout.WindowLayoutInfo
import kotlinx.coroutines.CoroutineScope
@@ -72,6 +73,7 @@
* @param consumer for [WindowLayoutInfo] values.
* @see WindowInfoTracker.windowLayoutInfo
*/
+ @OptIn(ExperimentalWindowApi::class)
fun addWindowLayoutInfoListener(
@UiContext context: Context,
executor: Executor,
diff --git a/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/layout/WindowInfoTrackerRxTest.kt b/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/layout/WindowInfoTrackerRxTest.kt
index 418725d..038ad11 100644
--- a/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/layout/WindowInfoTrackerRxTest.kt
+++ b/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/layout/WindowInfoTrackerRxTest.kt
@@ -18,6 +18,7 @@
import android.app.Activity
import android.content.Context
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.FoldingFeature
import androidx.window.layout.WindowInfoTracker
import androidx.window.layout.WindowLayoutInfo
@@ -29,6 +30,7 @@
/**
* Tests for the RxJava 2 adapters.
*/
+@OptIn(ExperimentalWindowApi::class)
class WindowInfoTrackerRxTest {
@Test
diff --git a/window/window-rxjava2/src/main/java/androidx/window/rxjava2/layout/WindowInfoTrackerRx.kt b/window/window-rxjava2/src/main/java/androidx/window/rxjava2/layout/WindowInfoTrackerRx.kt
index d41cc80..1833993 100644
--- a/window/window-rxjava2/src/main/java/androidx/window/rxjava2/layout/WindowInfoTrackerRx.kt
+++ b/window/window-rxjava2/src/main/java/androidx/window/rxjava2/layout/WindowInfoTrackerRx.kt
@@ -20,6 +20,7 @@
import android.app.Activity
import android.content.Context
import androidx.annotation.UiContext
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.WindowInfoTracker
import androidx.window.layout.WindowLayoutInfo
import io.reactivex.Flowable
@@ -51,6 +52,7 @@
* Return an [Observable] stream of [WindowLayoutInfo].
* @see WindowInfoTracker.windowLayoutInfo
*/
+@OptIn(ExperimentalWindowApi::class)
fun WindowInfoTracker.windowLayoutInfoObservable(
@UiContext context: Context
): Observable<WindowLayoutInfo> {
@@ -61,6 +63,7 @@
* Return a [Flowable] stream of [WindowLayoutInfo].
* @see WindowInfoTracker.windowLayoutInfo
*/
+@OptIn(ExperimentalWindowApi::class)
fun WindowInfoTracker.windowLayoutInfoFlowable(
@UiContext context: Context
): Flowable<WindowLayoutInfo> {
diff --git a/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/layout/WindowInfoTrackerRxTest.kt b/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/layout/WindowInfoTrackerRxTest.kt
index f4a4c4c..8630cc6 100644
--- a/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/layout/WindowInfoTrackerRxTest.kt
+++ b/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/layout/WindowInfoTrackerRxTest.kt
@@ -18,6 +18,7 @@
import android.app.Activity
import android.content.Context
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.FoldingFeature
import androidx.window.layout.WindowInfoTracker
import androidx.window.layout.WindowLayoutInfo
@@ -31,6 +32,7 @@
* [io.reactivex.rxjava3.core.Flowable] and ensure that data is forwarded appropriately.
* @see WindowInfoTracker
*/
+@OptIn(ExperimentalWindowApi::class)
class WindowInfoTrackerRxTest {
@Test
diff --git a/window/window-rxjava3/src/main/java/androidx/window/rxjava3/layout/WindowInfoTrackerRx.kt b/window/window-rxjava3/src/main/java/androidx/window/rxjava3/layout/WindowInfoTrackerRx.kt
index 084292b..d41a416 100644
--- a/window/window-rxjava3/src/main/java/androidx/window/rxjava3/layout/WindowInfoTrackerRx.kt
+++ b/window/window-rxjava3/src/main/java/androidx/window/rxjava3/layout/WindowInfoTrackerRx.kt
@@ -20,6 +20,7 @@
import android.app.Activity
import android.content.Context
import androidx.annotation.UiContext
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.WindowInfoTracker
import androidx.window.layout.WindowLayoutInfo
import io.reactivex.rxjava3.core.Flowable
@@ -51,6 +52,7 @@
* Return an [Observable] stream of [WindowLayoutInfo].
* @see WindowInfoTracker.windowLayoutInfo
*/
+@OptIn(ExperimentalWindowApi::class)
fun WindowInfoTracker.windowLayoutInfoObservable(
@UiContext context: Context
): Observable<WindowLayoutInfo> {
@@ -61,6 +63,7 @@
* Return a [Flowable] stream of [WindowLayoutInfo].
* @see WindowInfoTracker.windowLayoutInfo
*/
+@OptIn(ExperimentalWindowApi::class)
fun WindowInfoTracker.windowLayoutInfoFlowable(
@UiContext context: Context
): Flowable<WindowLayoutInfo> {
diff --git a/window/window/api/current.txt b/window/window/api/current.txt
index 2a716a3..356f9c3 100644
--- a/window/window/api/current.txt
+++ b/window/window/api/current.txt
@@ -84,19 +84,29 @@
}
public final class SplitAttributes {
- method public int getAnimationBackgroundColor();
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor getAnimationBackgroundColor();
method public androidx.window.embedding.SplitAttributes.LayoutDirection getLayoutDirection();
method public androidx.window.embedding.SplitAttributes.SplitType getSplitType();
- property public final int animationBackgroundColor;
+ property public final androidx.window.embedding.SplitAttributes.BackgroundColor animationBackgroundColor;
property public final androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection;
property public final androidx.window.embedding.SplitAttributes.SplitType splitType;
field public static final androidx.window.embedding.SplitAttributes.Companion Companion;
}
+ public static final class SplitAttributes.BackgroundColor {
+ method public static androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor.Companion Companion;
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor DEFAULT;
+ }
+
+ public static final class SplitAttributes.BackgroundColor.Companion {
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ }
+
public static final class SplitAttributes.Builder {
ctor public SplitAttributes.Builder();
method public androidx.window.embedding.SplitAttributes build();
- method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(@ColorInt int color);
+ method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(androidx.window.embedding.SplitAttributes.BackgroundColor color);
method public androidx.window.embedding.SplitAttributes.Builder setLayoutDirection(androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection);
method public androidx.window.embedding.SplitAttributes.Builder setSplitType(androidx.window.embedding.SplitAttributes.SplitType type);
}
@@ -326,7 +336,6 @@
public interface WindowInfoTracker {
method public default static androidx.window.layout.WindowInfoTracker getOrCreate(android.content.Context context);
- method public default kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(@UiContext android.content.Context context);
method public kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(android.app.Activity activity);
field public static final androidx.window.layout.WindowInfoTracker.Companion Companion;
}
diff --git a/window/window/api/public_plus_experimental_current.txt b/window/window/api/public_plus_experimental_current.txt
index 986a2d0..ffb1d62 100644
--- a/window/window/api/public_plus_experimental_current.txt
+++ b/window/window/api/public_plus_experimental_current.txt
@@ -9,6 +9,40 @@
}
+package androidx.window.area {
+
+ @androidx.window.core.ExperimentalWindowApi public interface WindowAreaController {
+ method public default static androidx.window.area.WindowAreaController getOrCreate();
+ method public void rearDisplayMode(android.app.Activity activity, java.util.concurrent.Executor executor, androidx.window.area.WindowAreaSessionCallback windowAreaSessionCallback);
+ method public kotlinx.coroutines.flow.Flow<androidx.window.area.WindowAreaStatus> rearDisplayStatus();
+ field public static final androidx.window.area.WindowAreaController.Companion Companion;
+ }
+
+ public static final class WindowAreaController.Companion {
+ method public androidx.window.area.WindowAreaController getOrCreate();
+ }
+
+ @androidx.window.core.ExperimentalWindowApi public interface WindowAreaSession {
+ method public void close();
+ }
+
+ @androidx.window.core.ExperimentalWindowApi public interface WindowAreaSessionCallback {
+ method public void onSessionEnded();
+ method public void onSessionStarted(androidx.window.area.WindowAreaSession session);
+ }
+
+ @androidx.window.core.ExperimentalWindowApi public final class WindowAreaStatus {
+ field public static final androidx.window.area.WindowAreaStatus AVAILABLE;
+ field public static final androidx.window.area.WindowAreaStatus.Companion Companion;
+ field public static final androidx.window.area.WindowAreaStatus UNAVAILABLE;
+ field public static final androidx.window.area.WindowAreaStatus UNSUPPORTED;
+ }
+
+ public static final class WindowAreaStatus.Companion {
+ }
+
+}
+
package androidx.window.core {
@kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWindowApi {
@@ -91,19 +125,29 @@
}
public final class SplitAttributes {
- method public int getAnimationBackgroundColor();
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor getAnimationBackgroundColor();
method public androidx.window.embedding.SplitAttributes.LayoutDirection getLayoutDirection();
method public androidx.window.embedding.SplitAttributes.SplitType getSplitType();
- property public final int animationBackgroundColor;
+ property public final androidx.window.embedding.SplitAttributes.BackgroundColor animationBackgroundColor;
property public final androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection;
property public final androidx.window.embedding.SplitAttributes.SplitType splitType;
field public static final androidx.window.embedding.SplitAttributes.Companion Companion;
}
+ public static final class SplitAttributes.BackgroundColor {
+ method public static androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor.Companion Companion;
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor DEFAULT;
+ }
+
+ public static final class SplitAttributes.BackgroundColor.Companion {
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ }
+
public static final class SplitAttributes.Builder {
ctor public SplitAttributes.Builder();
method public androidx.window.embedding.SplitAttributes build();
- method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(@ColorInt int color);
+ method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(androidx.window.embedding.SplitAttributes.BackgroundColor color);
method public androidx.window.embedding.SplitAttributes.Builder setLayoutDirection(androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection);
method public androidx.window.embedding.SplitAttributes.Builder setSplitType(androidx.window.embedding.SplitAttributes.SplitType type);
}
@@ -336,7 +380,7 @@
public interface WindowInfoTracker {
method public default static androidx.window.layout.WindowInfoTracker getOrCreate(android.content.Context context);
- method public default kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(@UiContext android.content.Context context);
+ method @androidx.window.core.ExperimentalWindowApi public default kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(@UiContext android.content.Context context);
method public kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(android.app.Activity activity);
field public static final androidx.window.layout.WindowInfoTracker.Companion Companion;
}
diff --git a/window/window/api/restricted_current.txt b/window/window/api/restricted_current.txt
index 2a716a3..356f9c3 100644
--- a/window/window/api/restricted_current.txt
+++ b/window/window/api/restricted_current.txt
@@ -84,19 +84,29 @@
}
public final class SplitAttributes {
- method public int getAnimationBackgroundColor();
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor getAnimationBackgroundColor();
method public androidx.window.embedding.SplitAttributes.LayoutDirection getLayoutDirection();
method public androidx.window.embedding.SplitAttributes.SplitType getSplitType();
- property public final int animationBackgroundColor;
+ property public final androidx.window.embedding.SplitAttributes.BackgroundColor animationBackgroundColor;
property public final androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection;
property public final androidx.window.embedding.SplitAttributes.SplitType splitType;
field public static final androidx.window.embedding.SplitAttributes.Companion Companion;
}
+ public static final class SplitAttributes.BackgroundColor {
+ method public static androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor.Companion Companion;
+ field public static final androidx.window.embedding.SplitAttributes.BackgroundColor DEFAULT;
+ }
+
+ public static final class SplitAttributes.BackgroundColor.Companion {
+ method public androidx.window.embedding.SplitAttributes.BackgroundColor color(@ColorInt @IntRange(from=android.graphics.Color.BLACK.toLong(), to=android.graphics.Color.WHITE.toLong()) int color);
+ }
+
public static final class SplitAttributes.Builder {
ctor public SplitAttributes.Builder();
method public androidx.window.embedding.SplitAttributes build();
- method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(@ColorInt int color);
+ method public androidx.window.embedding.SplitAttributes.Builder setAnimationBackgroundColor(androidx.window.embedding.SplitAttributes.BackgroundColor color);
method public androidx.window.embedding.SplitAttributes.Builder setLayoutDirection(androidx.window.embedding.SplitAttributes.LayoutDirection layoutDirection);
method public androidx.window.embedding.SplitAttributes.Builder setSplitType(androidx.window.embedding.SplitAttributes.SplitType type);
}
@@ -326,7 +336,6 @@
public interface WindowInfoTracker {
method public default static androidx.window.layout.WindowInfoTracker getOrCreate(android.content.Context context);
- method public default kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(@UiContext android.content.Context context);
method public kotlinx.coroutines.flow.Flow<androidx.window.layout.WindowLayoutInfo> windowLayoutInfo(android.app.Activity activity);
field public static final androidx.window.layout.WindowInfoTracker.Companion Companion;
}
diff --git a/window/window/samples/src/main/java/androidx.window.samples.embedding/SplitAttributesCalculatorSamples.kt b/window/window/samples/src/main/java/androidx.window.samples.embedding/SplitAttributesCalculatorSamples.kt
index 8eebd5c..2cba736 100644
--- a/window/window/samples/src/main/java/androidx.window.samples.embedding/SplitAttributesCalculatorSamples.kt
+++ b/window/window/samples/src/main/java/androidx.window.samples.embedding/SplitAttributesCalculatorSamples.kt
@@ -59,7 +59,7 @@
}
)
// Set the color to use when switching between vertical and horizontal
- .setAnimationBackgroundColor(Color.GRAY)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GRAY))
.build()
}
return@setSplitAttributesCalculator if (
@@ -69,7 +69,7 @@
SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.splitEqually())
.setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
- .setAnimationBackgroundColor(Color.GRAY)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GRAY))
.build()
} else {
// Expand containers if the device is in portrait or the width is less than 600 dp.
@@ -93,13 +93,13 @@
builder
.setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
// Set the color to use when switching between vertical and horizontal
- .setAnimationBackgroundColor(Color.GRAY)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GRAY))
.build()
} else if (parentConfiguration.screenHeightDp >= 600) {
builder
.setLayoutDirection(SplitAttributes.LayoutDirection.TOP_TO_BOTTOM)
// Set the color to use when switching between vertical and horizontal
- .setAnimationBackgroundColor(Color.GRAY)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GRAY))
.build()
} else {
// Fallback to expand the secondary container
diff --git a/window/window/src/androidTest/java/androidx/window/area/WindowAreaControllerImplTest.kt b/window/window/src/androidTest/java/androidx/window/area/WindowAreaControllerImplTest.kt
new file mode 100644
index 0000000..3b10142
--- /dev/null
+++ b/window/window/src/androidTest/java/androidx/window/area/WindowAreaControllerImplTest.kt
@@ -0,0 +1,215 @@
+/*
+ * 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.area
+
+import android.annotation.TargetApi
+import android.app.Activity
+import android.content.pm.ActivityInfo
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.window.TestActivity
+import androidx.window.TestConsumer
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.extensions.area.WindowAreaComponent
+import androidx.window.extensions.core.util.function.Consumer
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+import kotlin.test.assertFailsWith
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+
+@OptIn(ExperimentalCoroutinesApi::class, ExperimentalWindowApi::class)
+class WindowAreaControllerImplTest {
+
+ @get:Rule
+ public val activityScenario: ActivityScenarioRule<TestActivity> =
+ ActivityScenarioRule(TestActivity::class.java)
+
+ private val testScope = TestScope(UnconfinedTestDispatcher())
+
+ @TargetApi(Build.VERSION_CODES.N)
+ @Test
+ public fun testRearDisplayStatus(): Unit = testScope.runTest {
+ assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
+ activityScenario.scenario.onActivity {
+ val extensionComponent = FakeWindowAreaComponent()
+ val repo = WindowAreaControllerImpl(extensionComponent)
+ val collector = TestConsumer<WindowAreaStatus>()
+ extensionComponent
+ .updateStatusListeners(WindowAreaComponent.STATUS_UNAVAILABLE)
+ testScope.launch(Job()) {
+ repo.rearDisplayStatus().collect(collector::accept)
+ }
+ collector.assertValue(WindowAreaStatus.UNAVAILABLE)
+ extensionComponent
+ .updateStatusListeners(WindowAreaComponent.STATUS_AVAILABLE)
+ collector.assertValues(
+ WindowAreaStatus.UNAVAILABLE,
+ WindowAreaStatus.AVAILABLE
+ )
+ }
+ }
+
+ @Test
+ public fun testRearDisplayStatusNullComponent(): Unit = testScope.runTest {
+ activityScenario.scenario.onActivity {
+ val repo = EmptyWindowAreaControllerImpl()
+ val collector = TestConsumer<WindowAreaStatus>()
+ testScope.launch(Job()) {
+ repo.rearDisplayStatus().collect(collector::accept)
+ }
+ collector.assertValue(WindowAreaStatus.UNSUPPORTED)
+ }
+ }
+
+ /**
+ * Tests the rear display mode flow works as expected. Tests the flow
+ * through WindowAreaControllerImpl with a fake extension. This fake extension
+ * changes the orientation of the activity to landscape when rear display mode is enabled
+ * and then returns it back to portrait when it's disabled.
+ */
+ @TargetApi(Build.VERSION_CODES.N)
+ @Test
+ public fun testRearDisplayMode(): Unit = testScope.runTest {
+ assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
+ val extensions = FakeWindowAreaComponent()
+ val repo = WindowAreaControllerImpl(extensions)
+ extensions.currentStatus = WindowAreaComponent.STATUS_AVAILABLE
+ val callback = TestWindowAreaSessionCallback()
+ activityScenario.scenario.onActivity { testActivity ->
+ testActivity.resetLayoutCounter()
+ testActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ testActivity.waitForLayout()
+ }
+
+ activityScenario.scenario.onActivity { testActivity ->
+ assert(testActivity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
+ testActivity.resetLayoutCounter()
+ repo.rearDisplayMode(testActivity, Runnable::run, callback)
+ }
+
+ activityScenario.scenario.onActivity { testActivity ->
+ assert(testActivity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
+ assert(callback.currentSession != null)
+ testActivity.resetLayoutCounter()
+ callback.endSession()
+ }
+ activityScenario.scenario.onActivity { testActivity ->
+ assert(testActivity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
+ assert(callback.currentSession == null)
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.N)
+ @Test
+ public fun testRearDisplayModeReturnsError(): Unit = testScope.runTest {
+ assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
+ val extensionComponent = FakeWindowAreaComponent()
+ extensionComponent.currentStatus = WindowAreaComponent.STATUS_UNAVAILABLE
+ val repo = WindowAreaControllerImpl(extensionComponent)
+ val callback = TestWindowAreaSessionCallback()
+ activityScenario.scenario.onActivity { testActivity ->
+ assertFailsWith(
+ exceptionClass = UnsupportedOperationException::class,
+ block = { repo.rearDisplayMode(testActivity, Runnable::run, callback) }
+ )
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.N)
+ @Test
+ public fun testRearDisplayModeNullComponent(): Unit = testScope.runTest {
+ assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
+ val repo = EmptyWindowAreaControllerImpl()
+ val callback = TestWindowAreaSessionCallback()
+ activityScenario.scenario.onActivity { testActivity ->
+ assertFailsWith(
+ exceptionClass = UnsupportedOperationException::class,
+ block = { repo.rearDisplayMode(testActivity, Runnable::run, callback) }
+ )
+ }
+ }
+
+ private class FakeWindowAreaComponent : WindowAreaComponent {
+ val statusListeners = mutableListOf<Consumer<Int>>()
+ var currentStatus = WindowAreaComponent.STATUS_UNSUPPORTED
+ var testActivity: Activity? = null
+ var sessionConsumer: Consumer<Int>? = null
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ override fun addRearDisplayStatusListener(consumer: Consumer<Int>) {
+ statusListeners.add(consumer)
+ consumer.accept(currentStatus)
+ }
+
+ override fun removeRearDisplayStatusListener(consumer: Consumer<Int>) {
+ statusListeners.remove(consumer)
+ }
+
+ // Fake WindowAreaComponent will change the orientation of the activity to signal
+ // entering rear display mode, as well as ending the session
+ @RequiresApi(Build.VERSION_CODES.N)
+ override fun startRearDisplaySession(
+ activity: Activity,
+ rearDisplaySessionConsumer: Consumer<Int>
+ ) {
+ if (currentStatus != WindowAreaComponent.STATUS_AVAILABLE) {
+ throw UnsupportedOperationException("Rear Display mode cannot be enabled currently")
+ }
+ testActivity = activity
+ sessionConsumer = rearDisplaySessionConsumer
+ testActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ rearDisplaySessionConsumer.accept(WindowAreaComponent.SESSION_STATE_ACTIVE)
+ }
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ override fun endRearDisplaySession() {
+ testActivity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ sessionConsumer?.accept(WindowAreaComponent.SESSION_STATE_INACTIVE)
+ }
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ fun updateStatusListeners(newStatus: Int) {
+ currentStatus = newStatus
+ for (consumer in statusListeners) {
+ consumer.accept(currentStatus)
+ }
+ }
+ }
+
+ private class TestWindowAreaSessionCallback : WindowAreaSessionCallback {
+
+ var currentSession: WindowAreaSession? = null
+ var error: Throwable? = null
+
+ override fun onSessionStarted(session: WindowAreaSession) {
+ currentSession = session
+ }
+
+ override fun onSessionEnded() {
+ currentSession = null
+ }
+
+ fun endSession() = currentSession?.close()
+ }
+}
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/ActivityFilterTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/ActivityFilterTest.kt
index 1d9d74c..44e9c5b 100644
--- a/window/window/src/androidTest/java/androidx/window/embedding/ActivityFilterTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/ActivityFilterTest.kt
@@ -52,16 +52,20 @@
}
@Test
- fun testMatchActivity_MatchIntentWithoutAction() {
+ fun testMatch_WithoutAction() {
val filter = ActivityFilter(COMPONENT_1, null /* intentAction */)
assertWithMessage("#matchActivity must be true because intent.component matches")
.that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage("#matchIntent must be true because intent.component matches")
+ .that(filter.matchesIntent(intent)).isTrue()
intent.component = COMPONENT_2
assertWithMessage("#matchActivity must be false because component mismatches")
.that(filter.matchesActivity(activity)).isFalse()
+ assertWithMessage("#matchesIntent must be false because component mismatches")
+ .that(filter.matchesIntent(intent)).isFalse()
doReturn(COMPONENT_1).whenever(activity).componentName
@@ -70,29 +74,37 @@
}
@Test
- fun testMatchActivity_MatchIntentWithAction() {
+ fun testMatch_WithAction() {
val filter = ActivityFilter(COMPONENT_1, ACTION)
assertWithMessage("#matchActivity must be false because intent has no action")
.that(filter.matchesActivity(activity)).isFalse()
+ assertWithMessage("#matchesIntent must be false because intent has no action")
+ .that(filter.matchesIntent(intent)).isFalse()
intent.action = ACTION
assertWithMessage("#matchActivity must be true because intent matches")
.that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage("#matchesIntent must be true because intent matches")
+ .that(filter.matchesIntent(intent)).isTrue()
}
@Test
- fun testMatchActivity_MatchWildcardWithAction() {
+ fun testMatch_WildcardWithAction() {
val filter = ActivityFilter(WILDCARD, ACTION)
assertWithMessage("#matchActivity must be false because intent has no action")
.that(filter.matchesActivity(activity)).isFalse()
+ assertWithMessage("#matchesIntent must be false because intent has no action")
+ .that(filter.matchesIntent(intent)).isFalse()
intent.action = ACTION
assertWithMessage("#matchActivity must be true because intent.action matches")
.that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage("#matchesIntent must be true because intent.action matches")
+ .that(filter.matchesIntent(intent)).isTrue()
intent.component = null
@@ -101,10 +113,15 @@
"of null component"
)
.that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage(
+ "#matchesIntent must be true because intent.action matches regardless " +
+ "of null component"
+ )
+ .that(filter.matchesIntent(intent)).isTrue()
}
@Test
- fun testMatchActivity_MatchIntentWithPackage() {
+ fun testMatch_IntentWithPackage() {
val filter = ActivityFilter(WILDCARD, null /* intentAction */)
intent.component = null
@@ -112,6 +129,20 @@
assertWithMessage("#matchActivity must be true because intent.package matches")
.that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage("#matchesIntent must be true because intent.package matches")
+ .that(filter.matchesIntent(intent)).isTrue()
+ }
+
+ @Test
+ fun testMatch_EmptyIntentWithWildcard() {
+ val filter = ActivityFilter(WILDCARD, null /* intentAction */)
+
+ intent.component = null
+
+ assertWithMessage("#matchActivity must be true because rule is wildcard to match all")
+ .that(filter.matchesActivity(activity)).isTrue()
+ assertWithMessage("#matchesIntent must be true because rule is wildcard to match all")
+ .that(filter.matchesIntent(intent)).isTrue()
}
companion object {
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
index f098cd6..0ce0920 100644
--- a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingAdapterTest.kt
@@ -59,7 +59,7 @@
SplitAttributes.Builder()
.setSplitType(SplitType.splitEqually())
.setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
)
assertEquals(listOf(expectedSplitInfo), adapter.translate(listOf(oemSplitInfo)))
@@ -134,7 +134,7 @@
SplitAttributes.Builder()
.setSplitType(SplitType.splitByHinge(SplitType.ratio(0.3f)))
.setLayoutDirection(SplitAttributes.LayoutDirection.TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(Color.YELLOW)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.YELLOW))
.build()
)
assertEquals(listOf(expectedSplitInfo), adapter.translate(listOf(oemSplitInfo)))
@@ -143,7 +143,7 @@
private fun createTestOEMSplitInfo(
testPrimaryActivityStack: OEMActivityStack,
testSecondaryActivityStack: OEMActivityStack,
- testSplitAttributes: OEMSplitAttributes
+ testSplitAttributes: OEMSplitAttributes,
): OEMSplitInfo {
return mock<OEMSplitInfo>().apply {
whenever(primaryActivityStack).thenReturn(testPrimaryActivityStack)
@@ -156,7 +156,7 @@
private fun createTestOEMActivityStack(
testActivities: List<Activity>,
- testIsEmpty: Boolean
+ testIsEmpty: Boolean,
): OEMActivityStack {
return mock<OEMActivityStack>().apply {
whenever(activities).thenReturn(testActivities)
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt
index 62dcd3b..582d047 100644
--- a/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/EmbeddingRuleConstructionTests.kt
@@ -81,7 +81,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.5f))
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
assertNull(rule.tag)
assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
@@ -133,7 +133,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.3f))
.setLayoutDirection(TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(Color.BLUE)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.BLUE))
.build()
assertEquals(TEST_TAG, rule.tag)
assertEquals(NEVER, rule.finishPrimaryWithSecondary)
@@ -154,7 +154,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.5f))
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
assertNull(rule.tag)
assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
@@ -180,7 +180,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.3f))
.setLayoutDirection(LEFT_TO_RIGHT)
- .setAnimationBackgroundColor(Color.GREEN)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GREEN))
.build()
filters.add(
SplitPairFilter(
@@ -382,7 +382,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.5f))
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
assertNull(rule.tag)
assertEquals(SPLIT_MIN_DIMENSION_DP_DEFAULT, rule.minWidthDp)
@@ -437,7 +437,8 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.3f))
.setLayoutDirection(BOTTOM_TO_TOP)
- .setAnimationBackgroundColor(application.resources.getColor(R.color.testColor, null))
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(
+ application.resources.getColor(R.color.testColor, null)))
.build()
assertEquals(TEST_TAG, rule.tag)
assertEquals(ALWAYS, rule.finishPrimaryWithPlaceholder)
@@ -465,7 +466,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.5f))
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
assertEquals(expectedSplitLayout, rule.defaultSplitAttributes)
assertTrue(rule.checkParentBounds(density, minValidWindowBounds()))
@@ -489,7 +490,7 @@
val expectedSplitLayout = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.3f))
.setLayoutDirection(LEFT_TO_RIGHT)
- .setAnimationBackgroundColor(Color.GREEN)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GREEN))
.build()
val rule = SplitPlaceholderRule.Builder(filters, intent)
.setMinWidthDp(123)
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/SafeActivityEmbeddingComponentProviderTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/SafeActivityEmbeddingComponentProviderTest.kt
new file mode 100644
index 0000000..3b93a9a
--- /dev/null
+++ b/window/window/src/androidTest/java/androidx/window/embedding/SafeActivityEmbeddingComponentProviderTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 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.ConsumerAdapter
+import androidx.window.extensions.WindowExtensions
+import androidx.window.extensions.WindowExtensionsProvider
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+/**
+ * An integration test to verify that if [WindowExtensionsProvider] is present then
+ * [SafeActivityEmbeddingComponentProvider.activityEmbeddingComponent] will return a value.
+ * This can fail if the implementation of window:extensions:extensions
+ * does not have the expected API.
+ */
+class SafeActivityEmbeddingComponentProviderTest {
+
+ /**
+ * Test that if [WindowExtensionsProvider] is available then
+ * use [SafeActivityEmbeddingComponentProvider.activityEmbeddingComponent] to validate.
+ * If [WindowExtensions.getActivityEmbeddingComponent] matches contract,
+ * return a non-null value.
+ * If it doesn't match, it will return a null.
+ *
+ * TODO(b/267708462) : add a more reliable test
+ */
+ @Test
+ fun activityEmbeddingComponentIsAvailable_ifProviderIsAvailable() {
+ val loader = SafeActivityEmbeddingComponentProviderTest::class.java.classLoader!!
+ val consumerAdapter = ConsumerAdapter(loader)
+ val windowExtensions: WindowExtensions = try {
+ WindowExtensionsProvider.getWindowExtensions()
+ } catch (e: UnsupportedOperationException) {
+ Log.d(TAG, "Device doesn't have WindowExtensions available")
+ return
+ }
+ val safeComponent = SafeActivityEmbeddingComponentProvider(
+ loader,
+ consumerAdapter,
+ windowExtensions
+ )
+ .activityEmbeddingComponent
+ try {
+ val actualComponent = windowExtensions.activityEmbeddingComponent
+ if (actualComponent == null) {
+ assertNull(safeComponent)
+ } else {
+ // TODO(b/267573854) : verify upon each api level
+ // TODO(b/267708462) : more reliable test for testing actual method matching
+ if (safeComponent == null) {
+ Log.d(TAG, "ActivityEmbeddingComponent on device doesn't match our constraints")
+ }
+ }
+ } catch (e: UnsupportedOperationException) {
+ // Invalid implementation of extensions
+ assertNull(safeComponent)
+ }
+ }
+
+ companion object {
+ private const val TAG = "SafeActivityEmbeddingComponentProviderTest"
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/test/java/androidx/window/embedding/SplitAttributesTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/SplitAttributesTest.kt
similarity index 92%
rename from window/window/src/test/java/androidx/window/embedding/SplitAttributesTest.kt
rename to window/window/src/androidTest/java/androidx/window/embedding/SplitAttributesTest.kt
index 96571cc..69c507d 100644
--- a/window/window/src/test/java/androidx/window/embedding/SplitAttributesTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/SplitAttributesTest.kt
@@ -36,27 +36,27 @@
val attrs1 = SplitAttributes.Builder()
.setSplitType(SplitType.splitEqually())
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
val attrs2 = SplitAttributes.Builder()
.setSplitType(SplitType.splitByHinge())
.setLayoutDirection(LOCALE)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
val attrs3 = SplitAttributes.Builder()
.setSplitType(SplitType.splitByHinge())
.setLayoutDirection(TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(0)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.DEFAULT)
.build()
val attrs4 = SplitAttributes.Builder()
.setSplitType(SplitType.splitByHinge())
.setLayoutDirection(TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(Color.GREEN)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GREEN))
.build()
val attrs5 = SplitAttributes.Builder()
.setSplitType(SplitType.splitByHinge())
.setLayoutDirection(TOP_TO_BOTTOM)
- .setAnimationBackgroundColor(Color.GREEN)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.color(Color.GREEN))
.build()
assertNotEquals(attrs1, attrs2)
diff --git a/window/window/src/androidTest/java/androidx/window/embedding/SplitPairFilterTest.kt b/window/window/src/androidTest/java/androidx/window/embedding/SplitPairFilterTest.kt
index 408102b..4c75bd7 100644
--- a/window/window/src/androidTest/java/androidx/window/embedding/SplitPairFilterTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/embedding/SplitPairFilterTest.kt
@@ -22,43 +22,122 @@
import com.google.common.truth.Truth.assertWithMessage
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.whenever
+import org.junit.Before
import org.junit.Test
class SplitPairFilterTest {
- private val component1 = ComponentName("a.b.c", "a.b.c.TestActivity")
- private val component2 = ComponentName("d.e.f", "d.e.f.TestActivity")
- private val intentClassWildcard = ComponentName("d.e.f", "*")
- private val intent = Intent()
- private val activity = mock<Activity> {
- on { intent } doReturn intent
- on { componentName } doReturn component1
+ private val intent1 = Intent()
+ private val intent2 = Intent()
+ private val activity1 = mock<Activity> {
+ on { intent } doReturn intent1
+ on { componentName } doReturn COMPONENT_1
}
- private val filter =
- SplitPairFilter(component1, intentClassWildcard, null /* secondaryActivityIntentAction */)
+ private val activity2 = mock<Activity> {
+ on { intent } doReturn intent2
+ on { componentName } doReturn COMPONENT_2
+ }
- @Test
- fun testMatchActivityIntentPair_MatchIntentComponent() {
- assertWithMessage("#matchesActivityIntentPair must be false because intent is empty")
- .that(filter.matchesActivityIntentPair(activity, intent)).isFalse()
-
- intent.component = component2
-
- assertWithMessage("#matchesActivityIntentPair must be true because intent.component" +
- " matches")
- .that(filter.matchesActivityIntentPair(activity, intent)).isTrue()
+ @Before
+ fun setUp() {
+ intent1.component = COMPONENT_1
+ intent2.component = COMPONENT_2
}
@Test
- fun testMatchActivityIntentPair_MatchIntentPackage() {
- intent.`package` = intentClassWildcard.packageName
+ fun testMatch_WithoutAction() {
+ val filter = SplitPairFilter(
+ COMPONENT_1,
+ COMPONENT_2,
+ null /* secondaryActivityIntentAction */
+ )
+ assertWithMessage("#matchesActivityPair must be true because intents match")
+ .that(filter.matchesActivityPair(activity1, activity2)).isTrue()
+ assertWithMessage("#matchesActivityIntentPair must be true because intents match")
+ .that(filter.matchesActivityIntentPair(activity1, intent2)).isTrue()
+
+ assertWithMessage("#matchesActivityPair must be false because secondary doesn't match")
+ .that(filter.matchesActivityPair(activity1, activity1)).isFalse()
+ assertWithMessage(
+ "#matchesActivityIntentPair must be false because secondary doesn't match"
+ )
+ .that(filter.matchesActivityIntentPair(activity1, intent1)).isFalse()
+
+ assertWithMessage("#matchesActivityPair must be false because primary doesn't match")
+ .that(filter.matchesActivityPair(activity2, activity2)).isFalse()
+ assertWithMessage(
+ "#matchesActivityIntentPair must be false because primary doesn't match"
+ )
+ .that(filter.matchesActivityIntentPair(activity2, intent2)).isFalse()
+ }
+
+ @Test
+ fun testMatch_WithAction() {
+ val filter = SplitPairFilter(COMPONENT_1, WILDCARD, ACTION)
+
+ assertWithMessage("#matchesActivityPair must be false because intent has no action")
+ .that(filter.matchesActivityPair(activity1, activity2)).isFalse()
+ assertWithMessage("#matchesActivityIntentPair must be false because intent has no action")
+ .that(filter.matchesActivityIntentPair(activity1, intent2)).isFalse()
+
+ intent2.action = ACTION
+
+ assertWithMessage("#matchesActivityPair must be true because intent.action matches")
+ .that(filter.matchesActivityPair(activity1, activity2)).isTrue()
+ assertWithMessage("#matchesActivityIntentPair must be true because intent.action matches")
+ .that(filter.matchesActivityIntentPair(activity1, intent2)).isTrue()
+ }
+
+ @Test
+ fun testMatch_WithIntentPackage() {
+ val filter = SplitPairFilter(
+ COMPONENT_1,
+ CLASS_WILDCARD,
+ null /* secondaryActivityIntentAction */
+ )
+ intent2.component = null
+ intent2.`package` = CLASS_WILDCARD.packageName
+ doReturn(COMPONENT_1).whenever(activity2).componentName
+
+ assertWithMessage("#matchesActivityPair must be true because intent.package matches")
+ .that(filter.matchesActivityPair(activity1, activity2)).isTrue()
assertWithMessage("#matchesActivityIntentPair must be true because intent.package matches")
- .that(filter.matchesActivityIntentPair(activity, intent)).isTrue()
+ .that(filter.matchesActivityIntentPair(activity1, intent2)).isTrue()
- intent.component = component1
+ intent2.component = COMPONENT_1
- assertWithMessage("#matchesActivityIntentPair must be false because intent.component" +
- " doesn't match")
- .that(filter.matchesActivityIntentPair(activity, intent)).isFalse()
+ assertWithMessage(
+ "#matchesActivityPair must be false because intent.component doesn't match"
+ )
+ .that(filter.matchesActivityPair(activity1, activity1)).isFalse()
+ assertWithMessage(
+ "#matchesActivityIntentPair must be false because intent.component doesn't match"
+ )
+ .that(filter.matchesActivityIntentPair(activity1, intent1)).isFalse()
+ }
+
+ @Test
+ fun testMatch_EmptyIntentWithWildcard() {
+ val filter = SplitPairFilter(
+ WILDCARD,
+ WILDCARD,
+ null /* secondaryActivityIntentAction */
+ )
+ intent1.component = null
+ intent2.component = null
+
+ assertWithMessage("#matchesActivityPair must be true because rule is wildcard")
+ .that(filter.matchesActivityPair(activity1, activity2)).isTrue()
+ assertWithMessage("#matchesActivityIntentPair must be true because rule is wildcard")
+ .that(filter.matchesActivityIntentPair(activity1, intent2)).isTrue()
+ }
+
+ companion object {
+ private const val ACTION = "action.test"
+ private val COMPONENT_1 = ComponentName("a.b.c", "a.b.c.TestActivity")
+ private val COMPONENT_2 = ComponentName("d.e.f", "d.e.f.TestActivity")
+ private val WILDCARD = ComponentName("*", "*")
+ private val CLASS_WILDCARD = ComponentName("d.e.f", "*")
}
}
\ No newline at end of file
diff --git a/window/window/src/androidTest/java/androidx/window/layout/SafeWindowLayoutComponentProviderTest.kt b/window/window/src/androidTest/java/androidx/window/layout/SafeWindowLayoutComponentProviderTest.kt
index 246e9a3..bc78a38 100644
--- a/window/window/src/androidTest/java/androidx/window/layout/SafeWindowLayoutComponentProviderTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/layout/SafeWindowLayoutComponentProviderTest.kt
@@ -16,9 +16,9 @@
package androidx.window.layout
+import android.util.Log
import androidx.window.core.ConsumerAdapter
import androidx.window.extensions.WindowExtensionsProvider
-import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
@@ -46,11 +46,17 @@
if (actualComponent == null) {
assertNull(safeComponent)
} else {
- assertNotNull(safeComponent)
+ // TODO(b/267831038): verify upon each api level
+ // TODO(b/267708462): more reliable test for testing actual method matching
+ Log.d(TAG, "WindowLayoutComponent on device doesn't match our constraints")
}
} catch (e: UnsupportedOperationException) {
// Invalid implementation of extensions
assertNull(safeComponent)
}
}
+
+ companion object {
+ private const val TAG = "SafeWindowLayoutComponentProviderTest"
+ }
}
\ No newline at end of file
diff --git a/window/window/src/androidTest/java/androidx/window/layout/WindowInfoTrackerImplTest.kt b/window/window/src/androidTest/java/androidx/window/layout/WindowInfoTrackerImplTest.kt
index 1d86ece..9ff7856 100644
--- a/window/window/src/androidTest/java/androidx/window/layout/WindowInfoTrackerImplTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/layout/WindowInfoTrackerImplTest.kt
@@ -24,6 +24,7 @@
import androidx.window.TestConsumer
import androidx.window.WindowTestUtils
import androidx.window.WindowTestUtils.Companion.assumeAtLeastVendorApiLevel
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.adapter.WindowBackend
import java.util.concurrent.Executor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -35,7 +36,7 @@
import org.junit.Rule
import org.junit.Test
-@OptIn(ExperimentalCoroutinesApi::class)
+@OptIn(ExperimentalCoroutinesApi::class, ExperimentalWindowApi::class)
public class WindowInfoTrackerImplTest {
@get:Rule
diff --git a/window/window/src/main/java/androidx/window/area/EmptyWindowAreaControllerImpl.kt b/window/window/src/main/java/androidx/window/area/EmptyWindowAreaControllerImpl.kt
new file mode 100644
index 0000000..d56eccb
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/EmptyWindowAreaControllerImpl.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 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.area
+
+import android.app.Activity
+import androidx.window.core.ExperimentalWindowApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import java.util.concurrent.Executor
+
+/**
+ * Empty Implementation for devices that do not
+ * support the [WindowAreaController] functionality
+ */
+@ExperimentalWindowApi
+internal class EmptyWindowAreaControllerImpl : WindowAreaController {
+ override fun rearDisplayStatus(): Flow<WindowAreaStatus> {
+ return flowOf(WindowAreaStatus.UNSUPPORTED)
+ }
+
+ override fun rearDisplayMode(
+ activity: Activity,
+ executor: Executor,
+ windowAreaSessionCallback: WindowAreaSessionCallback
+ ) {
+ // TODO(b/269144982): Investigate not throwing an exception
+ throw UnsupportedOperationException("Rear Display mode cannot be enabled currently")
+ }
+}
diff --git a/window/window/src/main/java/androidx/window/area/RearDisplaySessionImpl.kt b/window/window/src/main/java/androidx/window/area/RearDisplaySessionImpl.kt
new file mode 100644
index 0000000..ae7d3ca
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/RearDisplaySessionImpl.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.extensions.area.WindowAreaComponent
+
+@ExperimentalWindowApi
+internal class RearDisplaySessionImpl(
+ private val windowAreaComponent: WindowAreaComponent
+) : WindowAreaSession {
+
+ override fun close() {
+ windowAreaComponent.endRearDisplaySession()
+ }
+}
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaAdapter.kt b/window/window/src/main/java/androidx/window/area/WindowAreaAdapter.kt
new file mode 100644
index 0000000..65154449
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaAdapter.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.extensions.area.WindowAreaComponent
+
+/**
+ * Adapter object to assist in translating values received from [WindowAreaComponent]
+ * to developer friendly values in [WindowAreaController]
+ */
+@ExperimentalWindowApi
+internal object WindowAreaAdapter {
+
+ internal fun translate(status: @WindowAreaComponent.WindowAreaStatus Int): WindowAreaStatus {
+ return when (status) {
+ WindowAreaComponent.STATUS_AVAILABLE -> WindowAreaStatus.AVAILABLE
+ WindowAreaComponent.STATUS_UNAVAILABLE -> WindowAreaStatus.UNAVAILABLE
+ else -> WindowAreaStatus.UNSUPPORTED
+ }
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaController.kt b/window/window/src/main/java/androidx/window/area/WindowAreaController.kt
new file mode 100644
index 0000000..385b290
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaController.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2023 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.area
+
+import android.app.Activity
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RestrictTo
+import androidx.window.core.BuildConfig
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.core.VerificationMode
+import androidx.window.extensions.WindowExtensionsProvider
+import androidx.window.extensions.area.WindowAreaComponent
+import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * An interface to provide information about available window areas on the device and an option
+ * to use the rear display area of a foldable device, exclusively or concurrently with the internal
+ * display.
+ */
+@ExperimentalWindowApi
+interface WindowAreaController {
+
+ /**
+ * Provides information about the current state of the window area of the rear display on the
+ * device, if or when it is available. Rear Display mode can be invoked if the current status is
+ * [WindowAreaStatus.AVAILABLE].
+ */
+ fun rearDisplayStatus(): Flow<WindowAreaStatus>
+
+ /**
+ * Starts Rear Display Mode and moves the provided activity to the rear side of the device in
+ * order to face the same direction as the primary device camera(s). When a rear display
+ * mode is started, the system will turn on the rear display of the device to show the content
+ * there, and can disable the internal display. The provided [Activity] is likely to get a
+ * configuration change or being relaunched due to the difference in the internal and rear
+ * display sizes on the device.
+ * <p>Only the top visible application can request and use this mode. The system can dismiss the
+ * mode if the user changes the device state.
+ * <p>This method can only be called if the feature is supported on the device and is reported
+ * as available in the current state through [rearDisplayStatus], otherwise it will
+ * throw an [Exception].
+ */
+ fun rearDisplayMode(
+ activity: Activity,
+ executor: Executor,
+ windowAreaSessionCallback: WindowAreaSessionCallback
+ )
+
+ public companion object {
+ private val TAG = WindowAreaController::class.simpleName
+
+ private var decorator: WindowAreaControllerDecorator = EmptyDecorator
+
+ /**
+ * Provides an instance of [WindowAreaController].
+ */
+ @JvmName("getOrCreate")
+ @JvmStatic
+ fun getOrCreate(): WindowAreaController {
+ var windowAreaComponentExtensions: WindowAreaComponent?
+ try {
+ // TODO(b/267972002): Introduce reflection guard for WindowAreaComponent
+ windowAreaComponentExtensions = WindowExtensionsProvider
+ .getWindowExtensions()
+ .windowAreaComponent
+ } catch (t: Throwable) {
+ if (BuildConfig.verificationMode == VerificationMode.STRICT) {
+ Log.d(TAG, "Failed to load WindowExtensions")
+ }
+ windowAreaComponentExtensions = null
+ }
+ val controller =
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N ||
+ windowAreaComponentExtensions == null) {
+ EmptyWindowAreaControllerImpl()
+ } else {
+ WindowAreaControllerImpl(windowAreaComponentExtensions)
+ }
+ return decorator.decorate(controller)
+ }
+
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ fun overrideDecorator(overridingDecorator: WindowAreaControllerDecorator) {
+ decorator = overridingDecorator
+ }
+
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ fun reset() {
+ decorator = EmptyDecorator
+ }
+ }
+}
+
+/**
+ * Decorator that allows us to provide different functionality
+ * in our window-testing artifact.
+ */
+@ExperimentalWindowApi
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface WindowAreaControllerDecorator {
+ /**
+ * Returns an instance of [WindowAreaController] associated to the [Activity]
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public fun decorate(controller: WindowAreaController): WindowAreaController
+}
+
+@ExperimentalWindowApi
+private object EmptyDecorator : WindowAreaControllerDecorator {
+ override fun decorate(controller: WindowAreaController): WindowAreaController {
+ return controller
+ }
+}
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt b/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt
new file mode 100644
index 0000000..af9a398
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaControllerImpl.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2023 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.area
+
+import android.app.Activity
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import androidx.window.core.BuildConfig
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.core.VerificationMode
+import androidx.window.extensions.area.WindowAreaComponent
+import androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_ACTIVE
+import androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_INACTIVE
+import androidx.window.extensions.core.util.function.Consumer
+import java.util.concurrent.Executor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+
+/**
+ * Implementation of WindowAreaController for devices
+ * that do implement the WindowAreaComponent on device.
+ *
+ * Requires [Build.VERSION_CODES.N] due to the use of [Consumer].
+ * Will not be created though on API levels lower than
+ * [Build.VERSION_CODES.S] as that's the min level of support for
+ * this functionality.
+ */
+@ExperimentalWindowApi
+@RequiresApi(Build.VERSION_CODES.N)
+internal class WindowAreaControllerImpl(
+ private val windowAreaComponent: WindowAreaComponent
+) : WindowAreaController {
+
+ private var currentStatus: WindowAreaStatus? = null
+
+ override fun rearDisplayStatus(): Flow<WindowAreaStatus> {
+ return callbackFlow {
+ val listener = Consumer<@WindowAreaComponent.WindowAreaStatus Int> { status ->
+ currentStatus = WindowAreaAdapter.translate(status)
+ channel.trySend(currentStatus ?: WindowAreaStatus.UNSUPPORTED)
+ }
+ windowAreaComponent.addRearDisplayStatusListener(listener)
+ awaitClose {
+ windowAreaComponent.removeRearDisplayStatusListener(listener)
+ }
+ }.distinctUntilChanged()
+ }
+
+ override fun rearDisplayMode(
+ activity: Activity,
+ executor: Executor,
+ windowAreaSessionCallback: WindowAreaSessionCallback
+ ) {
+ // If we already have a status value that is not [WindowAreaStatus.AVAILABLE]
+ // we should throw an exception quick to indicate they tried to enable
+ // RearDisplay mode when it was not available.
+ if (currentStatus != null && currentStatus != WindowAreaStatus.AVAILABLE) {
+ throw UnsupportedOperationException("Rear Display mode cannot be enabled currently")
+ }
+ val rearDisplaySessionConsumer =
+ RearDisplaySessionConsumer(executor, windowAreaSessionCallback, windowAreaComponent)
+ windowAreaComponent.startRearDisplaySession(activity, rearDisplaySessionConsumer)
+ }
+
+ internal class RearDisplaySessionConsumer(
+ private val executor: Executor,
+ private val appCallback: WindowAreaSessionCallback,
+ private val extensionsComponent: WindowAreaComponent
+ ) : Consumer<@WindowAreaComponent.WindowAreaSessionState Int> {
+
+ private var session: WindowAreaSession? = null
+
+ override fun accept(t: @WindowAreaComponent.WindowAreaSessionState Int) {
+ when (t) {
+ SESSION_STATE_ACTIVE -> onSessionStarted()
+ SESSION_STATE_INACTIVE -> onSessionFinished()
+ else -> {
+ if (BuildConfig.verificationMode == VerificationMode.STRICT) {
+ Log.d(TAG, "Received an unknown session status value: $t")
+ }
+ onSessionFinished()
+ }
+ }
+ }
+
+ private fun onSessionStarted() {
+ session = RearDisplaySessionImpl(extensionsComponent)
+ session?.let { executor.execute { appCallback.onSessionStarted(it) } }
+ }
+
+ private fun onSessionFinished() {
+ session = null
+ executor.execute { appCallback.onSessionEnded() }
+ }
+ }
+
+ internal companion object {
+ private val TAG = WindowAreaControllerImpl::class.simpleName
+ }
+}
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaSession.kt b/window/window/src/main/java/androidx/window/area/WindowAreaSession.kt
new file mode 100644
index 0000000..e84cb4a
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaSession.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+
+/**
+ * Session interface to represent a long-standing
+ * WindowArea mode or feature that provides a handle
+ * to close the session.
+ */
+@ExperimentalWindowApi
+public interface WindowAreaSession {
+ fun close()
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaSessionCallback.kt b/window/window/src/main/java/androidx/window/area/WindowAreaSessionCallback.kt
new file mode 100644
index 0000000..15ea453
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaSessionCallback.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+
+/**
+ * Callback to update the client on the WindowArea Session being
+ * started and ended.
+ * TODO(b/207720511) Move to window-java module when Kotlin API Finalized
+ */
+@ExperimentalWindowApi
+interface WindowAreaSessionCallback {
+
+ fun onSessionStarted(session: WindowAreaSession)
+
+ fun onSessionEnded()
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/area/WindowAreaStatus.kt b/window/window/src/main/java/androidx/window/area/WindowAreaStatus.kt
new file mode 100644
index 0000000..5f8f668
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/area/WindowAreaStatus.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2023 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+
+/**
+ * Represents a window area status.
+ */
+@ExperimentalWindowApi
+class WindowAreaStatus private constructor(private val mDescription: String) {
+
+ override fun toString(): String {
+ return mDescription
+ }
+
+ companion object {
+ /**
+ * Status representing that the WindowArea feature is not a supported
+ * feature on the device.
+ */
+ @JvmField
+ val UNSUPPORTED = WindowAreaStatus("UNSUPPORTED")
+
+ /**
+ * Status representing that the WindowArea feature is currently not available
+ * to be enabled. This could be due to another process has enabled it, or that the
+ * current device configuration doesn't allow it.
+ */
+ @JvmField
+ val UNAVAILABLE = WindowAreaStatus("UNAVAILABLE")
+
+ /**
+ * Status representing that the WindowArea feature is available to be enabled.
+ */
+ @JvmField
+ val AVAILABLE = WindowAreaStatus("AVAILABLE")
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/embedding/ActivityFilter.kt b/window/window/src/main/java/androidx/window/embedding/ActivityFilter.kt
index 836a897..b76a3c2 100644
--- a/window/window/src/main/java/androidx/window/embedding/ActivityFilter.kt
+++ b/window/window/src/main/java/androidx/window/embedding/ActivityFilter.kt
@@ -20,10 +20,11 @@
import android.content.Intent
import android.util.Log
import androidx.window.core.ActivityComponentInfo
-import androidx.window.embedding.MatcherUtils.isActivityOrIntentMatching
+import androidx.window.embedding.MatcherUtils.isActivityMatching
import androidx.window.embedding.MatcherUtils.isIntentMatching
import androidx.window.embedding.MatcherUtils.sDebugMatchers
import androidx.window.embedding.MatcherUtils.sMatchersTag
+import androidx.window.embedding.MatcherUtils.validateComponentName
/**
* Filter for [ActivityRule] and [SplitPlaceholderRule] that checks for component name match when
@@ -69,26 +70,7 @@
)
init {
- val packageName = activityComponentInfo.packageName
- val className = activityComponentInfo.className
- require(
- packageName.isNotEmpty()
- ) { "Package name must not be empty" }
- require(
- className.isNotEmpty()
- ) { "Activity class name must not be empty." }
- require(
- !(
- packageName.contains("*") &&
- packageName.indexOf("*") != packageName.length - 1
- )
- ) { "Wildcard in package name is only allowed at the end." }
- require(
- !(
- className.contains("*") &&
- className.indexOf("*") != className.length - 1
- )
- ) { "Wildcard in class name is only allowed at the end." }
+ validateComponentName(activityComponentInfo.packageName, activityComponentInfo.className)
}
/**
@@ -122,9 +104,8 @@
* @param activity the [Activity] to test against.
*/
fun matchesActivity(activity: Activity): Boolean {
- val match =
- isActivityOrIntentMatching(activity, activityComponentInfo) &&
- (intentAction == null || intentAction == activity.intent?.action)
+ val match = isActivityMatching(activity, activityComponentInfo) &&
+ (intentAction == null || intentAction == activity.intent?.action)
if (sDebugMatchers) {
val matchString = if (match) "MATCH" else "NO MATCH"
Log.w(
diff --git a/window/window/src/main/java/androidx/window/embedding/ActivityRule.kt b/window/window/src/main/java/androidx/window/embedding/ActivityRule.kt
index c231818..310a9fa 100644
--- a/window/window/src/main/java/androidx/window/embedding/ActivityRule.kt
+++ b/window/window/src/main/java/androidx/window/embedding/ActivityRule.kt
@@ -47,18 +47,29 @@
private var alwaysExpand: Boolean = false
/**
- * Whether the activity should always be expanded on launch. Some activities are supposed to
- * expand to the full task bounds, independent of the state of the split. An example is an
- * activity that blocks all user interactions, such as a warning dialog.
+ * Sets whether the activity should always be expanded on launch. Some activities are
+ * supposed to expand to the full task bounds, independent of the state of the split. An
+ * example is an activity that blocks all user interactions, such as a warning dialog.
+ *
+ * @param alwaysExpand whether the activity should always be expanded on launch.
*/
@SuppressWarnings("MissingGetterMatchingBuilder")
fun setAlwaysExpand(alwaysExpand: Boolean): Builder =
apply { this.alwaysExpand = alwaysExpand }
- /** @see ActivityRule.tag */
+ /**
+ * Sets a unique string to identify this [ActivityRule], which defaults to `null`.
+ *
+ * @param tag unique string to identify this [ActivityRule].
+ */
fun setTag(tag: String): Builder =
apply { this.tag = tag }
+ /**
+ * Builds an `ActivityRule` instance.
+ *
+ * @return The new `ActivityRule` instance.
+ */
fun build() = ActivityRule(tag, filters, alwaysExpand)
}
diff --git a/window/window/src/main/java/androidx/window/embedding/ActivityStack.kt b/window/window/src/main/java/androidx/window/embedding/ActivityStack.kt
index 310ce17..7666ad7 100644
--- a/window/window/src/main/java/androidx/window/embedding/ActivityStack.kt
+++ b/window/window/src/main/java/androidx/window/embedding/ActivityStack.kt
@@ -38,18 +38,19 @@
* process(es), [activitiesInProcess] will return an empty list, but this method will return
* `false`.
*/
- val isEmpty: Boolean = false
+ val isEmpty: Boolean
) {
+ /**
+ * Whether this [ActivityStack] contains the [activity].
+ */
operator fun contains(activity: Activity): Boolean {
return activitiesInProcess.contains(activity)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as ActivityStack
+ if (other !is ActivityStack) return false
if (activitiesInProcess != other.activitiesInProcess) return false
if (isEmpty != other.isEmpty) return false
diff --git a/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt b/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
index c38e4f3..da6a05b 100644
--- a/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
+++ b/window/window/src/main/java/androidx/window/embedding/EmbeddingAdapter.kt
@@ -50,17 +50,7 @@
import androidx.window.extensions.embedding.SplitPairRule.FINISH_NEVER
import androidx.window.layout.WindowMetricsCalculator
import androidx.window.layout.adapter.extensions.ExtensionsWindowLayoutInfoAdapter
-import kotlin.Any
-import kotlin.Float
-import kotlin.IllegalArgumentException
-import kotlin.IllegalStateException
-import kotlin.Int
import kotlin.Pair
-import kotlin.Suppress
-import kotlin.apply
-import kotlin.arrayOf
-import kotlin.let
-import kotlin.require
/**
* Adapter class that translates data classes between Extension and Jetpack interfaces.
@@ -113,7 +103,9 @@
)
}
)
- .setAnimationBackgroundColor(splitAttributes.animationBackgroundColor)
+ .setAnimationBackgroundColor(SplitAttributes.BackgroundColor.buildFromValue(
+ splitAttributes.animationBackgroundColor)
+ )
.build()
private fun translate(splitType: OEMSplitType): SplitType =
@@ -228,7 +220,7 @@
)
}
)
- .setAnimationBackgroundColor(splitAttributes.animationBackgroundColor)
+ .setAnimationBackgroundColor(splitAttributes.animationBackgroundColor.value)
.build()
}
diff --git a/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt b/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
index 4b13ef5..dafb5b9 100644
--- a/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
+++ b/window/window/src/main/java/androidx/window/embedding/EmbeddingCompat.kt
@@ -111,7 +111,13 @@
fun isEmbeddingAvailable(): Boolean {
return try {
- WindowExtensionsProvider.getWindowExtensions().activityEmbeddingComponent != null
+ EmbeddingCompat::class.java.classLoader?.let { loader ->
+ SafeActivityEmbeddingComponentProvider(
+ loader,
+ ConsumerAdapter(loader),
+ WindowExtensionsProvider.getWindowExtensions(),
+ ).activityEmbeddingComponent != null
+ } ?: false
} catch (e: NoClassDefFoundError) {
if (DEBUG) {
Log.d(TAG, "Embedding extension version not found")
@@ -127,17 +133,23 @@
fun embeddingComponent(): ActivityEmbeddingComponent {
return if (isEmbeddingAvailable()) {
- WindowExtensionsProvider.getWindowExtensions().activityEmbeddingComponent
- ?: Proxy.newProxyInstance(
- EmbeddingCompat::class.java.classLoader,
- arrayOf(ActivityEmbeddingComponent::class.java)
- ) { _, _, _ -> } as ActivityEmbeddingComponent
+ EmbeddingCompat::class.java.classLoader?.let { loader ->
+ SafeActivityEmbeddingComponentProvider(
+ loader,
+ ConsumerAdapter(loader),
+ WindowExtensionsProvider.getWindowExtensions(),
+ ).activityEmbeddingComponent
+ } ?: emptyActivityEmbeddingProxy()
} else {
- Proxy.newProxyInstance(
- EmbeddingCompat::class.java.classLoader,
- arrayOf(ActivityEmbeddingComponent::class.java)
- ) { _, _, _ -> } as ActivityEmbeddingComponent
+ emptyActivityEmbeddingProxy()
}
}
+
+ private fun emptyActivityEmbeddingProxy(): ActivityEmbeddingComponent {
+ return Proxy.newProxyInstance(
+ EmbeddingCompat::class.java.classLoader,
+ arrayOf(ActivityEmbeddingComponent::class.java)
+ ) { _, _, _ -> } as ActivityEmbeddingComponent
+ }
}
}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/embedding/MatcherUtils.kt b/window/window/src/main/java/androidx/window/embedding/MatcherUtils.kt
index eb61516..1095444 100644
--- a/window/window/src/main/java/androidx/window/embedding/MatcherUtils.kt
+++ b/window/window/src/main/java/androidx/window/embedding/MatcherUtils.kt
@@ -16,7 +16,6 @@
package androidx.window.embedding
import android.app.Activity
-import android.content.ComponentName
import android.content.Intent
import android.util.Log
import androidx.window.core.ActivityComponentInfo
@@ -27,18 +26,6 @@
internal object MatcherUtils {
/** Checks component match allowing wildcard patterns. */
internal fun areComponentsMatching(
- activityComponent: ComponentName?,
- ruleComponent: ComponentName
- ): Boolean {
- val activityActivityComponentInfo = activityComponent?.let(::ActivityComponentInfo)
- return areComponentsMatching(
- activityActivityComponentInfo,
- ActivityComponentInfo(ruleComponent)
- )
- }
-
- /** Checks component match allowing wildcard patterns. */
- internal fun areComponentsMatching(
activityComponent: ActivityComponentInfo?,
ruleComponent: ActivityComponentInfo
): Boolean {
@@ -69,7 +56,7 @@
* Returns `true` if [Activity.getComponentName] match or [Activity.getIntent] match allowing
* wildcard patterns.
*/
- internal fun isActivityOrIntentMatching(
+ internal fun isActivityMatching(
activity: Activity,
ruleComponent: ActivityComponentInfo
): Boolean {
@@ -86,20 +73,24 @@
*/
internal fun isIntentMatching(
intent: Intent,
- ruleActivityComponentInfo: ActivityComponentInfo
+ ruleComponent: ActivityComponentInfo
): Boolean {
- if (intent.component != null) {
- // Compare the component if set.
- return areComponentsMatching(
+ // Check if the component is matched.
+ if (areComponentsMatching(
intent.component?.let(::ActivityComponentInfo),
- ruleActivityComponentInfo
- )
+ ruleComponent
+ )) {
+ return true
+ }
+ if (intent.component != null) {
+ // Only check package if the component is not set.
+ return false
}
// Check if there is wildcard match for Intent that only specifies the packageName.
val packageName = intent.`package` ?: return false
- return (packageName == ruleActivityComponentInfo.packageName ||
- wildcardMatch(packageName, ruleActivityComponentInfo.packageName)) &&
- ruleActivityComponentInfo.className == "*"
+ return (packageName == ruleComponent.packageName ||
+ wildcardMatch(packageName, ruleComponent.packageName)) &&
+ ruleComponent.className == "*"
}
/**
@@ -123,6 +114,22 @@
return name.startsWith(pattern.substring(0, pattern.length - 1))
}
+ /**
+ * Makes sure the component name is in the correct format.
+ */
+ internal fun validateComponentName(packageName: String, className: String) {
+ require(packageName.isNotEmpty()) { "Package name must not be empty" }
+ require(className.isNotEmpty()) { "Activity class name must not be empty" }
+ require(
+ !(packageName.contains("*") &&
+ packageName.indexOf("*") != packageName.length - 1)
+ ) { "Wildcard in package name is only allowed at the end." }
+ require(
+ !(className.contains("*") &&
+ className.indexOf("*") != className.length - 1)
+ ) { "Wildcard in class name is only allowed at the end." }
+ }
+
internal const val sDebugMatchers = SplitController.sDebug
internal const val sMatchersTag = "SplitRuleResolution"
}
diff --git a/window/window/src/main/java/androidx/window/embedding/RuleParser.kt b/window/window/src/main/java/androidx/window/embedding/RuleParser.kt
index c3334c0..add2f25 100644
--- a/window/window/src/main/java/androidx/window/embedding/RuleParser.kt
+++ b/window/window/src/main/java/androidx/window/embedding/RuleParser.kt
@@ -176,7 +176,8 @@
val clearTop = typedArray.getBoolean(R.styleable.SplitPairRule_clearTop, false)
val animationBackgroundColor = typedArray.getColor(
R.styleable.SplitPairRule_animationBackgroundColor,
- 0)
+ SplitAttributes.BackgroundColor.DEFAULT.value
+ )
typedArray.recycle()
val defaultAttrs = SplitAttributes.Builder()
@@ -184,7 +185,9 @@
.setLayoutDirection(
SplitAttributes.LayoutDirection.getLayoutDirectionFromValue(layoutDir)
)
- .setAnimationBackgroundColor(animationBackgroundColor)
+ .setAnimationBackgroundColor(
+ SplitAttributes.BackgroundColor.buildFromValue(animationBackgroundColor)
+ )
.build()
SplitPairRule.Builder(emptySet())
@@ -258,7 +261,8 @@
)
val animationBackgroundColor = typedArray.getColor(
R.styleable.SplitPlaceholderRule_animationBackgroundColor,
- 0)
+ SplitAttributes.BackgroundColor.DEFAULT.value
+ )
typedArray.recycle()
val defaultAttrs = SplitAttributes.Builder()
@@ -266,7 +270,9 @@
.setLayoutDirection(
SplitAttributes.LayoutDirection.getLayoutDirectionFromValue(layoutDir)
)
- .setAnimationBackgroundColor(animationBackgroundColor)
+ .setAnimationBackgroundColor(
+ SplitAttributes.BackgroundColor.buildFromValue(animationBackgroundColor)
+ )
.build()
val packageName = context.applicationContext.packageName
val placeholderActivityClassName = buildClassName(
diff --git a/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt b/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt
new file mode 100644
index 0000000..44699d8
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2023 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.app.Activity
+import androidx.window.core.ConsumerAdapter
+import androidx.window.core.ExtensionsUtil
+import androidx.window.extensions.WindowExtensions
+import androidx.window.extensions.core.util.function.Consumer
+import androidx.window.extensions.core.util.function.Function
+import androidx.window.extensions.embedding.ActivityEmbeddingComponent
+import androidx.window.reflection.ReflectionUtils.doesReturn
+import androidx.window.reflection.ReflectionUtils.isPublic
+import androidx.window.reflection.ReflectionUtils.validateReflection
+import androidx.window.reflection.WindowExtensionsConstants.ACTIVITY_EMBEDDING_COMPONENT_CLASS
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_EXTENSIONS_CLASS
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_EXTENSIONS_PROVIDER_CLASS
+
+/**
+ * Reflection Guard for [ActivityEmbeddingComponent].
+ * This will go through the [ActivityEmbeddingComponent]'s method by reflection and
+ * check each method's name and signature to see if the interface is what we required.
+ */
+internal class SafeActivityEmbeddingComponentProvider(
+ private val loader: ClassLoader,
+ private val consumerAdapter: ConsumerAdapter,
+ private val windowExtensions: WindowExtensions
+) {
+ val activityEmbeddingComponent: ActivityEmbeddingComponent?
+ get() {
+ return if (canUseActivityEmbeddingComponent()) {
+ try {
+ windowExtensions.activityEmbeddingComponent
+ } catch (e: UnsupportedOperationException) {
+ null
+ }
+ } else {
+ null
+ }
+ }
+
+ private fun canUseActivityEmbeddingComponent(): Boolean {
+ if (!isWindowExtensionsValid() || !isActivityEmbeddingComponentValid()) {
+ return false
+ }
+ // TODO(b/267573854) : update logic to fallback to lower version
+ // if higher version is not matched
+ return when (ExtensionsUtil.safeVendorApiLevel) {
+ 1 -> hasValidVendorApiLevel1()
+ in 2..Int.MAX_VALUE -> hasValidVendorApiLevel2()
+ // TODO(b/267956499) : add hasValidVendorApiLevel3
+ else -> false
+ }
+ }
+
+ /**
+ * [WindowExtensions.VENDOR_API_LEVEL_1] includes the following methods:
+ * - [ActivityEmbeddingComponent.setEmbeddingRules]
+ * - [ActivityEmbeddingComponent.isActivityEmbedded]
+ * - [ActivityEmbeddingComponent.setSplitInfoCallback] with [java.util.function.Consumer]
+ * and following classes: TODO(b/268583307) : add guard function for those classes
+ * - [androidx.window.extensions.embedding.ActivityRule]
+ * - [androidx.window.extensions.embedding.SplitPairRule]
+ * - [androidx.window.extensions.embedding.SplitPlaceholderRule]
+ * - [androidx.window.extensions.embedding.SplitInfo]
+ */
+ private fun hasValidVendorApiLevel1(): Boolean {
+ return isMethodSetEmbeddingRulesValid() &&
+ isMethodIsActivityEmbeddedValid() &&
+ isMethodSetSplitInfoCallbackJavaConsumerValid()
+ }
+
+ /**
+ * [WindowExtensions.VENDOR_API_LEVEL_2] includes the following methods
+ * - [ActivityEmbeddingComponent.setSplitInfoCallback] with [Consumer]
+ * - [ActivityEmbeddingComponent.clearSplitInfoCallback]
+ * - [ActivityEmbeddingComponent.setSplitAttributesCalculator]
+ * - [ActivityEmbeddingComponent.clearSplitAttributesCalculator]
+ * and following classes: TODO(b/268583307) : add guard function for those classes
+ * - [androidx.window.extensions.embedding.SplitAttributes]
+ */
+ private fun hasValidVendorApiLevel2(): Boolean {
+ return hasValidVendorApiLevel1() &&
+ isMethodSetSplitInfoCallbackWindowConsumerValid() &&
+ isMethodClearSplitInfoCallbackValid() &&
+ isMethodSplitAttributesCalculatorValid()
+ }
+
+ private fun isMethodSetEmbeddingRulesValid(): Boolean {
+ return validateReflection("ActivityEmbeddingComponent#setEmbeddingRules is not valid") {
+ val setEmbeddingRulesMethod = activityEmbeddingComponentClass.getMethod(
+ "setEmbeddingRules",
+ Set::class.java
+ )
+ setEmbeddingRulesMethod.isPublic
+ }
+ }
+
+ private fun isMethodIsActivityEmbeddedValid(): Boolean {
+ return validateReflection("ActivityEmbeddingComponent#isActivityEmbedded is not valid") {
+ val isActivityEmbeddedMethod = activityEmbeddingComponentClass.getMethod(
+ "isActivityEmbedded",
+ Activity::class.java
+ )
+ isActivityEmbeddedMethod.isPublic &&
+ isActivityEmbeddedMethod.doesReturn(Boolean::class.java)
+ }
+ }
+
+ private fun isMethodClearSplitInfoCallbackValid(): Boolean {
+ return validateReflection(
+ "ActivityEmbeddingComponent#clearSplitInfoCallback is not valid"
+ ) {
+ val clearSplitInfoCallbackMethod =
+ activityEmbeddingComponentClass.getMethod("clearSplitInfoCallback")
+ clearSplitInfoCallbackMethod.isPublic
+ }
+ }
+
+ private fun isMethodSplitAttributesCalculatorValid(): Boolean {
+ return validateReflection(
+ "ActivityEmbeddingComponent#setSplitAttributesCalculator is not valid"
+ ) {
+ val setSplitAttributesCalculatorMethod = activityEmbeddingComponentClass.getMethod(
+ "setSplitAttributesCalculator",
+ Function::class.java
+ )
+ val clearSplitAttributesCalculatorMethod =
+ activityEmbeddingComponentClass.getMethod("clearSplitAttributesCalculator")
+ setSplitAttributesCalculatorMethod.isPublic &&
+ clearSplitAttributesCalculatorMethod.isPublic
+ }
+ }
+
+ private fun isMethodSetSplitInfoCallbackJavaConsumerValid(): Boolean {
+ return validateReflection("ActivityEmbeddingComponent#setSplitInfoCallback is not valid") {
+ val consumerClass =
+ consumerAdapter.consumerClassOrNull() ?: return@validateReflection false
+ val setSplitInfoCallbackMethod =
+ activityEmbeddingComponentClass.getMethod("setSplitInfoCallback", consumerClass)
+ setSplitInfoCallbackMethod.isPublic
+ }
+ }
+
+ private fun isMethodSetSplitInfoCallbackWindowConsumerValid(): Boolean {
+ return validateReflection("ActivityEmbeddingComponent#setSplitInfoCallback is not valid") {
+ val setSplitInfoCallbackMethod = activityEmbeddingComponentClass.getMethod(
+ "setSplitInfoCallback",
+ Consumer::class.java
+ )
+ setSplitInfoCallbackMethod.isPublic
+ }
+ }
+
+ private fun isWindowExtensionsValid(): Boolean {
+ return validateReflection("WindowExtensionsProvider#getWindowExtensions is not valid") {
+ val providerClass = windowExtensionsProviderClass
+ val getWindowExtensionsMethod = providerClass.getDeclaredMethod("getWindowExtensions")
+ val windowExtensionsClass = windowExtensionsClass
+ getWindowExtensionsMethod.isPublic && getWindowExtensionsMethod.doesReturn(
+ windowExtensionsClass
+ )
+ }
+ }
+
+ private fun isActivityEmbeddingComponentValid(): Boolean {
+ return validateReflection("WindowExtensions#getActivityEmbeddingComponent is not valid") {
+ val extensionsClass = windowExtensionsClass
+ val getActivityEmbeddingComponentMethod =
+ extensionsClass.getMethod("getActivityEmbeddingComponent")
+ val activityEmbeddingComponentClass = activityEmbeddingComponentClass
+ getActivityEmbeddingComponentMethod.isPublic &&
+ getActivityEmbeddingComponentMethod.doesReturn(activityEmbeddingComponentClass)
+ }
+ }
+
+ private val windowExtensionsProviderClass: Class<*>
+ get() {
+ return loader.loadClass(WINDOW_EXTENSIONS_PROVIDER_CLASS)
+ }
+
+ private val windowExtensionsClass: Class<*>
+ get() {
+ return loader.loadClass(WINDOW_EXTENSIONS_CLASS)
+ }
+
+ private val activityEmbeddingComponentClass: Class<*>
+ get() {
+ return loader.loadClass(ACTIVITY_EMBEDDING_COMPONENT_CLASS)
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/embedding/SplitAttributes.kt b/window/window/src/main/java/androidx/window/embedding/SplitAttributes.kt
index d83ce52..64219d2 100644
--- a/window/window/src/main/java/androidx/window/embedding/SplitAttributes.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SplitAttributes.kt
@@ -17,14 +17,14 @@
package androidx.window.embedding
import android.annotation.SuppressLint
+import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import androidx.annotation.IntRange
import androidx.window.core.SpecificationComputer.Companion.startSpecification
import androidx.window.core.VerificationMode
-import androidx.window.embedding.SplitAttributes.LayoutDirection
+import androidx.window.embedding.SplitAttributes.BackgroundColor
import androidx.window.embedding.SplitAttributes.LayoutDirection.Companion.LOCALE
-import androidx.window.embedding.SplitAttributes.SplitType
import androidx.window.embedding.SplitAttributes.SplitType.Companion.splitEqually
/**
@@ -48,15 +48,16 @@
* - Setting `splitRatio`, `splitLayoutDirection`, and
* `animationBackgroundColor` attributes in `<SplitPairRule>` or
* `<SplitPlaceholderRule>` tags in an XML configuration file. The
- * attributes are parsed as [SplitType], [LayoutDirection], and [ColorInt],
- * respectively. Note that [SplitType.HingeSplitType] is not supported XML
- * format.
+ * attributes are parsed as [SplitType], [LayoutDirection], and
+ * [BackgroundColor], respectively. Note that [SplitType.HingeSplitType]
+ * is not supported XML format.
* - Using
* [SplitAttributesCalculator.computeSplitAttributesForParams] to customize
* the `SplitAttributes` for a given device and window state.
*
* @see SplitAttributes.SplitType
* @see SplitAttributes.LayoutDirection
+ * @see SplitAttributes.BackgroundColor
*/
class SplitAttributes internal constructor(
@@ -73,14 +74,16 @@
val layoutDirection: LayoutDirection = LOCALE,
/**
- * The [ColorInt] to use for the background color during the animation of
+ * The color to use for the background color during the animation of
* the split involving this `SplitAttributes` object if the animation
* requires a background.
*
- * The default is 0, which specifies the theme window background color.
+ * The default is to use the current theme window background color.
+ *
+ * @see BackgroundColor.color
+ * @see BackgroundColor.DEFAULT
*/
- @ColorInt
- val animationBackgroundColor: Int = 0
+ val animationBackgroundColor: BackgroundColor = BackgroundColor.DEFAULT
) {
/**
@@ -422,6 +425,85 @@
}
/**
+ * Background color to be used for window transition animations in a split if the animation
+ * requires a background.
+ *
+ * @see SplitAttributes.animationBackgroundColor
+ */
+ class BackgroundColor private constructor(
+
+ /**
+ * The description of this `BackgroundColor`.
+ */
+ private val description: String,
+
+ /**
+ * [ColorInt] to represent the color to use as the background color.
+ */
+ @ColorInt
+ internal val value: Int,
+ ) {
+ override fun toString() = "BackgroundColor($description)"
+
+ override fun equals(other: Any?): Boolean {
+ if (other === this) return true
+ if (other !is BackgroundColor) return false
+ return value == other.value && description == other.description
+ }
+
+ override fun hashCode() = description.hashCode() + 31 * value.hashCode()
+
+ /**
+ * Methods that create various [BackgroundColor].
+ */
+ companion object {
+
+ /**
+ * Creates a [BackgroundColor] to represent the given [color].
+ *
+ * Only opaque color is supported.
+ *
+ * @param color [ColorInt] of an opaque color.
+ * @return the [BackgroundColor] representing the [color].
+ *
+ * @see [DEFAULT] for the default value, which means to use the
+ * current theme window background color.
+ */
+ @JvmStatic
+ fun color(
+ @IntRange(from = Color.BLACK.toLong(), to = Color.WHITE.toLong())
+ @ColorInt
+ color: Int
+ ):
+ BackgroundColor {
+ require(Color.BLACK <= color && color <= Color.WHITE) {
+ "Background color must be opaque"
+ }
+ return BackgroundColor("color:${Integer.toHexString(color)}", color)
+ }
+
+ /**
+ * The special [BackgroundColor] to represent the default value,
+ * which means to use the current theme window background color.
+ */
+ @JvmField
+ val DEFAULT = BackgroundColor("DEFAULT", 0)
+
+ /**
+ * Returns a [BackgroundColor] with the given [value]
+ */
+ internal fun buildFromValue(@ColorInt value: Int): BackgroundColor {
+ return if (Color.alpha(value) != 255) {
+ // Treat any non-opaque color as the default.
+ DEFAULT
+ } else {
+ color(value)
+ }
+ }
+ }
+ }
+
+ /**
* Non-public properties and methods.
*/
companion object {
@@ -464,21 +546,21 @@
override fun toString(): String =
"${SplitAttributes::class.java.simpleName}:" +
"{splitType=$splitType, layoutDir=$layoutDirection," +
- " animationBackgroundColor=${Integer.toHexString(animationBackgroundColor)}"
+ " animationBackgroundColor=$animationBackgroundColor"
/**
* Builder for creating an instance of [SplitAttributes].
*
- * The default split type is an equal split between primary and secondary
- * containers. The default layout direction is based on locale. The default
- * animation background color is 0, which specifies the theme window
- * background color.
+ * - The default split type is an equal split between primary and secondary
+ * containers.
+ * - The default layout direction is based on locale.
+ * - The default animation background color is to use the current theme
+ * window background color.
*/
class Builder {
private var splitType: SplitType = splitEqually()
private var layoutDirection = LOCALE
- @ColorInt
- private var animationBackgroundColor = 0
+ private var animationBackgroundColor = BackgroundColor.DEFAULT
/**
* Sets the split type attribute.
@@ -507,20 +589,23 @@
apply { this.layoutDirection = layoutDirection }
/**
- * Sets the [ColorInt] to use for the background color during animation
+ * Sets the color to use for the background color during animation
* of the split involving this `SplitAttributes` object if the animation
- * requires a background.
+ * requires a background. Only opaque color is supported.
*
- * The default is 0, which specifies the theme window background color.
+ * The default is [BackgroundColor.DEFAULT], which means to use the
+ * current theme window background color.
*
- * @param color A packed color int of the form `AARRGGBB`, for the
- * animation background color.
+ * @param color The animation background color.
* @return This `Builder`.
*
- * @see SplitAttributes.animationBackgroundColor
+ * @see BackgroundColor.color
+ * @see BackgroundColor.DEFAULT
*/
- fun setAnimationBackgroundColor(@ColorInt color: Int): Builder =
- apply { this.animationBackgroundColor = color }
+ fun setAnimationBackgroundColor(color: BackgroundColor): Builder =
+ apply {
+ animationBackgroundColor = color
+ }
/**
* Builds a `SplitAttributes` instance with the attributes specified by
diff --git a/window/window/src/main/java/androidx/window/embedding/SplitInfo.kt b/window/window/src/main/java/androidx/window/embedding/SplitInfo.kt
index fabb354..b3dc89c 100644
--- a/window/window/src/main/java/androidx/window/embedding/SplitInfo.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SplitInfo.kt
@@ -31,6 +31,10 @@
/** The [SplitAttributes] of this split pair. */
val splitAttributes: SplitAttributes
) {
+ /**
+ * Whether the [primaryActivityStack] or the [secondaryActivityStack] in this [SplitInfo]
+ * contains the [activity].
+ */
operator fun contains(activity: Activity): Boolean {
return primaryActivityStack.contains(activity) ||
secondaryActivityStack.contains(activity)
diff --git a/window/window/src/main/java/androidx/window/embedding/SplitPairFilter.kt b/window/window/src/main/java/androidx/window/embedding/SplitPairFilter.kt
index d09fa3b..5c022fa 100644
--- a/window/window/src/main/java/androidx/window/embedding/SplitPairFilter.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SplitPairFilter.kt
@@ -20,10 +20,11 @@
import android.content.Intent
import android.util.Log
import androidx.window.core.ActivityComponentInfo
-import androidx.window.embedding.MatcherUtils.areComponentsMatching
+import androidx.window.embedding.MatcherUtils.isActivityMatching
import androidx.window.embedding.MatcherUtils.isIntentMatching
import androidx.window.embedding.MatcherUtils.sDebugMatchers
import androidx.window.embedding.MatcherUtils.sMatchersTag
+import androidx.window.embedding.MatcherUtils.validateComponentName
/**
* Filter for [SplitPairRule] and used to find if a pair of activities should be put in a split.
@@ -79,6 +80,14 @@
val secondaryActivityIntentAction: String?
) {
+ init {
+ validateComponentName(primaryActivityName.packageName, primaryActivityName.className)
+ validateComponentName(secondaryActivityName.packageName, secondaryActivityName.className)
+ }
+
+ private val primaryActivityInfo: ActivityComponentInfo
+ get() = ActivityComponentInfo(primaryActivityName)
+
private val secondaryActivityInfo: ActivityComponentInfo
get() = ActivityComponentInfo(secondaryActivityName)
@@ -92,11 +101,13 @@
*/
fun matchesActivityPair(primaryActivity: Activity, secondaryActivity: Activity): Boolean {
// Check if the activity component names match
- var match = areComponentsMatching(primaryActivity.componentName, primaryActivityName) &&
- areComponentsMatching(secondaryActivity.componentName, secondaryActivityName)
- // If the intent is not empty - check that the rest of the filter fields match
- if (secondaryActivity.intent != null) {
- match = match && matchesActivityIntentPair(primaryActivity, secondaryActivity.intent)
+ val match = if (!isActivityMatching(primaryActivity, primaryActivityInfo)) {
+ false
+ } else if (!isActivityMatching(secondaryActivity, secondaryActivityInfo)) {
+ false
+ } else {
+ secondaryActivityIntentAction == null ||
+ secondaryActivityIntentAction == secondaryActivity.intent?.action
}
if (sDebugMatchers) {
@@ -123,14 +134,9 @@
primaryActivity: Activity,
secondaryActivityIntent: Intent
): Boolean {
- val inPrimaryActivityName = primaryActivity.componentName
- val match = if (
- !areComponentsMatching(inPrimaryActivityName, primaryActivityName)
- ) {
+ val match = if (!isActivityMatching(primaryActivity, primaryActivityInfo)) {
false
- } else if (
- !isIntentMatching(secondaryActivityIntent, secondaryActivityInfo)
- ) {
+ } else if (!isIntentMatching(secondaryActivityIntent, secondaryActivityInfo)) {
false
} else {
secondaryActivityIntentAction == null ||
@@ -147,43 +153,6 @@
return match
}
- init {
- val primaryPackageName = primaryActivityName.packageName
- val primaryClassName = primaryActivityName.className
- val secondaryPackageName = secondaryActivityName.packageName
- val secondaryClassName = secondaryActivityName.className
- require(
- !(primaryPackageName.isEmpty() || secondaryPackageName.isEmpty())
- ) { "Package name must not be empty" }
- require(
- !(primaryClassName.isEmpty() || secondaryClassName.isEmpty())
- ) { "Activity class name must not be empty." }
- require(
- !(
- primaryPackageName.contains("*") &&
- primaryPackageName.indexOf("*") != primaryPackageName.length - 1
- )
- ) { "Wildcard in package name is only allowed at the end." }
- require(
- !(
- primaryClassName.contains("*") &&
- primaryClassName.indexOf("*") != primaryClassName.length - 1
- )
- ) { "Wildcard in class name is only allowed at the end." }
- require(
- !(
- secondaryPackageName.contains("*") &&
- secondaryPackageName.indexOf("*") != secondaryPackageName.length - 1
- )
- ) { "Wildcard in package name is only allowed at the end." }
- require(
- !(
- secondaryClassName.contains("*") &&
- secondaryClassName.indexOf("*") != secondaryClassName.length - 1
- )
- ) { "Wildcard in class name is only allowed at the end." }
- }
-
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SplitPairFilter) return false
diff --git a/window/window/src/main/java/androidx/window/embedding/SplitPairRule.kt b/window/window/src/main/java/androidx/window/embedding/SplitPairRule.kt
index 76a561c..2cf3650 100644
--- a/window/window/src/main/java/androidx/window/embedding/SplitPairRule.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SplitPairRule.kt
@@ -117,6 +117,9 @@
*
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
+ *
+ * @param minWidthDp the smallest value of width of the parent window when the split should
+ * be used, in DP.
*/
fun setMinWidthDp(@IntRange(from = 0) minWidthDp: Int): Builder =
apply { this.minWidthDp = minWidthDp }
@@ -133,6 +136,9 @@
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
*
+ * @param minHeightDp the smallest value of height of the parent task window when the split
+ * should be used, in DP.
+ *
* @see SplitAttributes.LayoutDirection.TOP_TO_BOTTOM
* @see SplitAttributes.LayoutDirection.BOTTOM_TO_TOP
*/
@@ -141,12 +147,15 @@
/**
* Sets the smallest value of the smallest possible width of the parent window in any
- * rotation when the split should be used, in DP. When the window size is smaller than
+ * rotation when the split should be used, in DP. When the window size is smaller than
* requested here, activities in the secondary container will be stacked on top of the
* activities in the primary one, completely overlapping them.
*
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
+ *
+ * @param minSmallestWidthDp the smallest value of the smallest possible width of the parent
+ * window in any rotation when the split should be used, in DP.
*/
fun setMinSmallestWidthDp(@IntRange(from = 0) minSmallestWidthDp: Int): Builder =
apply { this.minSmallestWidthDp = minSmallestWidthDp }
@@ -163,6 +172,9 @@
* the recommend value to only allow split when the parent window is not too stretched in
* portrait.
*
+ * @param aspectRatio the largest value of the aspect ratio, expressed as `height / width`
+ * in decimal form, of the parent window bounds in portrait when the split should be used.
+ *
* @see EmbeddingAspectRatio.ratio
* @see EmbeddingAspectRatio.ALWAYS_ALLOW
* @see EmbeddingAspectRatio.ALWAYS_DISALLOW
@@ -181,6 +193,9 @@
* The default is [SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT] if the app doesn't set, which
* is the recommend value to always allow split when the parent window is in landscape.
*
+ * @param aspectRatio the largest value of the aspect ratio, expressed as `width / height`
+ * in decimal form, of the parent window bounds in landscape when the split should be used.
+ *
* @see EmbeddingAspectRatio.ratio
* @see EmbeddingAspectRatio.ALWAYS_ALLOW
* @see EmbeddingAspectRatio.ALWAYS_DISALLOW
@@ -192,6 +207,9 @@
* Sets the behavior of the primary container when all activities are finished in the
* associated secondary container.
*
+ * @param finishPrimaryWithSecondary the [SplitRule.FinishBehavior] of the primary container
+ * when all activities are finished in the associated secondary container.
+ *
* @see SplitRule.FinishBehavior.NEVER
* @see SplitRule.FinishBehavior.ALWAYS
* @see SplitRule.FinishBehavior.ADJACENT
@@ -205,6 +223,9 @@
* Sets the behavior of the secondary container when all activities are finished in the
* associated primary container.
*
+ * @param finishSecondaryWithPrimary the [SplitRule.FinishBehavior] of the secondary
+ * container when all activities are finished in the associated primary container.
+ *
* @see SplitRule.FinishBehavior.NEVER
* @see SplitRule.FinishBehavior.ALWAYS
* @see SplitRule.FinishBehavior.ADJACENT
@@ -218,6 +239,9 @@
* Sets whether the existing secondary container on top and all activities in it should be
* destroyed when a new split is created using this rule. Otherwise the new secondary will
* appear on top by default.
+ *
+ * @param clearTop whether the existing secondary container on top and all activities in it
+ * should be destroyed when a new split is created using this rule.
*/
@SuppressWarnings("MissingGetterMatchingBuilder")
fun setClearTop(clearTop: Boolean): Builder =
@@ -227,6 +251,9 @@
* Sets the default [SplitAttributes] to apply on the activity containers pair when the host
* task bounds satisfy [minWidthDp], [minHeightDp], [minSmallestWidthDp],
* [maxAspectRatioInPortrait] and [maxAspectRatioInLandscape] requirements.
+ *
+ * @param defaultSplitAttributes the default [SplitAttributes] to apply on the activity
+ * containers pair when the host task bounds satisfy all the rule requirements.
*/
fun setDefaultSplitAttributes(defaultSplitAttributes: SplitAttributes): Builder =
apply { this.defaultSplitAttributes = defaultSplitAttributes }
@@ -235,10 +262,17 @@
* Sets a unique string to identify this [SplitPairRule], which defaults to `null`.
* The suggested usage is to set the tag to be able to differentiate between different rules
* in the [SplitAttributesCalculatorParams.splitRuleTag].
+ *
+ * @param tag unique string to identify this [SplitPairRule].
*/
fun setTag(tag: String?): Builder =
apply { this.tag = tag }
+ /**
+ * Builds a `SplitPairRule` instance.
+ *
+ * @return The new `SplitPairRule` instance.
+ */
fun build() = SplitPairRule(
tag,
filters,
diff --git a/window/window/src/main/java/androidx/window/embedding/SplitPlaceholderRule.kt b/window/window/src/main/java/androidx/window/embedding/SplitPlaceholderRule.kt
index 1dc70c1..2639171 100644
--- a/window/window/src/main/java/androidx/window/embedding/SplitPlaceholderRule.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SplitPlaceholderRule.kt
@@ -128,6 +128,9 @@
*
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
+ *
+ * @param minWidthDp the smallest value of width of the parent window when the split should
+ * be used, in DP.
*/
fun setMinWidthDp(@IntRange(from = 0) minWidthDp: Int): Builder =
apply { this.minWidthDp = minWidthDp }
@@ -144,6 +147,9 @@
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
*
+ * @param minHeightDp the smallest value of height of the parent task window when the split
+ * should be used, in DP.
+ *
* @see SplitAttributes.LayoutDirection.TOP_TO_BOTTOM
* @see SplitAttributes.LayoutDirection.BOTTOM_TO_TOP
*/
@@ -152,12 +158,15 @@
/**
* Sets the smallest value of the smallest possible width of the parent window in any
- * rotation when the split should be used, in DP. When the window size is smaller than
+ * rotation when the split should be used, in DP. When the window size is smaller than
* requested here, activities in the secondary container will be stacked on top of the
* activities in the primary one, completely overlapping them.
*
* The default is [SPLIT_MIN_DIMENSION_DP_DEFAULT] if the app doesn't set.
* [SPLIT_MIN_DIMENSION_ALWAYS_ALLOW] means to always allow split.
+ *
+ * @param minSmallestWidthDp the smallest value of the smallest possible width of the parent
+ * window in any rotation when the split should be used, in DP.
*/
fun setMinSmallestWidthDp(@IntRange(from = 0) minSmallestWidthDp: Int): Builder =
apply { this.minSmallestWidthDp = minSmallestWidthDp }
@@ -174,6 +183,9 @@
* the recommend value to only allow split when the parent window is not too stretched in
* portrait.
*
+ * @param aspectRatio the largest value of the aspect ratio, expressed as `height / width`
+ * in decimal form, of the parent window bounds in portrait when the split should be used.
+ *
* @see EmbeddingAspectRatio.ratio
* @see EmbeddingAspectRatio.ALWAYS_ALLOW
* @see EmbeddingAspectRatio.ALWAYS_DISALLOW
@@ -192,6 +204,9 @@
* The default is [SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT] if the app doesn't set, which
* is the recommend value to always allow split when the parent window is in landscape.
*
+ * @param aspectRatio the largest value of the aspect ratio, expressed as `width / height`
+ * in decimal form, of the parent window bounds in landscape when the split should be used.
+ *
* @see EmbeddingAspectRatio.ratio
* @see EmbeddingAspectRatio.ALWAYS_ALLOW
* @see EmbeddingAspectRatio.ALWAYS_DISALLOW
@@ -205,6 +220,9 @@
*
* **Note** that it is not valid to set [SplitRule.FinishBehavior.NEVER]
*
+ * @param finishPrimaryWithPlaceholder the [SplitRule.FinishBehavior] of the primary
+ * container when all activities are finished in the associated placeholder container.
+ *
* @see SplitRule.FinishBehavior.ALWAYS
* @see SplitRule.FinishBehavior.ADJACENT
*/
@@ -216,6 +234,9 @@
/**
* Sets whether the placeholder will show on top in a smaller window size after it first
* appeared in a split with sufficient minimum width.
+ *
+ * @param isSticky whether the placeholder will show on top in a smaller window size after
+ * it first appeared in a split with sufficient minimum width.
*/
fun setSticky(isSticky: Boolean): Builder =
apply { this.isSticky = isSticky }
@@ -224,6 +245,9 @@
* Sets the default [SplitAttributes] to apply on the activity containers pair when the host
* task bounds satisfy [minWidthDp], [minHeightDp], [minSmallestWidthDp],
* [maxAspectRatioInPortrait] and [maxAspectRatioInLandscape] requirements.
+ *
+ * @param defaultSplitAttributes the default [SplitAttributes] to apply on the activity
+ * containers pair when the host task bounds satisfy all the rule requirements.
*/
fun setDefaultSplitAttributes(defaultSplitAttributes: SplitAttributes): Builder =
apply { this.defaultSplitAttributes = defaultSplitAttributes }
@@ -232,10 +256,17 @@
* Sets a unique string to identify this [SplitPlaceholderRule], which defaults to `null`.
* The suggested usage is to set the tag to be able to differentiate between different rules
* in the [SplitAttributesCalculatorParams.splitRuleTag].
+ *
+ * @param tag unique string to identify this [SplitPlaceholderRule].
*/
fun setTag(tag: String?): Builder =
apply { this.tag = tag }
+ /**
+ * Builds a `SplitPlaceholderRule` instance.
+ *
+ * @return The new `SplitPlaceholderRule` instance.
+ */
fun build() = SplitPlaceholderRule(
tag,
filters,
diff --git a/window/window/src/main/java/androidx/window/layout/SafeWindowLayoutComponentProvider.kt b/window/window/src/main/java/androidx/window/layout/SafeWindowLayoutComponentProvider.kt
index 6c9ec9d..fdc25a2 100644
--- a/window/window/src/main/java/androidx/window/layout/SafeWindowLayoutComponentProvider.kt
+++ b/window/window/src/main/java/androidx/window/layout/SafeWindowLayoutComponentProvider.kt
@@ -17,14 +17,30 @@
package androidx.window.layout
import android.app.Activity
+import android.content.Context
import android.graphics.Rect
import androidx.window.core.ConsumerAdapter
+import androidx.window.core.ExtensionsUtil
+import androidx.window.extensions.WindowExtensions
import androidx.window.extensions.WindowExtensionsProvider
+import androidx.window.extensions.core.util.function.Consumer
import androidx.window.extensions.layout.WindowLayoutComponent
-import java.lang.reflect.Method
-import java.lang.reflect.Modifier
-import kotlin.reflect.KClass
+import androidx.window.reflection.ReflectionUtils.checkIsPresent
+import androidx.window.reflection.ReflectionUtils.doesReturn
+import androidx.window.reflection.ReflectionUtils.isPublic
+import androidx.window.reflection.ReflectionUtils.validateReflection
+import androidx.window.reflection.WindowExtensionsConstants.FOLDING_FEATURE_CLASS
+import androidx.window.reflection.WindowExtensionsConstants.JAVA_CONSUMER
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_CONSUMER
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_EXTENSIONS_CLASS
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_EXTENSIONS_PROVIDER_CLASS
+import androidx.window.reflection.WindowExtensionsConstants.WINDOW_LAYOUT_COMPONENT_CLASS
+/**
+ * Reflection Guard for [WindowLayoutComponent].
+ * This will go through the [WindowLayoutComponent]'s method by reflection and
+ * check each method's name and signature to see if the interface is what we required.
+ */
internal class SafeWindowLayoutComponentProvider(
private val loader: ClassLoader,
private val consumerAdapter: ConsumerAdapter
@@ -44,14 +60,53 @@
}
private fun canUseWindowLayoutComponent(): Boolean {
- return isWindowLayoutProviderValid() &&
- isWindowExtensionsValid() &&
- isWindowLayoutComponentValid() &&
- isFoldingFeatureValid()
+ if (!isWindowExtensionsPresent() || !isWindowExtensionsValid() ||
+ !isWindowLayoutProviderValid() ||
+ !isFoldingFeatureValid()
+ ) {
+ return false
+ }
+ // TODO(b/267831038): can fallback to VendorApiLevel1 when level2 is not match
+ // but level 1 is matched
+ return when (ExtensionsUtil.safeVendorApiLevel) {
+ 1 -> hasValidVendorApiLevel1()
+ in 2..Int.MAX_VALUE -> hasValidVendorApiLevel2()
+ // TODO(b/267956499): add hasValidVendorApiLevel3
+ else -> false
+ }
}
- private fun isWindowLayoutProviderValid(): Boolean {
- return validate {
+ private fun isWindowExtensionsPresent(): Boolean {
+ return checkIsPresent {
+ loader.loadClass(WINDOW_EXTENSIONS_PROVIDER_CLASS)
+ }
+ }
+
+ /**
+ * [WindowExtensions.VENDOR_API_LEVEL_1] includes the following methods
+ * - [WindowLayoutComponent.addWindowLayoutInfoListener] with [Activity] and
+ * [java.util.function.Consumer]
+ * - [WindowLayoutComponent.removeWindowLayoutInfoListener] with [java.util.function.Consumer]
+ */
+ private fun hasValidVendorApiLevel1(): Boolean {
+ return isMethodWindowLayoutInfoListenerJavaConsumerValid()
+ }
+
+ /**
+ * [WindowExtensions.VENDOR_API_LEVEL_2] includes the following methods
+ * - [WindowLayoutComponent.addWindowLayoutInfoListener] with [Context] and
+ * [java.util.function.Consumer]
+ * - [WindowLayoutComponent.addWindowLayoutInfoListener] with [Context] and [Consumer]
+ * - [WindowLayoutComponent.removeWindowLayoutInfoListener] with [Consumer]
+ */
+ private fun hasValidVendorApiLevel2(): Boolean {
+ return hasValidVendorApiLevel1() &&
+ isMethodWindowLayoutInfoListenerJavaConsumerUiContextValid() &&
+ isMethodWindowLayoutInfoListenerWindowConsumerValid()
+ }
+
+ private fun isWindowExtensionsValid(): Boolean {
+ return validateReflection("WindowExtensionsProvider#getWindowExtensions is not valid") {
val providerClass = windowExtensionsProviderClass
val getWindowExtensionsMethod = providerClass.getDeclaredMethod("getWindowExtensions")
val windowExtensionsClass = windowExtensionsClass
@@ -60,8 +115,8 @@
}
}
- private fun isWindowExtensionsValid(): Boolean {
- return validate {
+ private fun isWindowLayoutProviderValid(): Boolean {
+ return validateReflection("WindowExtensions#getWindowLayoutComponent is not valid") {
val extensionsClass = windowExtensionsClass
val getWindowLayoutComponentMethod =
extensionsClass.getMethod("getWindowLayoutComponent")
@@ -72,7 +127,7 @@
}
private fun isFoldingFeatureValid(): Boolean {
- return validate {
+ return validateReflection("FoldingFeature class is not valid") {
val foldingFeatureClass = foldingFeatureClass
val getBoundsMethod = foldingFeatureClass.getMethod("getBounds")
val getTypeMethod = foldingFeatureClass.getMethod("getType")
@@ -86,9 +141,13 @@
}
}
- private fun isWindowLayoutComponentValid(): Boolean {
- return validate {
- val consumerClass = consumerAdapter.consumerClassOrNull() ?: return@validate false
+ private fun isMethodWindowLayoutInfoListenerJavaConsumerValid(): Boolean {
+ return validateReflection(
+ "WindowLayoutComponent#addWindowLayoutInfoListener(" +
+ "${Activity::class.java.name}, $JAVA_CONSUMER) is not valid"
+ ) {
+ val consumerClass =
+ consumerAdapter.consumerClassOrNull() ?: return@validateReflection false
val windowLayoutComponent = windowLayoutComponentClass
val addListenerMethod = windowLayoutComponent
.getMethod(
@@ -102,46 +161,59 @@
}
}
- private fun validate(block: () -> Boolean): Boolean {
- return try {
- block()
- } catch (noClass: ClassNotFoundException) {
- false
- } catch (noMethod: NoSuchMethodException) {
- false
+ private fun isMethodWindowLayoutInfoListenerWindowConsumerValid(): Boolean {
+ return validateReflection(
+ "WindowLayoutComponent#addWindowLayoutInfoListener" +
+ "(${Context::class.java.name}, $WINDOW_CONSUMER) is not valid"
+ ) {
+ val windowLayoutComponent = windowLayoutComponentClass
+ val addListenerMethod = windowLayoutComponent
+ .getMethod(
+ "addWindowLayoutInfoListener",
+ Context::class.java,
+ Consumer::class.java
+ )
+ val removeListenerMethod = windowLayoutComponent
+ .getMethod("removeWindowLayoutInfoListener", Consumer::class.java)
+ addListenerMethod.isPublic && removeListenerMethod.isPublic
}
}
- private val Method.isPublic: Boolean
- get() {
- return Modifier.isPublic(modifiers)
+ private fun isMethodWindowLayoutInfoListenerJavaConsumerUiContextValid(): Boolean {
+ return validateReflection(
+ "WindowLayoutComponent#addWindowLayoutInfoListener" +
+ "(${Context::class.java.name}, $JAVA_CONSUMER) is not valid"
+ ) {
+ val consumerClass =
+ consumerAdapter.consumerClassOrNull() ?: return@validateReflection false
+ val windowLayoutComponent = windowLayoutComponentClass
+ val addListenerMethod = windowLayoutComponent
+ .getMethod(
+ "addWindowLayoutInfoListener",
+ Context::class.java,
+ consumerClass
+ )
+ addListenerMethod.isPublic
}
-
- private fun Method.doesReturn(clazz: KClass<*>): Boolean {
- return doesReturn(clazz.java)
- }
-
- private fun Method.doesReturn(clazz: Class<*>): Boolean {
- return returnType.equals(clazz)
}
private val windowExtensionsProviderClass: Class<*>
get() {
- return loader.loadClass("androidx.window.extensions.WindowExtensionsProvider")
+ return loader.loadClass(WINDOW_EXTENSIONS_PROVIDER_CLASS)
}
private val windowExtensionsClass: Class<*>
get() {
- return loader.loadClass("androidx.window.extensions.WindowExtensions")
+ return loader.loadClass(WINDOW_EXTENSIONS_CLASS)
}
private val foldingFeatureClass: Class<*>
get() {
- return loader.loadClass("androidx.window.extensions.layout.FoldingFeature")
+ return loader.loadClass(FOLDING_FEATURE_CLASS)
}
private val windowLayoutComponentClass: Class<*>
get() {
- return loader.loadClass("androidx.window.extensions.layout.WindowLayoutComponent")
+ return loader.loadClass(WINDOW_LAYOUT_COMPONENT_CLASS)
}
}
diff --git a/window/window/src/main/java/androidx/window/layout/WindowInfoTracker.kt b/window/window/src/main/java/androidx/window/layout/WindowInfoTracker.kt
index 242217a..8af11e0 100644
--- a/window/window/src/main/java/androidx/window/layout/WindowInfoTracker.kt
+++ b/window/window/src/main/java/androidx/window/layout/WindowInfoTracker.kt
@@ -24,6 +24,7 @@
import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
import androidx.annotation.UiContext
import androidx.window.core.ConsumerAdapter
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.adapter.WindowBackend
import androidx.window.layout.adapter.extensions.ExtensionWindowLayoutInfoBackend
import androidx.window.layout.adapter.sidecar.SidecarWindowBackend
@@ -61,6 +62,7 @@
* @throws NotImplementedError when [Context] is not an [UiContext] or this method has no
* supporting implementation.
*/
+ @ExperimentalWindowApi
fun windowLayoutInfo(@UiContext context: Context): Flow<WindowLayoutInfo> {
val windowLayoutInfoFlow: Flow<WindowLayoutInfo>? = windowLayoutInfo((context as Activity))
return windowLayoutInfoFlow
diff --git a/window/window/src/main/java/androidx/window/layout/WindowInfoTrackerImpl.kt b/window/window/src/main/java/androidx/window/layout/WindowInfoTrackerImpl.kt
index 0796437..2247c4b 100644
--- a/window/window/src/main/java/androidx/window/layout/WindowInfoTrackerImpl.kt
+++ b/window/window/src/main/java/androidx/window/layout/WindowInfoTrackerImpl.kt
@@ -20,6 +20,7 @@
import android.content.Context
import androidx.annotation.UiContext
import androidx.core.util.Consumer
+import androidx.window.core.ExperimentalWindowApi
import androidx.window.layout.adapter.WindowBackend
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -41,6 +42,7 @@
* A [Flow] of window layout changes in the current visual [UiContext]. A context has to be
* either an [Activity] or created with [Context#createWindowContext].
*/
+ @ExperimentalWindowApi
override fun windowLayoutInfo(@UiContext context: Context): Flow<WindowLayoutInfo> {
return callbackFlow {
val listener = Consumer { info: WindowLayoutInfo -> trySend(info) }
diff --git a/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt b/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt
new file mode 100644
index 0000000..326486e
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 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.reflection
+
+import android.util.Log
+import java.lang.reflect.Method
+import java.lang.reflect.Modifier
+import kotlin.reflect.KClass
+
+/**
+ * Utility class used for reflection guard for WindowExtensions classes' validation
+ */
+internal object ReflectionUtils {
+
+ internal fun checkIsPresent(classLoader: () -> Class<*>): Boolean {
+ return try {
+ classLoader()
+ true
+ } catch (noClass: ClassNotFoundException) {
+ false
+ } catch (noDefinition: NoClassDefFoundError) {
+ false
+ }
+ }
+
+ /**
+ * Validates the code block normally for reflection. If there are [ClassNotFoundException]
+ * or [NoSuchMethodException] thrown, validation will fail.
+ * Otherwise will return the validation result from the [block]
+ */
+ @JvmStatic
+ internal fun validateReflection(errorMessage: String? = null, block: () -> Boolean): Boolean {
+ return try {
+ val result = block()
+ if (!result && errorMessage != null) {
+ Log.e("ReflectionGuard", errorMessage)
+ }
+ result
+ } catch (noClass: ClassNotFoundException) {
+ Log.e("ReflectionGuard", "ClassNotFound: ${errorMessage.orEmpty()}")
+ false
+ } catch (noMethod: NoSuchMethodException) {
+ Log.e("ReflectionGuard", "NoSuchMethod: ${errorMessage.orEmpty()}")
+ false
+ }
+ }
+
+ /**
+ * Checks if a method has public modifier
+ */
+ internal val Method.isPublic: Boolean
+ get() {
+ return Modifier.isPublic(modifiers)
+ }
+
+ /**
+ * Checks if a method's return value is type of kotlin [clazz]
+ */
+ internal fun Method.doesReturn(clazz: KClass<*>): Boolean {
+ return doesReturn(clazz.java)
+ }
+
+ /**
+ * Checks if a method's return value is type of java [clazz]
+ */
+ internal fun Method.doesReturn(clazz: Class<*>): Boolean {
+ return returnType.equals(clazz)
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/reflection/WindowExtensionsConstants.kt b/window/window/src/main/java/androidx/window/reflection/WindowExtensionsConstants.kt
new file mode 100644
index 0000000..341e019
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/reflection/WindowExtensionsConstants.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2023 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.reflection
+
+/**
+ * Constants for WindowExtensions
+ */
+internal object WindowExtensionsConstants {
+ /**
+ * Constant name for package [androidx.window.extensions]
+ */
+ private const val WINDOW_EXTENSIONS_PACKAGE_NAME = "androidx.window.extensions"
+
+ /**
+ * Constant name for class [androidx.window.extensions.WindowExtensionsProvider] used
+ * for reflection
+ */
+ internal const val WINDOW_EXTENSIONS_PROVIDER_CLASS =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.WindowExtensionsProvider"
+
+ /**
+ * Constant name for class [androidx.window.extensions.WindowExtensions] used for reflection
+ */
+ internal const val WINDOW_EXTENSIONS_CLASS =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.WindowExtensions"
+
+ /**
+ * Constant name for class [androidx.window.extensions.layout.FoldingFeature]
+ * used for reflection
+ */
+ internal const val FOLDING_FEATURE_CLASS =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.layout.FoldingFeature"
+
+ /**
+ * Constant name for class [androidx.window.extensions.layout.WindowLayoutComponent]
+ * used for reflection
+ */
+ internal const val WINDOW_LAYOUT_COMPONENT_CLASS =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.layout.WindowLayoutComponent"
+
+ /**
+ * Constant name for class [androidx.window.extensions.embedding.ActivityEmbeddingComponent]
+ * used for reflection
+ */
+ internal const val ACTIVITY_EMBEDDING_COMPONENT_CLASS =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.embedding.ActivityEmbeddingComponent"
+
+ /**
+ * Constant name for class [androidx.window.extensions.core.util.function]
+ * used for reflection
+ */
+ internal const val WINDOW_CONSUMER =
+ "$WINDOW_EXTENSIONS_PACKAGE_NAME.core.util.function.Consumer"
+
+ /**
+ * Constant name for class [java.util.function.Consumer]
+ * used for reflection
+ */
+ internal const val JAVA_CONSUMER = "java.util.function.Consumer"
+}
diff --git a/window/window/src/main/res/values/attrs.xml b/window/window/src/main/res/values/attrs.xml
index 8ee9802..a2880ca 100644
--- a/window/window/src/main/res/values/attrs.xml
+++ b/window/window/src/main/res/values/attrs.xml
@@ -47,8 +47,9 @@
<attr name="tag" format="string" />
<!-- An attribute for Activity Embedding rules.
Background color of Activity Embedding window animation if the animation requires a
- background.
- The default is to use the theme's windowBackground. -->
+ background. Only opaque color is supported.
+ The default is to use the current theme's windowBackground. Any non-opaque color will be
+ treated the same as default. -->
<attr name="animationBackgroundColor" format="color" />
<!-- An attribute for Activity Embedding rules.
diff --git a/window/window/src/test/java/androidx/window/area/WindowAreaAdapterUnitTest.kt b/window/window/src/test/java/androidx/window/area/WindowAreaAdapterUnitTest.kt
new file mode 100644
index 0000000..89a9808
--- /dev/null
+++ b/window/window/src/test/java/androidx/window/area/WindowAreaAdapterUnitTest.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.area
+
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.extensions.area.WindowAreaComponent
+import org.junit.Test
+
+/**
+ * Unit tests for [WindowAreaAdapter] that run on the JVM.
+ */
+@OptIn(ExperimentalWindowApi::class)
+class WindowAreaAdapterUnitTest {
+
+ @Test
+ fun testWindowAreaStatusTranslateValueAvailable() {
+ val expected = WindowAreaStatus.AVAILABLE
+ val translateValue = WindowAreaAdapter.translate(WindowAreaComponent.STATUS_AVAILABLE)
+ assert(expected == translateValue)
+ }
+
+ @Test
+ fun testWindowAreaStatusTranslateValueUnavailable() {
+ val expected = WindowAreaStatus.UNAVAILABLE
+ val translateValue = WindowAreaAdapter.translate(WindowAreaComponent.STATUS_UNAVAILABLE)
+ assert(expected == translateValue)
+ }
+
+ @Test
+ fun testWindowAreaStatusTranslateValueUnsupported() {
+ val expected = WindowAreaStatus.UNSUPPORTED
+ val translateValue = WindowAreaAdapter.translate(WindowAreaComponent.STATUS_UNSUPPORTED)
+ assert(expected == translateValue)
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/test/java/androidx/window/embedding/EmbeddingAspectRatioTest.kt b/window/window/src/test/java/androidx/window/embedding/EmbeddingAspectRatioTest.kt
new file mode 100644
index 0000000..fc5fb0c
--- /dev/null
+++ b/window/window/src/test/java/androidx/window/embedding/EmbeddingAspectRatioTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2023 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 org.junit.Assert.assertEquals
+import org.junit.Assert.assertThrows
+import org.junit.Test
+
+/**
+ * The unit tests for [EmbeddingAspectRatio].
+ */
+class EmbeddingAspectRatioTest {
+
+ @Test
+ fun testRatio() {
+ // ratio must > 1.
+ assertThrows(IllegalArgumentException::class.java) {
+ EmbeddingAspectRatio.ratio(0f)
+ }
+ assertThrows(IllegalArgumentException::class.java) {
+ EmbeddingAspectRatio.ratio(1f)
+ }
+
+ // test equals and value.
+ assertEquals(EmbeddingAspectRatio.ratio(1.1f), EmbeddingAspectRatio.ratio(1.1f))
+ assertEquals(1.1f, EmbeddingAspectRatio.ratio(1.1f).value)
+ }
+
+ @Test
+ fun testAlwaysAllow() {
+ assertEquals(0f, EmbeddingAspectRatio.ALWAYS_ALLOW.value)
+ }
+
+ @Test
+ fun testAlwaysDisallow() {
+ assertEquals(-1f, EmbeddingAspectRatio.ALWAYS_DISALLOW.value)
+ }
+
+ @Test
+ fun testBuildAspectRatioFromValue() {
+ assertEquals(
+ EmbeddingAspectRatio.ALWAYS_ALLOW,
+ EmbeddingAspectRatio.buildAspectRatioFromValue(0f)
+ )
+ assertEquals(
+ EmbeddingAspectRatio.ALWAYS_DISALLOW,
+ EmbeddingAspectRatio.buildAspectRatioFromValue(-1f)
+ )
+ assertEquals(
+ EmbeddingAspectRatio.ratio(1.1f),
+ EmbeddingAspectRatio.buildAspectRatioFromValue(1.1f)
+ )
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/test/java/androidx/window/reflection/ReflectionUtilsTest.kt b/window/window/src/test/java/androidx/window/reflection/ReflectionUtilsTest.kt
new file mode 100644
index 0000000..bdab6f7
--- /dev/null
+++ b/window/window/src/test/java/androidx/window/reflection/ReflectionUtilsTest.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2023 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.reflection
+
+import androidx.window.reflection.ReflectionUtils.doesReturn
+import androidx.window.reflection.ReflectionUtils.isPublic
+import androidx.window.reflection.ReflectionUtils.validateReflection
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Unit test for reflection utilities
+ */
+class ReflectionUtilsTest {
+
+ private lateinit var classLoader: ClassLoader
+
+ @Before
+ fun setup() {
+ classLoader = this::class.java.classLoader!!
+ }
+
+ @Test
+ fun testValidateReflectionSuccess() {
+ val result = validateReflection {
+ true
+ }
+ assertTrue(result)
+ }
+
+ @Test
+ fun testValidateReflectionFail() {
+ val result = validateReflection {
+ classLoader.loadClass("SomeUnExistedClass.java")
+ true
+ }
+ assertFalse(result)
+ }
+
+ @Test
+ fun testMethodModifier() {
+ val result = validateReflection {
+ val testClass = this::class.java
+ val privateMethod = testClass.getDeclaredMethod("testMethod").isPublic
+ assertFalse(privateMethod)
+ val publicMethod = testClass.getDeclaredMethod("testMethodModifier").isPublic
+ assertTrue(publicMethod)
+ true
+ }
+ assertTrue(result)
+ }
+
+ @Test
+ fun testDoesReturn() {
+ val result = validateReflection {
+ val testClass = this::class.java
+ val privateMethod = testClass.getDeclaredMethod("testMethod")
+ assertTrue(privateMethod.doesReturn(Int::class.java))
+ assertTrue(privateMethod.doesReturn(Int::class))
+ assertFalse(privateMethod.doesReturn(Any::class.java))
+ assertFalse(privateMethod.doesReturn(Any::class))
+ true
+ }
+ assertTrue(result)
+ }
+
+ // method for testing
+ @Suppress("unused")
+ private fun testMethod(): Int {
+ return 0
+ }
+}
\ No newline at end of file
diff --git a/work/work-lint/src/main/java/androidx/work/lint/WorkManagerIssueRegistry.kt b/work/work-lint/src/main/java/androidx/work/lint/WorkManagerIssueRegistry.kt
index ac9972b..28e0e2f 100644
--- a/work/work-lint/src/main/java/androidx/work/lint/WorkManagerIssueRegistry.kt
+++ b/work/work-lint/src/main/java/androidx/work/lint/WorkManagerIssueRegistry.kt
@@ -25,7 +25,7 @@
class WorkManagerIssueRegistry : IssueRegistry() {
override val minApi = CURRENT_API
- override val api = 14
+ override val api = 13
override val issues: List<Issue> = listOf(
BadConfigurationProviderIssueDetector.ISSUE,
IdleBatteryChargingConstraintsDetector.ISSUE,
diff --git a/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerRealExecutorTest.kt b/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerRealExecutorTest.kt
index 848dd44..78b5732 100644
--- a/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerRealExecutorTest.kt
+++ b/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerRealExecutorTest.kt
@@ -29,8 +29,10 @@
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
+import androidx.work.WorkInfo.State.ENQUEUED
import androidx.work.impl.WorkManagerImpl
import androidx.work.impl.model.WorkSpec
+import androidx.work.impl.utils.taskexecutor.SerialExecutor
import androidx.work.testing.workers.CountingTestWorker
import androidx.work.testing.workers.RetryWorker
import androidx.work.testing.workers.TestWorker
@@ -81,13 +83,14 @@
// TODO: specifically removing deduplication for periodic workers
// so runs aren't dedupped. We need periodicity data in workinfo
val workInfo = wm.workDatabase.workSpecDao().getWorkStatusPojoLiveDataForIds(
- listOf("${request.id}"))
+ listOf("${request.id}")
+ )
var expectedCounter = 1
val maxCount = 5
handler.post {
workInfo.observeForever {
val info = it.first()
- val isEnqueued = info.state == WorkInfo.State.ENQUEUED
+ val isEnqueued = info.state == ENQUEUED
val counter = CountingTestWorker.COUNT.get()
if (isEnqueued && counter == maxCount) {
periodicLatch.countDown()
@@ -107,6 +110,10 @@
wm.enqueue(request).result.get()
driver.setInitialDelayMet(request.id)
awaitPeriodicRunOnce(request.id)
+ driver.setPeriodDelayMet(request.id)
+ awaitCondition(request.id) {
+ it.state == WorkInfo.State.ENQUEUED && CountingTestWorker.COUNT.get() == 2
+ }
}
@Test
@@ -160,6 +167,30 @@
}
@Test
+ fun testSetAllConstraintsDontTriggerSecondRun() {
+ val request = PeriodicWorkRequestBuilder<CountingTestWorker>(10, TimeUnit.DAYS)
+ .setConstraints(Constraints(requiresCharging = true)).build()
+ wm.enqueue(request).result.get()
+ val latch = CountDownLatch(1)
+ wm.workTaskExecutor.serialTaskExecutor.execute {
+ latch.await()
+ }
+ // double call to setAllConstraint. It shouldn't lead to double execution of worker.
+ // It should run once, but second time it shouldn't run because "setPeriodDelayMet" wasn't
+ // called.
+ driver.setAllConstraintsMet(request.id)
+ driver.setAllConstraintsMet(request.id)
+ latch.countDown()
+ awaitCondition(request.id) {
+ it.state == ENQUEUED && CountingTestWorker.COUNT.get() > 0
+ }
+
+ drainSerialExecutor()
+ assertThat(wm.getWorkInfoById(request.id).get().state).isEqualTo(ENQUEUED)
+ assertThat(CountingTestWorker.COUNT.get()).isEqualTo(1)
+ }
+
+ @Test
fun testOneTimeWorkerRetry() {
val request = OneTimeWorkRequest.from(RetryWorker::class.java)
wm.enqueue(request).result.get()
@@ -176,11 +207,11 @@
private fun awaitSuccess(id: UUID) = awaitCondition(id) { it.state == WorkInfo.State.SUCCEEDED }
private fun awaitPeriodicRunOnce(id: UUID) = awaitCondition(id) {
- it.state == WorkInfo.State.ENQUEUED && CountingTestWorker.COUNT.get() == 1
+ it.state == ENQUEUED && CountingTestWorker.COUNT.get() == 1
}
private fun awaitReenqueuedAfterRetry(id: UUID) = awaitCondition(id) {
- it.state == WorkInfo.State.ENQUEUED && it.runAttemptCount == 1
+ it.state == ENQUEUED && it.runAttemptCount == 1
}
private fun awaitCondition(id: UUID, predicate: (WorkSpec.WorkInfoPojo) -> Boolean) {
@@ -198,4 +229,22 @@
}
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue()
}
+
+ private fun drainSerialExecutor() {
+ val latch = CountDownLatch(1)
+
+ class DrainTask(val executor: SerialExecutor) : Runnable {
+ override fun run() {
+ if (executor.hasPendingTasks()) {
+ executor.execute(this)
+ } else {
+ latch.countDown()
+ }
+ }
+ }
+
+ val executor = wm.workTaskExecutor.serialTaskExecutor
+ executor.execute(DrainTask(executor))
+ latch.await()
+ }
}
\ No newline at end of file
diff --git a/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerTest.java b/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerTest.java
index 83f6878..2e44ffd 100644
--- a/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerTest.java
+++ b/work/work-testing/src/androidTest/java/androidx/work/testing/TestSchedulerTest.java
@@ -198,6 +198,8 @@
assertThat(CountingTestWorker.COUNT.get(), is(0));
mTestDriver.setInitialDelayMet(request.getId());
assertThat(CountingTestWorker.COUNT.get(), is(1));
+ mTestDriver.setPeriodDelayMet(request.getId());
+ assertThat(CountingTestWorker.COUNT.get(), is(2));
}
@Test
diff --git a/work/work-testing/src/main/java/androidx/work/testing/TestScheduler.kt b/work/work-testing/src/main/java/androidx/work/testing/TestScheduler.kt
index 7369589..84d9918 100644
--- a/work/work-testing/src/main/java/androidx/work/testing/TestScheduler.kt
+++ b/work/work-testing/src/main/java/androidx/work/testing/TestScheduler.kt
@@ -23,7 +23,6 @@
import androidx.work.impl.StartStopTokens
import androidx.work.impl.WorkDatabase
import androidx.work.impl.WorkManagerImpl
-import androidx.work.impl.model.WorkGenerationalId
import androidx.work.impl.model.WorkSpec
import androidx.work.impl.model.WorkSpecDao
import androidx.work.impl.model.generationalId
@@ -52,25 +51,19 @@
val toSchedule = mutableMapOf<WorkSpec, InternalWorkState>()
synchronized(lock) {
workSpecs.forEach {
- val state = pendingWorkStates.getOrPut(it.generationalId().workSpecId) {
- InternalWorkState(it, true)
- }
- toSchedule[it] = state.copy(isScheduled = true)
+ val oldState = pendingWorkStates[it.id] ?: InternalWorkState()
+ val state = oldState.copy(isScheduled = true)
+ pendingWorkStates[it.id] = state
+ toSchedule[it] = state
}
}
- toSchedule.forEach { (originalSpec, state) ->
- // this spec is attempted to run for the first time
- // so we have to rewind the time, because we have to override flex.
- val spec = if (originalSpec.isPeriodic && state.periodDelayMet) {
- workManagerImpl.rewindLastEnqueueTime(originalSpec.id)
- } else originalSpec
+ toSchedule.forEach { (spec, state) ->
// don't even try to run a worker that WorkerWrapper won't execute anyway.
// similar to logic in WorkerWrapper
- if ((spec.isPeriodic || spec.isBackedOff) &&
- (spec.calculateNextRunTime() > System.currentTimeMillis())) {
+ if (spec.isBackedOff && spec.calculateNextRunTime() > System.currentTimeMillis()) {
return@forEach
}
- scheduleInternal(spec.generationalId(), state)
+ scheduleInternal(spec, state)
}
}
@@ -95,11 +88,11 @@
val spec = loadSpec(id)
val state: InternalWorkState
synchronized(lock) {
- val oldState = pendingWorkStates[id] ?: InternalWorkState(spec, false)
+ val oldState = pendingWorkStates[id] ?: InternalWorkState(initialDelayMet = false)
state = oldState.copy(constraintsMet = true)
pendingWorkStates[id] = state
}
- scheduleInternal(WorkGenerationalId(id, state.generation), state)
+ scheduleInternal(spec, state)
}
/**
@@ -114,12 +107,11 @@
val state: InternalWorkState
val spec = loadSpec(id)
synchronized(lock) {
- val oldState = pendingWorkStates[id] ?: InternalWorkState(spec, false)
+ val oldState = pendingWorkStates[id] ?: InternalWorkState()
state = oldState.copy(initialDelayMet = true)
pendingWorkStates[id] = state
}
- workManagerImpl.rewindLastEnqueueTime(id)
- scheduleInternal(WorkGenerationalId(id, state.generation), state)
+ scheduleInternal(spec, state)
}
/**
@@ -136,20 +128,21 @@
val state: InternalWorkState
synchronized(lock) {
- val oldState = pendingWorkStates[id] ?: InternalWorkState(spec, false)
+ val oldState = pendingWorkStates[id] ?: InternalWorkState()
state = oldState.copy(periodDelayMet = true)
pendingWorkStates[id] = state
}
- workManagerImpl.rewindLastEnqueueTime(id)
- scheduleInternal(WorkGenerationalId(id, state.generation), state)
+ scheduleInternal(spec, state)
}
- private fun scheduleInternal(generationalId: WorkGenerationalId, state: InternalWorkState) {
- if (state.isRunnable) {
+ private fun scheduleInternal(spec: WorkSpec, state: InternalWorkState) {
+ val generationalId = spec.generationalId()
+ if (isRunnable(spec, state)) {
val token = synchronized(lock) {
pendingWorkStates.remove(generationalId.workSpecId)
startStopTokens.tokenFor(generationalId)
}
+ workManagerImpl.rewindLastEnqueueTime(spec.id)
workManagerImpl.startWork(token)
}
}
@@ -162,29 +155,21 @@
}
internal data class InternalWorkState(
- val generation: Int,
- val constraintsMet: Boolean,
- val initialDelayMet: Boolean,
- val periodDelayMet: Boolean,
- val hasConstraints: Boolean,
- val isPeriodic: Boolean,
+ val constraintsMet: Boolean = false,
+ val initialDelayMet: Boolean = false,
+ val periodDelayMet: Boolean = false,
/* means that TestScheduler received this workrequest in schedule(....) function */
- val isScheduled: Boolean
+ val isScheduled: Boolean = false,
)
-internal val InternalWorkState.isRunnable: Boolean
- get() = constraintsMet && initialDelayMet && periodDelayMet && isScheduled
+internal fun isRunnable(spec: WorkSpec, state: InternalWorkState): Boolean {
+ val constraints = !spec.hasConstraints() || state.constraintsMet
+ val initialDelay = spec.initialDelay == 0L || state.initialDelayMet || !spec.isFirstPeriodicRun
+ val periodic = if (spec.isPeriodic) (state.periodDelayMet || spec.isFirstPeriodicRun) else true
+ return state.isScheduled && constraints && periodic && initialDelay
+}
-internal fun InternalWorkState(spec: WorkSpec, isScheduled: Boolean): InternalWorkState =
- InternalWorkState(
- generation = spec.generation,
- constraintsMet = !spec.hasConstraints(),
- initialDelayMet = spec.initialDelay == 0L,
- periodDelayMet = spec.periodCount == 0 && spec.runAttemptCount == 0,
- hasConstraints = spec.hasConstraints(),
- isPeriodic = spec.isPeriodic,
- isScheduled = isScheduled,
- )
+private val WorkSpec.isFirstPeriodicRun get() = periodCount == 0 && runAttemptCount == 0
private fun WorkManagerImpl.rewindLastEnqueueTime(id: String): WorkSpec {
// We need to pass check that mWorkSpec.calculateNextRunTime() < now