Merge "PreTest camera for extension tests" into androidx-master-dev
diff --git a/appcompat/appcompat/src/androidTest/AndroidManifest.xml b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
index 9d3d665..9af9433 100644
--- a/appcompat/appcompat/src/androidTest/AndroidManifest.xml
+++ b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
@@ -125,6 +125,11 @@
android:theme="@style/Theme.AppCompat.Light"/>
<activity
+ android:name="androidx.appcompat.widget.AppCompatIconsActivity"
+ android:label="@string/app_compat_icons_activity"
+ android:theme="@style/Theme.AppCompat.Light"/>
+
+ <activity
android:name="androidx.appcompat.widget.AppCompatRadioButtonActivity"
android:label="@string/app_compat_radio_button_activity"
android:theme="@style/Theme.AppCompat.Light"/>
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsActivity.java b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsActivity.java
new file mode 100644
index 0000000..5e1f331
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.appcompat.widget;
+
+import androidx.appcompat.test.R;
+import androidx.appcompat.testutils.BaseTestActivity;
+
+public class AppCompatIconsActivity extends BaseTestActivity {
+ @Override
+ protected int getContentViewLayoutResId() {
+ return R.layout.appcompat_icons_activity;
+ }
+}
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsTest.kt
new file mode 100644
index 0000000..37a1584
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatIconsTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020 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.appcompat.widget
+
+import android.util.TypedValue
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.appcompat.test.R
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Assert.assertNotNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class AppCompatIconsTest {
+ @get:Rule
+ val activityRule = ActivityScenarioRule(AppCompatIconsActivity::class.java)
+
+ private lateinit var activityScenario: ActivityScenario<AppCompatIconsActivity>
+
+ @Before
+ fun setup() {
+ activityScenario = ActivityScenario.launch(AppCompatIconsActivity::class.java)
+ }
+
+ @Test
+ fun testActionModeIconsOnImageView() {
+ // Tests that the app:scrCompat attribute set to ?attr/actionModeXYZDrawable gets
+ // resolved to non-null drawables
+ activityScenario.onActivity {
+ val imageViewCut = it.findViewById<AppCompatImageView>(R.id.icon_cut)
+ val imageViewCopy = it.findViewById<AppCompatImageView>(R.id.icon_copy)
+ val imageViewPaste = it.findViewById<AppCompatImageView>(R.id.icon_paste)
+ val imageViewSelectAll = it.findViewById<AppCompatImageView>(R.id.icon_selectall)
+ val imageViewShare = it.findViewById<AppCompatImageView>(R.id.icon_share)
+
+ assertNotNull(imageViewCut.drawable)
+ assertNotNull(imageViewCopy.drawable)
+ assertNotNull(imageViewPaste.drawable)
+ assertNotNull(imageViewSelectAll.drawable)
+ assertNotNull(imageViewShare.drawable)
+ }
+ }
+
+ @Test
+ fun testActionModeIconsFromAppCompatResources() {
+ // Tests that we can resolve R.attr.actionModeXYZDrawable to a non-null drawable
+ // from our activity's theme
+
+ activityScenario.onActivity {
+ // Resolve ?attr/actionModeCutDrawable
+ val typedValueCut = TypedValue()
+ it.theme.resolveAttribute(
+ androidx.appcompat.R.attr.actionModeCutDrawable, typedValueCut, true
+ )
+ val drawableCut = AppCompatResources.getDrawable(it, typedValueCut.resourceId)
+ assertNotNull(drawableCut)
+
+ // Resolve ?attr/actionModeCopyDrawable
+ val typedValueCopy = TypedValue()
+ it.theme.resolveAttribute(
+ androidx.appcompat.R.attr.actionModeCopyDrawable, typedValueCopy, true
+ )
+ val drawableCopy = AppCompatResources.getDrawable(it, typedValueCopy.resourceId)
+ assertNotNull(drawableCopy)
+
+ // Resolve ?attr/actionModePasteDrawable
+ val typedValuePaste = TypedValue()
+ it.theme.resolveAttribute(
+ androidx.appcompat.R.attr.actionModePasteDrawable, typedValuePaste, true
+ )
+ val drawablePaste = AppCompatResources.getDrawable(it, typedValuePaste.resourceId)
+ assertNotNull(drawablePaste)
+
+ // Resolve ?attr/actionModeSelectAllDrawable
+ val typedValueSelectAll = TypedValue()
+ it.theme.resolveAttribute(
+ androidx.appcompat.R.attr.actionModeSelectAllDrawable, typedValueSelectAll, true
+ )
+ val drawableSelectAll =
+ AppCompatResources.getDrawable(it, typedValueSelectAll.resourceId)
+ assertNotNull(drawableSelectAll)
+
+ // Resolve ?attr/actionModeShareDrawable
+ val typedValueShare = TypedValue()
+ it.theme.resolveAttribute(
+ androidx.appcompat.R.attr.actionModeShareDrawable, typedValueShare, true
+ )
+ val drawableShare = AppCompatResources.getDrawable(it, typedValueShare.resourceId)
+ assertNotNull(drawableShare)
+ }
+ }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat/src/androidTest/res/layout/appcompat_icons_activity.xml b/appcompat/appcompat/src/androidTest/res/layout/appcompat_icons_activity.xml
new file mode 100644
index 0000000..e4a95ce
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/res/layout/appcompat_icons_activity.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/icon_cut"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeCutDrawable" />
+
+ <ImageView
+ android:id="@+id/icon_copy"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeCopyDrawable" />
+
+ <ImageView
+ android:id="@+id/icon_paste"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModePasteDrawable" />
+
+ <ImageView
+ android:id="@+id/icon_selectall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeSelectAllDrawable" />
+
+ <ImageView
+ android:id="@+id/icon_share"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeShareDrawable" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/appcompat/appcompat/src/androidTest/res/values/strings.xml b/appcompat/appcompat/src/androidTest/res/values/strings.xml
index 21d1659..19145b8 100644
--- a/appcompat/appcompat/src/androidTest/res/values/strings.xml
+++ b/appcompat/appcompat/src/androidTest/res/values/strings.xml
@@ -67,6 +67,7 @@
<string name="app_compat_checkbox_activity">AppCompat checkbox</string>
<string name="app_compat_radio_button_activity">AppCompat radio button</string>
<string name="app_compat_toggle_button_activity">AppCompat toggle button</string>
+ <string name="app_compat_icons_activity">AppCompat icons</string>
<string name="switch_compat_activity">Switch compat</string>
<string-array name="planets_array">
<item>Mercury</item>
diff --git a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_copy_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_copy_mtrl_am_alpha.png
deleted file mode 100644
index 706fc1f..0000000
--- a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_copy_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_cut_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_cut_mtrl_alpha.png
deleted file mode 100644
index e78bcaf..0000000
--- a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_cut_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_paste_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_paste_mtrl_am_alpha.png
deleted file mode 100644
index 8610c50..0000000
--- a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_paste_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_selectall_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_selectall_mtrl_alpha.png
deleted file mode 100644
index 63d0e5d..0000000
--- a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_selectall_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_share_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_share_mtrl_alpha.png
deleted file mode 100644
index cd1f57c..0000000
--- a/appcompat/appcompat/src/main/res/drawable-hdpi/abc_ic_menu_share_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_copy_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_copy_mtrl_am_alpha.png
deleted file mode 100644
index 559b835..0000000
--- a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_copy_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_cut_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_cut_mtrl_alpha.png
deleted file mode 100644
index a282219..0000000
--- a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_cut_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_paste_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_paste_mtrl_am_alpha.png
deleted file mode 100644
index 1492ab6..0000000
--- a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_paste_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_selectall_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_selectall_mtrl_alpha.png
deleted file mode 100644
index 7c011af..0000000
--- a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_selectall_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_share_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_share_mtrl_alpha.png
deleted file mode 100644
index 36f664c..0000000
--- a/appcompat/appcompat/src/main/res/drawable-mdpi/abc_ic_menu_share_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_copy_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
deleted file mode 100644
index 8e664eb..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_cut_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_cut_mtrl_alpha.png
deleted file mode 100644
index cd38901..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_cut_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_paste_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
deleted file mode 100644
index 9aabc43..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_selectall_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_selectall_mtrl_alpha.png
deleted file mode 100644
index c8bae19..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_selectall_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png
deleted file mode 100644
index 6be7e09..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
deleted file mode 100644
index 90d6ba3..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_cut_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_cut_mtrl_alpha.png
deleted file mode 100644
index 63e541f..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_cut_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
deleted file mode 100644
index f71485c..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_selectall_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_selectall_mtrl_alpha.png
deleted file mode 100644
index 162ab9847..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_selectall_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_share_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_share_mtrl_alpha.png
deleted file mode 100644
index d95a3774..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxhdpi/abc_ic_menu_share_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
deleted file mode 100644
index 6758084..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_copy_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_cut_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_cut_mtrl_alpha.png
deleted file mode 100644
index 397fd91..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_cut_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
deleted file mode 100644
index 6c8428a..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_paste_mtrl_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_selectall_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_selectall_mtrl_alpha.png
deleted file mode 100644
index 9084c38..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_selectall_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_share_mtrl_alpha.png b/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_share_mtrl_alpha.png
deleted file mode 100644
index ba16aac..0000000
--- a/appcompat/appcompat/src/main/res/drawable-xxxhdpi/abc_ic_menu_share_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_copy_mtrl_am_alpha.xml b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_copy_mtrl_am_alpha.xml
new file mode 100644
index 0000000..60ebf76
--- /dev/null
+++ b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_copy_mtrl_am_alpha.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright 2020 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 android:autoMirrored="true" android:height="24dp"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffff" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
+</vector>
diff --git a/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_cut_mtrl_alpha.xml b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_cut_mtrl_alpha.xml
new file mode 100644
index 0000000..592bd60
--- /dev/null
+++ b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_cut_mtrl_alpha.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright 2020 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 android:autoMirrored="true" android:height="24dp"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffff" android:pathData="M9.64,7.64c0.23,-0.5 0.36,-1.05 0.36,-1.64 0,-2.21 -1.79,-4 -4,-4S2,3.79 2,6s1.79,4 4,4c0.59,0 1.14,-0.13 1.64,-0.36L10,12l-2.36,2.36C7.14,14.13 6.59,14 6,14c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4c0,-0.59 -0.13,-1.14 -0.36,-1.64L12,14l7,7h3v-1L9.64,7.64zM6,8c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM6,20c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM12,12.5c-0.28,0 -0.5,-0.22 -0.5,-0.5s0.22,-0.5 0.5,-0.5 0.5,0.22 0.5,0.5 -0.22,0.5 -0.5,0.5zM19,3l-6,6 2,2 7,-7L22,3z"/>
+</vector>
diff --git a/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_paste_mtrl_am_alpha.xml b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_paste_mtrl_am_alpha.xml
new file mode 100644
index 0000000..5404374
--- /dev/null
+++ b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_paste_mtrl_am_alpha.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2020 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0c-1.3,0 -2.4,0.84 -2.82,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM19,20L5,20L5,4h2v3h10L17,4h2v16z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_selectall_mtrl_alpha.xml b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_selectall_mtrl_alpha.xml
new file mode 100644
index 0000000..d0de4ae
--- /dev/null
+++ b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_selectall_mtrl_alpha.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2020 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_share_mtrl_alpha.xml b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_share_mtrl_alpha.xml
new file mode 100644
index 0000000..597a1b3
--- /dev/null
+++ b/appcompat/appcompat/src/main/res/drawable/abc_ic_menu_share_mtrl_alpha.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2020 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
index e055dda..c2f1a3e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXGradleProperties.kt
@@ -16,6 +16,8 @@
package androidx.build
+import androidx.build.dependencyTracker.AffectedModuleDetector
+import org.gradle.api.GradleException
import org.gradle.api.Project
/**
@@ -35,6 +37,60 @@
const val ALL_WARNINGS_AS_ERRORS = "androidx.allWarningsAsErrors"
/**
+ * Setting this property enables calculating the fraction of code covered by tests
+ */
+const val COVERAGE_ENABLED = "androidx.coverageEnabled"
+
+/**
+ * Setting this property puts a summary of the relevant failure messages into standard error
+ */
+const val SUMMARIZE_STANDARD_ERROR = "androidx.summarizeStderr"
+
+/**
+ * Setting this property enables writing versioned API files
+ */
+const val WRITE_VERSIONED_API_FILES = "androidx.writeVersionedApiFiles"
+
+/**
+ * Specifies the type of Android Studio to use for the project's Studio task
+ */
+const val STUDIO_TYPE = "androidx.studio.type"
+
+val ALL_ANDROIDX_PROPERTIES = setOf(
+ ALL_WARNINGS_AS_ERRORS,
+ COVERAGE_ENABLED,
+ DISPLAY_TEST_OUTPUT,
+ STUDIO_TYPE,
+ SUMMARIZE_STANDARD_ERROR,
+ TEST_FAILURES_DO_NOT_FAIL_TEST_TASK,
+ WRITE_VERSIONED_API_FILES,
+ AffectedModuleDetector.CHANGED_PROJECTS_ARG,
+ AffectedModuleDetector.ENABLE_ARG,
+ AffectedModuleDetector.DEPENDENT_PROJECTS_ARG,
+ AffectedModuleDetector.CHANGED_PROJECTS_ARG
+)
+
+/**
+ * Validates that all properties passed by the user of the form "-Pandroidx.*" are not misspelled
+ */
+fun Project.validateAllAndroidxArgumentsAreRecognized() {
+ for (propertyName in project.properties.keys) {
+ if (propertyName.startsWith("androidx")) {
+ if (!ALL_ANDROIDX_PROPERTIES.contains(propertyName)) {
+ val message = "Unrecognized Androidx property '$propertyName'.\n" +
+ "\n" +
+ "Is this a misspelling? All recognized Androidx properties:\n" +
+ ALL_ANDROIDX_PROPERTIES.joinToString("\n") + "\n" +
+ "\n" +
+ "See AndroidXGradleProperties.kt if you need to add this property to " +
+ "the list of known properties."
+ throw GradleException(message)
+ }
+ }
+ }
+}
+
+/**
* Returns whether tests in the project should display output
*/
fun Project.isDisplayTestOutput(): Boolean =
@@ -48,7 +104,7 @@
* is `true`.
*/
fun Project.isWriteVersionedApiFilesEnabled(): Boolean =
- (project.findProperty("androidx.writeVersionedApiFiles") as? String)?.toBoolean() ?: true
+ (project.findProperty(WRITE_VERSIONED_API_FILES) as? String)?.toBoolean() ?: true
/**
* Returns whether the project should generate documentation.
@@ -60,13 +116,13 @@
* Returns whether the project has coverage enabled.
*/
fun Project.isCoverageEnabled(): Boolean =
- (project.findProperty("androidx.coverageEnabled") as? String)?.toBoolean() ?: false
+ (project.findProperty(COVERAGE_ENABLED) as? String)?.toBoolean() ?: false
/**
* Returns the Studio type for the project's studio task
*/
fun Project.studioType() = StudioType.findType(
- findProperty("androidx.studio.type")?.toString()
+ findProperty(STUDIO_TYPE)?.toString()
)
enum class StudioType {
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
index 1c47c0b..54598a6 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
@@ -59,6 +59,8 @@
// TODO have the normal license check run here so it catches the buildscript classpath.
tasks.register(CheckExternalDependencyLicensesTask.TASK_NAME)
+ project.validateAllAndroidxArgumentsAreRecognized()
+ tasks.register("listAndroidXProperties", ListAndroidXPropertiesTask::class.java)
setDependencyVersions()
configureKtlintCheckFile()
configureCheckInvalidSuppress()
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 1a28e14..6a4a957 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -59,7 +59,7 @@
val DYNAMICANIMATION_KTX = Version("1.0.0-alpha04")
val EMOJI = Version("1.2.0-alpha02")
val ENTERPRISE = Version("1.1.0-alpha02")
- val EXIFINTERFACE = Version("1.3.0-rc01")
+ val EXIFINTERFACE = Version("1.4.0-alpha01")
val FRAGMENT = Version("1.3.0-alpha09")
val FUTURES = Version("1.2.0-alpha01")
val GRIDLAYOUT = Version("1.1.0-alpha01")
@@ -76,9 +76,9 @@
val LIFECYCLE = Version("2.3.0-beta01")
val LIFECYCLE_EXTENSIONS = Version("2.2.0")
val LOADER = Version("1.2.0-alpha01")
- val MEDIA = Version("1.2.0-rc01")
- val MEDIA2 = Version("1.1.0-alpha02")
- val MEDIAROUTER = Version("1.2.0-beta01")
+ val MEDIA = Version("1.3.0-alpha01")
+ val MEDIA2 = Version("1.1.0-beta01")
+ val MEDIAROUTER = Version("1.2.0-rc01")
val NAVIGATION = Version("2.4.0-alpha01")
val PAGING = Version("3.0.0-alpha07")
val PALETTE = Version("1.1.0-alpha01")
@@ -125,5 +125,5 @@
val WEBKIT = Version("1.4.0-alpha01")
val WINDOW = Version("1.0.0-alpha02")
val WINDOW_SIDECAR = Version("0.1.0-alpha01")
- val WORK = Version("2.5.0-alpha01")
+ val WORK = Version("2.5.0-alpha02")
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/ListAndroidXPropertiesTask.kt b/buildSrc/src/main/kotlin/androidx/build/ListAndroidXPropertiesTask.kt
new file mode 100644
index 0000000..10656f4
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/ListAndroidXPropertiesTask.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 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
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * Lists recognized properties whose names start with "androidx"
+ */
+abstract class ListAndroidXPropertiesTask() : DefaultTask() {
+ init {
+ group = "Help"
+ description = "Lists AndroidX-specific properties (specifiable via -Pandroidx.*)"
+ }
+
+ @TaskAction
+ fun exec() {
+ project.logger.lifecycle(ALL_ANDROIDX_PROPERTIES.joinToString("\n"))
+ project.logger.lifecycle("See AndroidXGradleProperties.kt for more information")
+ }
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
index fa533f7..dcb0366 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
@@ -86,9 +86,9 @@
companion object {
private const val ROOT_PROP_NAME = "affectedModuleDetector"
private const val LOG_FILE_NAME = "affected_module_detector_log.txt"
- private const val ENABLE_ARG = "androidx.enableAffectedModuleDetection"
- private const val DEPENDENT_PROJECTS_ARG = "androidx.dependentProjects"
- private const val CHANGED_PROJECTS_ARG = "androidx.changedProjects"
+ public const val ENABLE_ARG = "androidx.enableAffectedModuleDetection"
+ public const val DEPENDENT_PROJECTS_ARG = "androidx.dependentProjects"
+ public const val CHANGED_PROJECTS_ARG = "androidx.changedProjects"
@JvmStatic
fun configure(gradle: Gradle, rootProject: Project) {
val enabled = rootProject.hasProperty(ENABLE_ARG)
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraControlDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraControlDeviceTest.java
index 355256b..fed9c13 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraControlDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraControlDeviceTest.java
@@ -24,13 +24,13 @@
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
-import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraX;
import androidx.camera.core.CameraXConfig;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.FocusMeteringResult;
import androidx.camera.core.ImageAnalysis;
+import androidx.camera.core.ImageProxy;
import androidx.camera.core.MeteringPoint;
import androidx.camera.core.SurfaceOrientedMeteringPointFactory;
import androidx.camera.core.UseCase;
@@ -86,13 +86,11 @@
private CameraUseCaseAdapter mCamera;
private UseCase mBoundUseCase;
private MeteringPoint mMeteringPoint1;
- private ImageAnalysis.Analyzer mAnalyzer = (image) -> {
- image.close();
- };
+ private final ImageAnalysis.Analyzer mAnalyzer = ImageProxy::close;
@Before
public void setUp()
- throws CameraInfoUnavailableException, ExecutionException, InterruptedException {
+ throws ExecutionException, InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
CameraXConfig cameraXConfig = Camera2Config.defaultConfig();
CameraX.initialize(context, cameraXConfig).get();
@@ -106,7 +104,7 @@
mMeteringPoint1 = factory.createPoint(0, 0);
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
- mCamera = CameraUtil.getCameraAndAttachUseCase(context, mCameraSelector,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(context, mCameraSelector,
mBoundUseCase = useCase);
useCase.setAnalyzer(CameraXExecutors.ioExecutor(), mAnalyzer);
}
@@ -138,6 +136,12 @@
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
@@ -150,7 +154,7 @@
new FocusMeteringAction.Builder(mMeteringPoint1,
FocusMeteringAction.FLAG_AE).build();
ListenableFuture<FocusMeteringResult> future =
- mCamera.getCameraControlInternal().startFocusAndMetering(action);
+ mCamera.getCameraControl().startFocusAndMetering(action);
assertFutureCompletes(future);
}
@@ -163,7 +167,7 @@
new FocusMeteringAction.Builder(mMeteringPoint1,
FocusMeteringAction.FLAG_AWB).build();
ListenableFuture<FocusMeteringResult> future =
- mCamera.getCameraControlInternal().startFocusAndMetering(action);
+ mCamera.getCameraControl().startFocusAndMetering(action);
assertFutureCompletes(future);
}
@@ -176,7 +180,7 @@
new FocusMeteringAction.Builder(mMeteringPoint1,
FocusMeteringAction.FLAG_AE | FocusMeteringAction.FLAG_AWB).build();
ListenableFuture<FocusMeteringResult> future =
- mCamera.getCameraControlInternal().startFocusAndMetering(action);
+ mCamera.getCameraControl().startFocusAndMetering(action);
assertFutureCompletes(future);
}
@@ -203,7 +207,7 @@
.build();
ListenableFuture<FocusMeteringResult> future =
- mCamera.getCameraControlInternal().startFocusAndMetering(action);
+ mCamera.getCameraControl().startFocusAndMetering(action);
assertFutureCompletes(future);
}
@@ -212,8 +216,8 @@
public void cancelFocusMetering_futureCompletes() {
FocusMeteringAction action =
new FocusMeteringAction.Builder(mMeteringPoint1).build();
- mCamera.getCameraControlInternal().startFocusAndMetering(action);
- ListenableFuture<Void> result = mCamera.getCameraControlInternal().cancelFocusAndMetering();
+ mCamera.getCameraControl().startFocusAndMetering(action);
+ ListenableFuture<Void> result = mCamera.getCameraControl().cancelFocusAndMetering();
assertFutureCompletes(result);
}
@@ -233,7 +237,7 @@
}
});
- ListenableFuture<Void> result = mCamera.getCameraControlInternal().enableTorch(true);
+ ListenableFuture<Void> result = mCamera.getCameraControl().enableTorch(true);
assertFutureCompletes(result);
}
@@ -251,7 +255,7 @@
}
});
- ListenableFuture<Void> result = mCamera.getCameraControlInternal().setZoomRatio(1.0f);
+ ListenableFuture<Void> result = mCamera.getCameraControl().setZoomRatio(1.0f);
assertFutureCompletes(result);
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index b95e958d..9c5c2f8 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -79,6 +79,7 @@
private Semaphore mAnalysisResultsSemaphore;
private CameraSelector mCameraSelector;
private Context mContext;
+ private CameraUseCaseAdapter mCamera;
@Rule
public TestRule mCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
@@ -112,6 +113,14 @@
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ if (mCamera != null) {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
if (mHandlerThread != null) {
@@ -136,8 +145,8 @@
ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
GUARANTEED_RESOLUTION).setTargetRotation(
isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_FRONT_CAMERA,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_FRONT_CAMERA, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
@@ -168,7 +177,8 @@
GUARANTEED_RESOLUTION).setTargetRotation(
isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
@@ -198,7 +208,7 @@
throws InterruptedException {
ImageAnalysis useCase = new ImageAnalysis.Builder().setBackpressureStrategy(
backpressureStrategy).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS);
@@ -212,9 +222,8 @@
public void analyzerDoesNotAnalyzeImages_whenCameraIsNotOpen() throws InterruptedException {
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
// Bind but do not start lifecycle
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, useCase);
- camera.detachUseCases();
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera.detachUseCases();
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
// Keep the lifecycle in an inactive state.
@@ -244,7 +253,7 @@
@Test
public void defaultAspectRatioWillBeSet_whenTargetResolutionIsNotSet() {
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
ImageOutputConfig config = (ImageOutputConfig) useCase.getUseCaseConfig();
assertThat(config.getTargetAspectRatio()).isEqualTo(AspectRatio.RATIO_4_3);
}
@@ -258,7 +267,8 @@
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
@@ -277,7 +287,7 @@
public void targetResolutionIsUpdatedAfterTargetRotationIsUpdated() {
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(
GUARANTEED_RESOLUTION).setTargetRotation(Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
// Updates target rotation from ROTATION_0 to ROTATION_90.
imageAnalysis.setTargetRotation(Surface.ROTATION_90);
@@ -295,7 +305,7 @@
public void analyzerSetMultipleTimesInKeepOnlyLatestMode() throws Exception {
ImageAnalysis useCase = new ImageAnalysis.Builder().setBackpressureStrategy(
STRATEGY_KEEP_ONLY_LATEST).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS);
@@ -329,11 +339,10 @@
final ImageAnalysis useCase = new ImageAnalysis.Builder().build();
UseCaseConfig<?> initialConfig = useCase.getUseCaseConfig();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
mInstrumentation.runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
UseCaseConfig<?> configAfterUnbinding = useCase.getUseCaseConfig();
@@ -344,8 +353,7 @@
public void targetRotationIsRetained_whenUseCaseIsReused() {
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
// Generally, the device can't be rotated to Surface.ROTATION_180. Therefore,
// use it to do the test.
@@ -353,13 +361,13 @@
mInstrumentation.runOnMainSync(() -> {
// Check the target rotation is kept when the use case is unbound.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
assertThat(useCase.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
});
// Check the target rotation is kept when the use case is rebound to the
// lifecycle.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
assertThat(useCase.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
@@ -367,19 +375,18 @@
public void useCaseCanBeReusedInSameCamera() throws InterruptedException {
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
mInstrumentation.runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
mAnalysisResultsSemaphore = new Semaphore(/*permits=*/ 0);
// Rebind the use case to the same camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
}
@@ -388,20 +395,20 @@
public void useCaseCanBeReusedInDifferentCamera() throws InterruptedException {
ImageAnalysis useCase = new ImageAnalysis.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
CameraSelector.DEFAULT_BACK_CAMERA, useCase);
useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
mInstrumentation.runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
mAnalysisResultsSemaphore = new Semaphore(/*permits=*/ 0);
// Rebind the use case to different camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_FRONT_CAMERA,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_FRONT_CAMERA, useCase);
assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
}
@@ -417,7 +424,7 @@
public void returnCorrectTargetRotation_afterUseCaseIsAttached() {
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetRotation(
Surface.ROTATION_180).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
assertThat(imageAnalysis.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
index 46b0986..7fc0216 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
@@ -114,13 +114,6 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
public final class ImageCaptureTest {
- @Rule
- public TestRule mCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
-
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.WRITE_EXTERNAL_STORAGE);
-
private static final Size DEFAULT_RESOLUTION = new Size(640, 480);
private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
@CameraSelector.LensFacing
@@ -128,13 +121,17 @@
private static final CameraSelector BACK_SELECTOR =
new CameraSelector.Builder().requireLensFacing(BACK_LENS_FACING).build();
private static final int FLASH_MODE_UNKNOWN = -1;
-
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
-
+ @Rule
+ public TestRule mCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+ @Rule
+ public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE);
private ImageCapture.Builder mDefaultBuilder;
private Executor mMainExecutor;
private ContentResolver mContentResolver;
private Context mContext;
+ private CameraUseCaseAdapter mCamera;
private ImageCaptureConfig createNonRotatedConfiguration() {
// Create a configuration with target rotation that matches the sensor rotation.
@@ -163,6 +160,14 @@
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ if (mCamera != null) {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
@@ -171,7 +176,7 @@
ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
DEFAULT_RESOLUTION).setTargetRotation(Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
@@ -215,8 +220,8 @@
GUARANTEED_RESOLUTION).setTargetRotation(
isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_FRONT_CAMERA,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_FRONT_CAMERA, useCase);
ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
@@ -248,7 +253,9 @@
GUARANTEED_RESOLUTION).setTargetRotation(
isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase);
ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
@@ -265,7 +272,8 @@
@Test
public void canCaptureMultipleImages() throws InterruptedException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
int numImages = 5;
CountingCallback callback = new CountingCallback(numImages, 50000);
@@ -281,7 +289,8 @@
ImageCapture useCase = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
int numImages = 5;
CountingCallback callback = new CountingCallback(numImages, 50000);
@@ -295,7 +304,8 @@
@Test
public void saveCanSucceed() throws IOException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -311,7 +321,8 @@
public void saveToUri() {
// Arrange.
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
@@ -341,7 +352,8 @@
public void saveToOutputStream() throws IOException {
// Arrange.
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -363,7 +375,8 @@
android.os.Build.MODEL.contains("Cuttlefish"));
ImageCapture useCase = new ImageCapture.Builder().setTargetRotation(
Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -420,7 +433,8 @@
// can be equivalent to flipping horizontally
ImageCapture useCase = ImageCapture.Builder.fromConfig(
createNonRotatedConfiguration()).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -447,7 +461,8 @@
// horizontally can be equivalent to flipping vertically
ImageCapture useCase = ImageCapture.Builder.fromConfig(
createNonRotatedConfiguration()).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -470,7 +485,8 @@
@Test
public void canSaveFile_withAttachedLocation() throws IOException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation = File.createTempFile("test", ".jpg");
saveLocation.deleteOnExit();
@@ -494,7 +510,8 @@
@Test
public void canSaveMultipleFiles() throws IOException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
OnImageSavedCallback callback = mock(OnImageSavedCallback.class);
int numImages = 5;
@@ -514,7 +531,8 @@
@Test
public void saveWillFail_whenInvalidFilePathIsUsed() {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
// Note the invalid path
File saveLocation = new File("/not/a/real/path.jpg");
@@ -540,7 +558,8 @@
mock(CameraCaptureSession.CaptureCallback.class);
new Camera2Interop.Extender<>(builder).setSessionCaptureCallback(captureCallback);
ImageCapture useCase = builder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(null);
useCase.takePicture(mMainExecutor, callback);
@@ -578,7 +597,8 @@
ImageCapture useCase = new ImageCapture.Builder()
.setBufferFormat(ImageFormat.RAW10)
.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
@@ -617,8 +637,8 @@
ImageCapture imageCapture = new ImageCapture.Builder().setCaptureBundle(
captureBundle).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA,
- imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, imageCapture);
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(null);
imageCapture.takePicture(mMainExecutor, callback);
@@ -650,8 +670,8 @@
.setCaptureProcessor(mock(CaptureProcessor.class))
.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA,
- imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, imageCapture);
// Add an additional capture stage to test the case
// captureStage.size() > mMaxCaptureStages during takePicture.
@@ -675,8 +695,8 @@
@Test
public void onStateOffline_abortAllCaptureRequests() throws InterruptedException {
ImageCapture imageCapture = new ImageCapture.Builder().build();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA,
- imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, imageCapture);
// After the use case can be reused, the capture requests can only be cancelled after the
// onStateAttached() callback has been received. In the normal code flow, the
@@ -708,9 +728,8 @@
@Test
public void unbind_abortAllCaptureRequests() throws InterruptedException {
ImageCapture imageCapture = new ImageCapture.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- CameraSelector.DEFAULT_BACK_CAMERA,
- imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, imageCapture);
CountingCallback callback = new CountingCallback(3, 10000);
@@ -723,7 +742,7 @@
// after ImageCapture is removed so errors out with a different error from
// ERROR_CAMERA_CLOSED
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
- camera.removeUseCases(Collections.singleton(imageCapture))
+ mCamera.removeUseCases(Collections.singleton(imageCapture))
);
assertThat(callback.getNumOnCaptureSuccess() + callback.getNumOnError()).isEqualTo(3);
@@ -758,7 +777,7 @@
@Test
public void defaultAspectRatioWillBeSet_whenTargetResolutionIsNotSet() {
ImageCapture useCase = new ImageCapture.Builder().build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ImageOutputConfig config = (ImageOutputConfig) useCase.getUseCaseConfig();
assertThat(config.getTargetAspectRatio()).isEqualTo(AspectRatio.RATIO_4_3);
}
@@ -772,7 +791,7 @@
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
@@ -791,7 +810,7 @@
public void targetResolutionIsUpdatedAfterTargetRotationIsUpdated() {
ImageCapture imageCapture = new ImageCapture.Builder().setTargetResolution(
DEFAULT_RESOLUTION).setTargetRotation(Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
// Updates target rotation from ROTATION_0 to ROTATION_90.
imageCapture.setTargetRotation(Surface.ROTATION_90);
@@ -810,7 +829,7 @@
ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
DEFAULT_RESOLUTION).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imagePropertiesFuture = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imagePropertiesFuture);
@@ -852,7 +871,7 @@
DEFAULT_RESOLUTION).setTargetRotation(
isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imagePropertiesFuture = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imagePropertiesFuture);
@@ -898,7 +917,7 @@
// Updates target rotation to opposite one.
useCase.setTargetRotation(isRotateNeeded ? Surface.ROTATION_0 : Surface.ROTATION_90);
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imagePropertiesFuture = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imagePropertiesFuture);
@@ -937,7 +956,7 @@
throws ExecutionException, InterruptedException {
ImageCapture useCase = new ImageCapture.Builder().build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imagePropertiesFuture = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imagePropertiesFuture);
@@ -986,11 +1005,10 @@
final ImageCapture useCase = mDefaultBuilder.build();
UseCaseConfig<?> initialConfig = useCase.getUseCaseConfig();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
mInstrumentation.runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
UseCaseConfig<?> configAfterUnbinding = useCase.getUseCaseConfig();
@@ -1001,8 +1019,7 @@
public void targetRotationIsRetained_whenUseCaseIsReused() {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
// Generally, the device can't be rotated to Surface.ROTATION_180. Therefore,
// use it to do the test.
@@ -1010,7 +1027,7 @@
mInstrumentation.runOnMainSync(() -> {
// Unbind the use case.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
// Check the target rotation is kept when the use case is unbound.
@@ -1018,7 +1035,7 @@
// Check the target rotation is kept when the use case is rebound to the
// lifecycle.
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
assertThat(useCase.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
@@ -1028,17 +1045,16 @@
ImageCapture useCase = mDefaultBuilder.build();
Rational cropAspectRatio = new Rational(1, 1);
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
useCase.setCropAspectRatio(cropAspectRatio);
mInstrumentation.runOnMainSync(() -> {
// Unbind the use case.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
// Rebind the use case.
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
ResolvableFuture<ImageProperties> imagePropertiesFuture = ResolvableFuture.create();
OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imagePropertiesFuture);
@@ -1059,8 +1075,7 @@
public void useCaseCanBeReusedInSameCamera() throws IOException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
File saveLocation1 = File.createTempFile("test1", ".jpg");
saveLocation1.deleteOnExit();
@@ -1072,11 +1087,11 @@
mInstrumentation.runOnMainSync(() -> {
// Unbind the use case.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
// Rebind the use case to the same camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, useCase);
File saveLocation2 = File.createTempFile("test2", ".jpg");
saveLocation2.deleteOnExit();
@@ -1091,7 +1106,7 @@
public void useCaseCanBeReusedInDifferentCamera() throws IOException {
ImageCapture useCase = mDefaultBuilder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
CameraSelector.DEFAULT_BACK_CAMERA, useCase);
File saveLocation1 = File.createTempFile("test1", ".jpg");
@@ -1104,12 +1119,12 @@
mInstrumentation.runOnMainSync(() -> {
// Unbind the use case.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
// Rebind the use case to different camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_FRONT_CAMERA,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_FRONT_CAMERA, useCase);
File saveLocation2 = File.createTempFile("test2", ".jpg");
saveLocation2.deleteOnExit();
@@ -1131,7 +1146,7 @@
public void returnCorrectTargetRotation_afterUseCaseIsAttached() {
ImageCapture imageCapture = new ImageCapture.Builder().setTargetRotation(
Surface.ROTATION_180).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
assertThat(imageCapture.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
@@ -1145,19 +1160,10 @@
public void returnCorrectFlashMode_afterUseCaseIsAttached() {
ImageCapture imageCapture = new ImageCapture.Builder().setFlashMode(
ImageCapture.FLASH_MODE_ON).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, BACK_SELECTOR, imageCapture);
assertThat(imageCapture.getFlashMode()).isEqualTo(ImageCapture.FLASH_MODE_ON);
}
- private static final class ImageProperties {
- public Size size;
- public int format;
- public int rotationDegrees;
- public Rect cropRect;
-
- public Exif exif;
- }
-
private OnImageCapturedCallback createMockOnImageCapturedCallback(
@Nullable ResolvableFuture<ImageProperties> resultProperties) {
OnImageCapturedCallback callback = mock(OnImageCapturedCallback.class);
@@ -1191,14 +1197,22 @@
return callback;
}
+ private static final class ImageProperties {
+ public Size size;
+ public int format;
+ public int rotationDegrees;
+ public Rect cropRect;
+
+ public Exif exif;
+ }
+
private static class CountingCallback extends OnImageCapturedCallback {
CountDownLatch mCountDownLatch;
long mTimeout;
+ List<Integer> mImageCaptureErrors = new ArrayList<>();
private int mNumOnCaptureSuccess = 0;
private int mNumOnErrorSuccess = 0;
- List<Integer> mImageCaptureErrors = new ArrayList<>();
-
CountingCallback(int numTakePictures, long timeout) {
mTimeout = timeout;
mCountDownLatch = new CountDownLatch(numTakePictures);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
index ad2fc3d..e0c776a 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
@@ -90,6 +90,7 @@
private Semaphore mSurfaceFutureSemaphore;
private Semaphore mSafeToReleaseSemaphore;
private Context mContext;
+ private CameraUseCaseAdapter mCamera;
@Before
public void setUp() throws ExecutionException, InterruptedException {
@@ -105,6 +106,14 @@
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ if (mCamera != null) {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
// Ensure all cameras are released for the next test
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
@@ -122,7 +131,7 @@
// done on the main thread
mInstrumentation.runOnMainSync(() -> preview.setSurfaceProvider(surfaceProvider));
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
verify(surfaceProvider, timeout(3000)).onSurfaceRequested(any(SurfaceRequest.class));
}
@@ -139,14 +148,13 @@
preview.setSurfaceProvider(CameraXExecutors.mainThreadExecutor(),
getSurfaceProvider(null))
);
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Wait until preview gets frame.
assertThat(mSurfaceFutureSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
// Remove the UseCase from the camera
- camera.removeUseCases(Collections.singleton(preview));
+ mCamera.removeUseCases(Collections.singleton(preview));
// Assert.
assertThat(mSafeToReleaseSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
@@ -161,7 +169,7 @@
mInstrumentation.runOnMainSync(() -> preview.setSurfaceProvider(getSurfaceProvider(null)));
// Act.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Assert.
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -182,7 +190,7 @@
);
// Act.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Assert.
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -193,7 +201,7 @@
public void setSurfaceProviderAfterAttach_getsFrame() throws InterruptedException {
// Arrange.
Preview preview = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Act.
// TODO(b/160261462) move off of main thread when setSurfaceProvider does not need to be
@@ -211,7 +219,7 @@
// Arrange.
Preview preview = mDefaultBuilder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Act.
// TODO(b/160261462) move off of main thread when setSurfaceProvider does not need to be
@@ -247,7 +255,7 @@
// TODO(b/160261462) move off of main thread when setSurfaceProvider does not need to be
// done on the main thread
mInstrumentation.runOnMainSync(() -> preview.setSurfaceProvider(getSurfaceProvider(null)));
- CameraUtil.getCameraAndAttachUseCase(mContext,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
CameraSelector.DEFAULT_FRONT_CAMERA, preview);
// Assert.
@@ -280,7 +288,7 @@
// TODO(b/160261462) move off of main thread when setSurfaceProvider does not need to be
// done on the main thread
mInstrumentation.runOnMainSync(() -> preview.setSurfaceProvider(getSurfaceProvider(null)));
- CameraUtil.getCameraAndAttachUseCase(mContext,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
CameraSelector.DEFAULT_BACK_CAMERA, preview);
// Assert.
@@ -303,7 +311,7 @@
// for preview.
preview.setSurfaceProvider(getSurfaceProvider(null));
});
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -329,7 +337,7 @@
// for preview.
preview.setSurfaceProvider(getSurfaceProvider(null));
});
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -348,7 +356,7 @@
@Test
public void defaultAspectRatioWillBeSet_whenTargetResolutionIsNotSet() {
Preview useCase = new Preview.Builder().build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
ImageOutputConfig config = (ImageOutputConfig) useCase.getUseCaseConfig();
assertThat(config.getTargetAspectRatio()).isEqualTo(AspectRatio.RATIO_4_3);
}
@@ -361,7 +369,8 @@
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_BACK_CAMERA, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_BACK_CAMERA, useCase);
assertThat(useCase.getUseCaseConfig().containsOption(
ImageOutputConfig.OPTION_TARGET_ASPECT_RATIO)).isFalse();
@@ -372,11 +381,10 @@
final Preview preview = mDefaultBuilder.build();
UseCaseConfig<?> initialConfig = preview.getUseCaseConfig();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
mInstrumentation.runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(preview));
+ mCamera.removeUseCases(Collections.singleton(preview));
});
UseCaseConfig<?> configAfterUnbinding = preview.getUseCaseConfig();
@@ -387,8 +395,7 @@
public void targetRotationIsRetained_whenUseCaseIsReused() {
Preview useCase = mDefaultBuilder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
// Generally, the device can't be rotated to Surface.ROTATION_180. Therefore,
// use it to do the test.
@@ -396,7 +403,7 @@
mInstrumentation.runOnMainSync(() -> {
// Unbind the use case.
- camera.removeUseCases(Collections.singleton(useCase));
+ mCamera.removeUseCases(Collections.singleton(useCase));
});
// Check the target rotation is kept when the use case is unbound.
@@ -404,7 +411,7 @@
// Check the target rotation is kept when the use case is rebound to the
// lifecycle.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, useCase);
assertThat(useCase.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
@@ -417,15 +424,14 @@
});
// This is the first time the use case bound to the lifecycle.
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Check the frame available callback is called.
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
mInstrumentation.runOnMainSync(() -> {
// Unbind and rebind the use case to the same lifecycle.
- camera.removeUseCases(Collections.singleton(preview));
+ mCamera.removeUseCases(Collections.singleton(preview));
});
assertThat(mSafeToReleaseSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
@@ -433,7 +439,7 @@
// Recreate the semaphore to monitor the frame available callback.
mSurfaceFutureSemaphore = new Semaphore(/*permits=*/ 0);
// Rebind the use case to the same camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
// Check the frame available callback can be called after reusing the use case.
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -448,7 +454,7 @@
});
// This is the first time the use case bound to the lifecycle.
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
CameraSelector.DEFAULT_BACK_CAMERA, preview);
// Check the frame available callback is called.
@@ -456,7 +462,7 @@
mInstrumentation.runOnMainSync(() -> {
// Unbind and rebind the use case to the same lifecycle.
- camera.removeUseCases(Collections.singleton(preview));
+ mCamera.removeUseCases(Collections.singleton(preview));
});
assertThat(mSafeToReleaseSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
@@ -464,8 +470,8 @@
// Recreate the semaphore to monitor the frame available callback.
mSurfaceFutureSemaphore = new Semaphore(/*permits=*/ 0);
// Rebind the use case to different camera.
- CameraUtil.getCameraAndAttachUseCase(mContext, CameraSelector.DEFAULT_FRONT_CAMERA,
- preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ CameraSelector.DEFAULT_FRONT_CAMERA, preview);
// Check the frame available callback can be called after reusing the use case.
assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
@@ -482,7 +488,7 @@
public void returnCorrectTargetRotation_afterUseCaseIsAttached() {
Preview preview = new Preview.Builder().setTargetRotation(
Surface.ROTATION_180).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, preview);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, preview);
assertThat(preview.getTargetRotation()).isEqualTo(Surface.ROTATION_180);
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
index b87901b..d7a27a3 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SurfaceOrientedMeteringPointFactoryTest.java
@@ -31,8 +31,10 @@
import androidx.camera.core.MeteringPoint;
import androidx.camera.core.MeteringPointFactory;
import androidx.camera.core.SurfaceOrientedMeteringPointFactory;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.camera.testing.CameraUtil;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -116,12 +118,19 @@
CameraSelector cameraSelector =
new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_BACK).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, cameraSelector, imageAnalysis);
+ CameraUseCaseAdapter camera = CameraUtil.createCameraAndAttachUseCase(mContext,
+ cameraSelector, imageAnalysis);
SurfaceOrientedMeteringPointFactory factory = new SurfaceOrientedMeteringPointFactory(
WIDTH, HEIGHT, imageAnalysis);
MeteringPoint point = factory.createPoint(0f, 0f);
assertThat(point.getSurfaceAspectRatio()).isEqualTo(new Rational(4, 3));
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ camera.removeUseCases(camera.getUseCases())
+ );
}
@Test(expected = IllegalStateException.class)
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
index 757b47f9..1406fb1 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
@@ -77,7 +77,7 @@
final Preview preview = initPreview();
final ImageCapture imageCapture = initImageCapture();
- CameraUseCaseAdapter camera = CameraUtil.getCameraUseCaseAdapter(mContext,
+ CameraUseCaseAdapter camera = CameraUtil.createCameraUseCaseAdapter(mContext,
DEFAULT_SELECTOR);
camera.detachUseCases();
@@ -101,7 +101,7 @@
final Preview preview = initPreview();
final ImageAnalysis imageAnalysis = initImageAnalysis();
- CameraUseCaseAdapter camera = CameraUtil.getCameraUseCaseAdapter(mContext,
+ CameraUseCaseAdapter camera = CameraUtil.createCameraUseCaseAdapter(mContext,
DEFAULT_SELECTOR);
camera.detachUseCases();
@@ -124,7 +124,7 @@
final ImageAnalysis imageAnalysis = initImageAnalysis();
final ImageCapture imageCapture = initImageCapture();
- CameraUseCaseAdapter camera = CameraUtil.getCameraUseCaseAdapter(mContext,
+ CameraUseCaseAdapter camera = CameraUtil.createCameraUseCaseAdapter(mContext,
DEFAULT_SELECTOR);
camera.detachUseCases();
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplTest.java
index 577b6e0..2dd1819 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraControlImplTest.java
@@ -53,7 +53,6 @@
import androidx.annotation.NonNull;
import androidx.camera.camera2.Camera2Config;
import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.core.Camera;
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraX;
@@ -117,7 +116,7 @@
private CameraCharacteristics mCameraCharacteristics;
private boolean mHasFlashUnit;
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
- private Camera mCamera;
+ private CameraUseCaseAdapter mCamera;
@Before
public void setUp() throws InterruptedException {
@@ -153,6 +152,14 @@
@After
public void tearDown() throws InterruptedException, ExecutionException, TimeoutException {
+ if (mCamera != null) {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
if (mHandlerThread != null) {
mHandlerThread.quitSafely();
@@ -365,17 +372,16 @@
future.get(5, TimeUnit.SECONDS);
}
-
private Camera2CameraControlImpl createCamera2CameraControlWithPhysicalCamera() {
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
// Make ImageAnalysis active.
imageAnalysis.setAnalyzer(CameraXExecutors.mainThreadExecutor(), (image) -> image.close());
- CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraAndAttachUseCase(ApplicationProvider.getApplicationContext(),
- CameraSelector.DEFAULT_BACK_CAMERA, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(
+ ApplicationProvider.getApplicationContext(), CameraSelector.DEFAULT_BACK_CAMERA,
+ imageAnalysis);
- return (Camera2CameraControlImpl) cameraUseCaseAdapter.getCameraControlInternal();
+ return (Camera2CameraControlImpl) mCamera.getCameraControl();
}
@Test
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
index ba69473..0cf4896 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
@@ -95,6 +95,7 @@
private FakeLifecycleOwner mLifecycle;
private Context mContext;
+ private CameraUseCaseAdapter mCamera;
@Before
public void setUp() {
@@ -107,6 +108,14 @@
@After
public void tearDown() throws InterruptedException, ExecutionException, TimeoutException {
+ if (mCamera != null) {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
@@ -116,7 +125,7 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(mDeviceStateCallback);
ImageAnalysis useCase = builder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
WaitingAnalyzer waitingAnalyzer = new WaitingAnalyzer(10);
useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), waitingAnalyzer);
@@ -142,8 +151,7 @@
ImageAnalysis useCase2 = new ImageAnalysis.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase,
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase,
useCase2);
CountingAnalyzer countingAnalyzer = new CountingAnalyzer();
@@ -155,7 +163,7 @@
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
- camera.removeUseCases(Arrays.asList(useCase))
+ mCamera.removeUseCases(Arrays.asList(useCase))
);
mLifecycle.startAndResume();
@@ -176,9 +184,7 @@
.setDeviceStateCallback(deviceStateCallback)
.setSessionCaptureCallback(sessionCaptureCallback);
ImageAnalysis useCase = configBuilder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR,
- useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
CountingAnalyzer countingAnalyzer = new CountingAnalyzer();
useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), countingAnalyzer);
@@ -187,7 +193,7 @@
// Wait a little bit for the camera to open and stream frames.
sessionCaptureCallback.waitForOnCaptureCompleted(5);
- camera.detachUseCases();
+ mCamera.detachUseCases();
// Wait a little bit for the camera to close.
deviceStateCallback.waitForOnClosed(1);
@@ -241,8 +247,7 @@
ImageAnalysis useCase0 = configBuilder0.build();
CameraSelector selectorBack = new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_BACK).build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext, selectorBack,
- useCase0);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, selectorBack, useCase0);
mLifecycle.startAndResume();
@@ -255,14 +260,14 @@
// camera capture session will be opened immediately after a previous
// CaptureSession is opened, and the previous CaptureSession will going to close
// right after the new CaptureSession is opened.
- camera.detachUseCases();
- camera.attachUseCases();
+ mCamera.detachUseCases();
+ mCamera.attachUseCases();
// Wait for the capture session is configured.
assertTrue(sessionStateCallback.waitForOnConfigured(1));
}
// Detach all useCase and switch to another camera to verify the camera close flow.
- camera.detachUseCases();
+ mCamera.detachUseCases();
// The camera switch only succeeds after all the exist CaptureSession was
// closed successfully.
@@ -272,7 +277,7 @@
ImageAnalysis useCase1 = configBuilder1.build();
CameraSelector selectorFront = new CameraSelector.Builder().requireLensFacing(
CameraSelector.LENS_FACING_FRONT).build();
- CameraUtil.getCameraAndAttachUseCase(mContext, selectorFront, useCase1);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, selectorFront, useCase1);
// The front camera should open successfully. If the test fail, the CameraX might
// in wrong internal state, and the CameraX#shutdown() might stuck.
@@ -285,7 +290,7 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(mDeviceStateCallback);
ImageAnalysis useCase = builder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
verify(mDeviceStateCallback, timeout(3000)).onOpened(any(CameraDevice.class));
}
@@ -296,7 +301,7 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(mDeviceStateCallback);
ImageAnalysis useCase = builder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
verify(mDeviceStateCallback, timeout(3000)).onOpened(any(CameraDevice.class));
}
@@ -312,7 +317,7 @@
ImageAnalysis useCase = builder.build();
- CameraUtil.getCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
// When no analyzer is set, there will be no active surface for repeating request
// CaptureSession#mSessionConfig will be null. Thus we wait until capture session
@@ -331,12 +336,11 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(callback);
ImageAnalysis useCase = builder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
verify(callback, timeout(5000)).onOpened(any(CameraDevice.class));
- camera.detachUseCases();
+ mCamera.detachUseCases();
verify(callback, timeout(3000)).onClosed(any(CameraDevice.class));
}
@@ -352,12 +356,11 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(callback);
ImageAnalysis useCase = builder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
verify(callback, timeout(5000)).onOpened(any(CameraDevice.class));
- camera.detachUseCases();
+ mCamera.detachUseCases();
verify(callback, timeout(3000)).onClosed(any(CameraDevice.class));
}
@@ -369,15 +372,14 @@
new Camera2Interop.Extender<>(builder).setDeviceStateCallback(mDeviceStateCallback);
ImageAnalysis useCase = builder.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase);
verify(mDeviceStateCallback, timeout(3000)).onOpened(any(CameraDevice.class));
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
- camera.removeUseCases(Collections.singletonList(useCase))
+ mCamera.removeUseCases(Collections.singletonList(useCase))
);
verify(mDeviceStateCallback, timeout(3000)).onClosed(any(CameraDevice.class));
}
@@ -392,15 +394,15 @@
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase0, useCase1);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase0,
+ useCase1);
verify(mDeviceStateCallback, timeout(3000)).onOpened(any(CameraDevice.class));
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
- camera.removeUseCases(Collections.singletonList(useCase1))
+ mCamera.removeUseCases(Collections.singletonList(useCase1))
);
Thread.sleep(3000);
@@ -417,16 +419,16 @@
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- DEFAULT_SELECTOR, useCase0, useCase1);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, DEFAULT_SELECTOR, useCase0,
+ useCase1);
verify(mDeviceStateCallback, timeout(3000)).onOpened(any(CameraDevice.class));
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(useCase0));
- camera.removeUseCases(Collections.singleton(useCase1));
+ mCamera.removeUseCases(Collections.singleton(useCase0));
+ mCamera.removeUseCases(Collections.singleton(useCase1));
}
);
@@ -443,15 +445,14 @@
new Camera2Interop.Extender<>(builder1).setDeviceStateCallback(mDeviceStateCallback);
ImageCapture imageCapture = builder1.build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraUseCaseAdapter(mContext,
- DEFAULT_SELECTOR);
+ mCamera = CameraUtil.createCameraUseCaseAdapter(mContext, DEFAULT_SELECTOR);
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
try {
- camera.addUseCases(Collections.singleton(imageCapture));
- camera.addUseCases(Collections.singleton(imageAnalysis));
+ mCamera.addUseCases(Collections.singleton(imageCapture));
+ mCamera.addUseCases(Collections.singleton(imageAnalysis));
} catch (CameraUseCaseAdapter.CameraException e) {
throw new IllegalArgumentException(e);
}
@@ -463,8 +464,8 @@
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
// thread
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- camera.removeUseCases(Collections.singleton(imageCapture));
- camera.removeUseCases(Collections.singleton(imageAnalysis));
+ mCamera.removeUseCases(Collections.singleton(imageCapture));
+ mCamera.removeUseCases(Collections.singleton(imageAnalysis));
});
verify(mDeviceStateCallback, timeout(3000)).onClosed(any(CameraDevice.class));
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/TorchControlDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/TorchControlDeviceTest.java
index efcf52f..fe8afe9 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/TorchControlDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/TorchControlDeviceTest.java
@@ -32,6 +32,7 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.GrantPermissionRule;
import com.google.common.util.concurrent.ListenableFuture;
@@ -57,6 +58,7 @@
GrantPermissionRule.grant(android.Manifest.permission.CAMERA);
private TorchControl mTorchControl;
+ private CameraUseCaseAdapter mCamera;
@Before
public void setUp() {
@@ -76,15 +78,23 @@
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
// Make ImageAnalysis active.
imageAnalysis.setAnalyzer(CameraXExecutors.mainThreadExecutor(), ImageProxy::close);
- CameraUseCaseAdapter cameraUseCaseAdapter = CameraUtil.getCameraAndAttachUseCase(context,
- cameraSelector, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(context, cameraSelector, imageAnalysis);
Camera2CameraControlImpl cameraControl = (Camera2CameraControlImpl)
- cameraUseCaseAdapter.getCameraControlInternal();
+ mCamera.getCameraControl();
+
mTorchControl = cameraControl.getTorchControl();
}
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ if (mCamera != null) {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
index 09f7f8b..c34f231 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
@@ -73,6 +73,7 @@
private CameraCaptureSession.CaptureCallback mMockCaptureCallback =
mock(CameraCaptureSession.CaptureCallback.class);
private Context mContext;
+ private CameraUseCaseAdapter mCamera;
@Rule
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
@@ -90,6 +91,14 @@
@After
public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ if (mCamera != null) {
+ mInstrumentation.runOnMainSync(() ->
+ //TODO: The removeUseCases() call might be removed after clarifying the
+ // abortCaptures() issue in b/162314023.
+ mCamera.removeUseCases(mCamera.getUseCases())
+ );
+ }
+
CameraX.shutdown().get(10000, TimeUnit.MILLISECONDS);
}
@@ -110,7 +119,7 @@
imageAnalysis.setAnalyzer(CameraXExecutors.highPriorityExecutor(),
mock(ImageAnalysis.Analyzer.class));
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
verify(mMockCaptureCallback, timeout(5000).atLeastOnce()).onCaptureCompleted(
any(CameraCaptureSession.class),
@@ -222,13 +231,13 @@
private Rect getZoom2XCropRegion() throws Exception {
AtomicReference<String> cameraIdRef = new AtomicReference<>();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
- CameraUseCaseAdapter camera = CameraUtil.getCameraAndAttachUseCase(mContext,
- mCameraSelector, imageAnalysis);
- String cameraId = camera.getCameraInfoInternal().getCameraId();
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
+
+ String cameraId = Camera2CameraInfo.fromCameraInfo(mCamera.getCameraInfo()).getCameraId();
cameraIdRef.set(cameraId);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
- camera.removeUseCases(Collections.singleton(imageAnalysis))
+ mCamera.removeUseCases(Collections.singleton(imageAnalysis))
);
CameraManager cameraManager =
@@ -260,7 +269,7 @@
imageAnalysis.setAnalyzer(CameraXExecutors.highPriorityExecutor(),
mock(ImageAnalysis.Analyzer.class));
- CameraUtil.getCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
+ mCamera = CameraUtil.createCameraAndAttachUseCase(mContext, mCameraSelector, imageAnalysis);
}
private <T> void verifyCaptureRequestParameter(
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 6ae5131..f79534c 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -37,8 +37,6 @@
import androidx.camera.camera2.internal.annotation.CameraExecutor;
import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
import androidx.camera.camera2.internal.compat.CameraManagerCompat;
-import androidx.camera.core.CameraControl;
-import androidx.camera.core.CameraInfo;
import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.Preview;
import androidx.camera.core.UseCase;
@@ -1143,18 +1141,6 @@
}
}
- @NonNull
- @Override
- public CameraControl getCameraControl() {
- return getCameraControlInternal();
- }
-
- @NonNull
- @Override
- public CameraInfo getCameraInfo() {
- return getCameraInfoInternal();
- }
-
enum InternalState {
/**
* Stable state once the camera has been constructed.
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2CameraInfo.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2CameraInfo.java
index adb34b6..2b3bb82 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2CameraInfo.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2CameraInfo.java
@@ -64,9 +64,19 @@
* Gets the string camera ID.
*
* <p>The camera ID is the same as the camera ID that would be obtained from
- * {@link android.hardware.camera2.CameraManager#getCameraIdList()}.
+ * {@link android.hardware.camera2.CameraManager#getCameraIdList()}. The ID that is retrieved
+ * is not static and can change depending on the current internal configuration of the
+ * {@link androidx.camera.core.Camera} from which the CameraInfo was retrieved.
+ *
+ * The Camera is a logical camera which can be backed by multiple
+ * {@link android.hardware.camera2.CameraDevice}. However, only one CameraDevice is active at
+ * one time. When the CameraDevice changes then the camera id will change.
*
* @return the camera ID.
+
+ * @throws IllegalStateException if the camera info does not contain the camera 2 camera ID
+ * (e.g., if CameraX was not initialized with a
+ * {@link androidx.camera.camera2.Camera2Config}).
*/
@NonNull
public String getCameraId() {
@@ -88,4 +98,30 @@
public <T> T getCameraCharacteristic(@NonNull CameraCharacteristics.Key<T> key) {
return mCamera2CameraInfoImpl.getCameraCharacteristics().get(key);
}
+
+ /**
+ * Returns the {@link CameraCharacteristics} for this camera.
+ *
+ * <p>The CameraCharacteristics will be the ones that would be obtained by
+ * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics(String)}. The
+ * CameraCharacteristics that are retrieved are not static and can change depending on the
+ * current internal configuration of the camera.
+ *
+ * @param cameraInfo The {@link CameraInfo} to extract the CameraCharacteristics from.
+ * @throws IllegalStateException if the camera info does not contain the camera 2
+ * characteristics(e.g., if CameraX was not initialized with a
+ * {@link androidx.camera.camera2.Camera2Config}).
+ *
+ * @hide
+ */
+ // TODO: Hidden until new extensions API released.
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @NonNull
+ public static CameraCharacteristics extractCameraCharacteristics(
+ @NonNull CameraInfo cameraInfo) {
+ Preconditions.checkState(cameraInfo instanceof Camera2CameraInfoImpl, "CameraInfo does "
+ + "not contain any Camera2 information.");
+ Camera2CameraInfoImpl impl = (Camera2CameraInfoImpl) cameraInfo;
+ return impl.getCameraCharacteristics();
+ }
}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
index a61b30c..a71184d 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
@@ -536,7 +536,7 @@
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.build();
- CameraUseCaseAdapter cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(mContext,
+ CameraUseCaseAdapter cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(mContext,
CameraSelector.DEFAULT_BACK_CAMERA);
cameraUseCaseAdapter.addUseCases(Arrays.asList(preview, imageCapture, imageAnalysis));
@@ -589,7 +589,7 @@
// Preview/ImageCapture/ImageAnalysis' default config settings that will be applied after
// bound to lifecycle. Calling bindToLifecycle here to make sure sizes matching to
// default aspect ratio will be selected.
- CameraUseCaseAdapter cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(mContext,
+ CameraUseCaseAdapter cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(mContext,
CameraSelector.DEFAULT_BACK_CAMERA);
cameraUseCaseAdapter.addUseCases(Arrays.asList(preview,
diff --git a/camera/camera-core/api/public_plus_experimental_1.0.0-beta09.txt b/camera/camera-core/api/public_plus_experimental_1.0.0-beta09.txt
index ff65585..7da2353 100644
--- a/camera/camera-core/api/public_plus_experimental_1.0.0-beta09.txt
+++ b/camera/camera-core/api/public_plus_experimental_1.0.0-beta09.txt
@@ -340,7 +340,7 @@
@androidx.camera.core.ExperimentalUseCaseGroup public final class UseCaseGroup {
method public java.util.List<androidx.camera.core.UseCase!> getUseCases();
- method public androidx.camera.core.ViewPort getViewPort();
+ method public androidx.camera.core.ViewPort? getViewPort();
}
@androidx.camera.core.ExperimentalUseCaseGroup public static final class UseCaseGroup.Builder {
diff --git a/camera/camera-core/api/public_plus_experimental_current.txt b/camera/camera-core/api/public_plus_experimental_current.txt
index ff65585..7da2353 100644
--- a/camera/camera-core/api/public_plus_experimental_current.txt
+++ b/camera/camera-core/api/public_plus_experimental_current.txt
@@ -340,7 +340,7 @@
@androidx.camera.core.ExperimentalUseCaseGroup public final class UseCaseGroup {
method public java.util.List<androidx.camera.core.UseCase!> getUseCases();
- method public androidx.camera.core.ViewPort getViewPort();
+ method public androidx.camera.core.ViewPort? getViewPort();
}
@androidx.camera.core.ExperimentalUseCaseGroup public static final class UseCaseGroup.Builder {
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
index 31cfda7..e9d4858 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
@@ -103,7 +103,7 @@
ImageCapture.OnImageCapturedCallback callback = mock(
ImageCapture.OnImageCapturedCallback.class);
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControl());
fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
// Notify the cancel after the capture request has been successfully submitted
@@ -134,7 +134,7 @@
ImageCapture.OnImageCapturedCallback callback = mock(
ImageCapture.OnImageCapturedCallback.class);
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControl());
fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
// Notify the failure after the capture request has been successfully submitted
fakeCameraControl.notifyAllRequestsOnCaptureFailed();
@@ -164,8 +164,7 @@
}
});
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
-
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControl());
FakeCameraControl.OnNewCaptureRequestListener mockCaptureRequestListener =
mock(FakeCameraControl.OnNewCaptureRequestListener.class);
fakeCameraControl.setOnNewCaptureRequestListener(mockCaptureRequestListener);
@@ -198,7 +197,7 @@
ImageCapture.OnImageCapturedCallback callback = mock(
ImageCapture.OnImageCapturedCallback.class);
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControl());
CountDownLatch latch = new CountDownLatch(1);
fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
latch.countDown();
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
index 84eb46e..334bf85 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
@@ -28,6 +28,7 @@
import android.view.Surface;
import androidx.annotation.NonNull;
+import androidx.camera.core.impl.DeferrableSurface;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.fakes.FakeCamera;
import androidx.core.content.ContextCompat;
@@ -40,8 +41,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
@SmallTest
@@ -53,8 +57,26 @@
SurfaceRequest.TransformationInfo.of(new Rect(), 0, Surface.ROTATION_0);
private static final Consumer<SurfaceRequest.Result> NO_OP_RESULT_LISTENER = ignored -> {
};
+ private static final long FINALIZE_TIMEOUT_MILLIS = 200L;
+ private static final int NUM_GC_ITERATIONS = 10;
private static final Surface MOCK_SURFACE = mock(Surface.class);
- private List<SurfaceRequest> mSurfaceRequests = new ArrayList<>();
+ private final List<SurfaceRequest> mSurfaceRequests = new ArrayList<>();
+
+ private static void runFinalization() throws TimeoutException, InterruptedException {
+ ReferenceQueue<Object> finalizeAwaitQueue = new ReferenceQueue<>();
+ PhantomReference<Object> finalizeSignal;
+ // Ensure finalization occurs multiple times
+ for (int i = 0; i < NUM_GC_ITERATIONS; ++i) {
+ finalizeSignal = new PhantomReference<>(new Object(), finalizeAwaitQueue);
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().runFinalization();
+ if (finalizeAwaitQueue.remove(FINALIZE_TIMEOUT_MILLIS) == null) {
+ throw new TimeoutException(
+ "Finalization failed on iteration " + (i + 1) + " of " + NUM_GC_ITERATIONS);
+ }
+ finalizeSignal.clear();
+ }
+ }
@After
public void tearDown() {
@@ -222,9 +244,80 @@
assertThat(infoReference.get()).isEqualTo(FAKE_INFO);
}
+ @SuppressWarnings("UnusedAssignment") // request assigned to null to make GC eligible
+ @Test
+ public void deferrableSurface_stronglyReferencesSurfaceRequest()
+ throws TimeoutException, InterruptedException {
+ // Arrange.
+ SurfaceRequest request = createNewRequestWithoutAutoCleanup(FAKE_SIZE);
+ // Retrieve the DeferrableSurface which should maintain the strong reference to the
+ // SurfaceRequest
+ DeferrableSurface deferrableSurface = request.getDeferrableSurface();
+ ReferenceQueue<SurfaceRequest> referenceQueue = new ReferenceQueue<>();
+ // Ensure surface request garbage collection is tracked
+ PhantomReference<SurfaceRequest> phantomReference = new PhantomReference<>(request,
+ referenceQueue);
+ try {
+ // Act.
+ // Null out the original reference to the SurfaceRequest. DeferrableSurface should be
+ // the only reference remaining.
+ request = null;
+ runFinalization();
+ boolean requestFinalized = (referenceQueue.poll() != null);
+
+ // Assert.
+ assertThat(requestFinalized).isFalse();
+ } finally {
+ // Clean up
+ phantomReference.clear();
+ deferrableSurface.close();
+ }
+ }
+
+ @SuppressWarnings("UnusedAssignment") // deferrableSurface assigned to null to make GC eligible
+ @Test
+ public void surfaceRequest_stronglyReferencesDeferrableSurface()
+ throws TimeoutException, InterruptedException {
+ // Arrange.
+ SurfaceRequest request = createNewRequestWithoutAutoCleanup(FAKE_SIZE);
+ // Retrieve the DeferrableSurface which should maintain the strong reference to the
+ // SurfaceRequest
+ DeferrableSurface deferrableSurface = request.getDeferrableSurface();
+ ReferenceQueue<DeferrableSurface> referenceQueue = new ReferenceQueue<>();
+ // Ensure surface request garbage collection is tracked
+ PhantomReference<DeferrableSurface> phantomReference = new PhantomReference<>(
+ deferrableSurface, referenceQueue);
+ try {
+ // Act.
+ // Null out the original reference to the DeferrableSurface. SurfaceRequest should be
+ // the only reference remaining.
+ deferrableSurface = null;
+ runFinalization();
+ boolean deferrableSurfaceFinalized = (referenceQueue.poll() != null);
+
+ // Assert.
+ assertThat(deferrableSurfaceFinalized).isFalse();
+ } finally {
+ // Clean up
+ phantomReference.clear();
+ request.getDeferrableSurface().close();
+ }
+ }
+
+ // The test method is responsible for ensuring that the SurfaceRequest is finished.
+ private SurfaceRequest createNewRequestWithoutAutoCleanup(@NonNull Size size) {
+ return createNewRequest(size, /*autoCleanUp=*/false);
+ }
+
private SurfaceRequest createNewRequest(@NonNull Size size) {
+ return createNewRequest(size, /*autoCleanUp=*/true);
+ }
+
+ private SurfaceRequest createNewRequest(@NonNull Size size, boolean autoCleanup) {
SurfaceRequest request = new SurfaceRequest(size, new FakeCamera(), false);
- mSurfaceRequests.add(request);
+ if (autoCleanup) {
+ mSurfaceRequests.add(request);
+ }
return request;
}
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Camera.java b/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
index a9f855d..dea0fb3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
@@ -17,9 +17,13 @@
package androidx.camera.core;
import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.camera.core.impl.CameraInternal;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+
/**
* The camera interface is used to control the flow of data to use cases, control the
* camera via the {@link CameraControl}, and publish the state of the camera via {@link CameraInfo}.
@@ -57,4 +61,21 @@
*/
@NonNull
CameraInfo getCameraInfo();
+
+ /**
+ * Returns all of the {@link CameraInternal} instances represented by this Camera.
+ *
+ * <p> A {@link Camera} is a logical camera which wraps one or more {@link CameraInternal}.
+ * At any time, only one of the CameraInternal is actually being used, and it is up to the
+ * implementation to determine which {@link CameraInternal} will be used. Certain
+ * reconfigurations of the camera will cause the current CameraInternal camera to change.
+ * However, it will be transparent to the {@link CameraControl} and {@link CameraInfo}
+ * retrieved from {@link #getCameraControl()} and {@link #getCameraInfo()}.
+ *
+ * <p> The set of CameraInternal should be static for the lifetime of the Camera.
+ * @hide
+ */
+ @NonNull
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ Collection<CameraInternal> getCameraInternals();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index e84615c..8753394 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -579,7 +579,7 @@
CameraThreadConfig cameraThreadConfig = CameraThreadConfig.create(mCameraExecutor,
mSchedulerHandler);
- mCameraFactory = cameraFactoryProvider.newInstance(context,
+ mCameraFactory = cameraFactoryProvider.newInstance(mAppContext,
cameraThreadConfig);
CameraDeviceSurfaceManager.Provider surfaceManagerProvider =
mCameraXConfig.getDeviceSurfaceManagerProvider(null);
@@ -588,7 +588,7 @@
"Invalid app configuration provided. Missing "
+ "CameraDeviceSurfaceManager."));
}
- mSurfaceManager = surfaceManagerProvider.newInstance(context);
+ mSurfaceManager = surfaceManagerProvider.newInstance(mAppContext);
UseCaseConfigFactory.Provider configFactoryProvider =
mCameraXConfig.getUseCaseConfigFactoryProvider(null);
@@ -597,7 +597,7 @@
"Invalid app configuration provided. Missing "
+ "UseCaseConfigFactory."));
}
- mDefaultConfigFactory = configFactoryProvider.newInstance(context);
+ mDefaultConfigFactory = configFactoryProvider.newInstance(mAppContext);
if (cameraExecutor instanceof CameraExecutor) {
CameraExecutor executor = (CameraExecutor) cameraExecutor;
@@ -615,7 +615,7 @@
Logger.w(TAG, "Retry init. Start time " + startMs + " current time "
+ SystemClock.elapsedRealtime(), e);
HandlerCompat.postDelayed(mSchedulerHandler, () -> initAndRetryRecursively(
- cameraExecutor, startMs, context, completer), RETRY_TOKEN,
+ cameraExecutor, startMs, mAppContext, completer), RETRY_TOKEN,
RETRY_SLEEP_MILLIS);
} else {
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 5d01749..8a3b70b 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
@@ -373,7 +373,7 @@
} else {
// No pending SurfaceRequest. It could be a previous request has already been
// sent, which means the caller wants to replace the Surface. Or, it could be the
- // pipeline has not started.
+ // pipeline has not started. Or the use case may have been detached from the camera.
// Either way, try updating session config and let createPipeline() sends a
// new SurfaceRequest.
if (getAttachedSurfaceResolution() != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
index 93b5d70..38ac668 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
@@ -31,6 +31,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.DeferrableSurface;
import androidx.camera.core.impl.ImageOutputConfig;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -61,9 +62,10 @@
public final class SurfaceRequest {
private final Size mResolution;
- private final Camera mCamera;
private final boolean mRGBA8888Required;
+ private final CameraInternal mCamera;
+
// For the camera to retrieve the surface from the user
@SuppressWarnings("WeakerAccess") /*synthetic accessor */
final ListenableFuture<Surface> mSurfaceFuture;
@@ -96,7 +98,7 @@
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public SurfaceRequest(
@NonNull Size resolution,
- @NonNull Camera camera,
+ @NonNull CameraInternal camera,
boolean isRGBA8888Required) {
super();
mResolution = resolution;
@@ -167,7 +169,10 @@
mSurfaceCompleter = Preconditions.checkNotNull(surfaceCompleterRef.get());
// Create the deferrable surface which will be used for communicating when the
- // camera and consumer are done using the surface.
+ // camera and consumer are done using the surface. Note this anonymous inner class holds
+ // an implicit reference to the SurfaceRequest. This is by design, and ensures the
+ // SurfaceRequest and all contained future completers will not be garbage collected as
+ // long as the DeferrableSurface is referenced externally (via getDeferrableSurface()).
mInternalDeferrableSurface = new DeferrableSurface() {
@NonNull
@Override
@@ -250,7 +255,7 @@
*/
@NonNull
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public Camera getCamera() {
+ public CameraInternal getCamera() {
return mCamera;
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseGroup.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseGroup.java
index 689261b..21d0c61 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseGroup.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseGroup.java
@@ -17,6 +17,7 @@
package androidx.camera.core;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.core.util.Preconditions;
import androidx.lifecycle.Lifecycle;
@@ -34,11 +35,13 @@
@ExperimentalUseCaseGroup
public final class UseCaseGroup {
- private ViewPort mViewPort;
+ @Nullable
+ private final ViewPort mViewPort;
- private List<UseCase> mUseCases;
+ @NonNull
+ private final List<UseCase> mUseCases;
- UseCaseGroup(@NonNull ViewPort viewPort, @NonNull List<UseCase> useCases) {
+ UseCaseGroup(@Nullable ViewPort viewPort, @NonNull List<UseCase> useCases) {
mViewPort = viewPort;
mUseCases = useCases;
}
@@ -46,7 +49,7 @@
/**
* Gets the {@link ViewPort} shared by the {@link UseCase} collection.
*/
- @NonNull
+ @Nullable
public ViewPort getViewPort() {
return mViewPort;
}
@@ -67,7 +70,7 @@
private ViewPort mViewPort;
- private List<UseCase> mUseCases;
+ private final List<UseCase> mUseCases;
public Builder() {
mUseCases = new ArrayList<>();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
index 4bdfd0c..e163dd7 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInternal.java
@@ -18,14 +18,19 @@
import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
+import androidx.camera.core.CameraControl;
+import androidx.camera.core.CameraInfo;
import androidx.camera.core.UseCase;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collection;
+import java.util.Collections;
/**
* The camera interface. It is controlled by the change of state in use cases.
+ *
+ * <p> It is a Camera instance backed by a single physical camera.
*/
public interface CameraInternal extends Camera, UseCase.StateChangeCallback {
/**
@@ -144,4 +149,28 @@
/** Returns an interface to retrieve characteristics of the camera. */
@NonNull
CameraInfoInternal getCameraInfoInternal();
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Camera interface
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ @NonNull
+ @Override
+ default CameraControl getCameraControl() {
+ return getCameraControlInternal();
+ }
+
+ @NonNull
+ @Override
+ default CameraInfo getCameraInfo() {
+ return getCameraInfoInternal();
+ }
+
+ /**
+ * Always returns only itself since there is only ever one CameraInternal.
+ */
+ @NonNull
+ @Override
+ default Collection<CameraInternal> getCameraInternals() {
+ return Collections.singleton(this);
+ }
}
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 4ebd8fe..fd60409 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
@@ -23,12 +23,13 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.experimental.UseExperimental;
+import androidx.camera.core.Camera;
+import androidx.camera.core.CameraControl;
+import androidx.camera.core.CameraInfo;
import androidx.camera.core.Logger;
import androidx.camera.core.UseCase;
import androidx.camera.core.ViewPort;
-import androidx.camera.core.impl.CameraControlInternal;
import androidx.camera.core.impl.CameraDeviceSurfaceManager;
-import androidx.camera.core.impl.CameraInfoInternal;
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.SurfaceConfig;
import androidx.camera.core.impl.UseCaseConfig;
@@ -51,7 +52,7 @@
* extensions in order to select the correct CameraInternal instance which has the required
* camera id.
*/
-public final class CameraUseCaseAdapter {
+public final class CameraUseCaseAdapter implements Camera {
private final CameraInternal mCameraInternal;
private final LinkedHashSet<CameraInternal> mCameraInternals;
private final CameraDeviceSurfaceManager mCameraDeviceSurfaceManager;
@@ -324,16 +325,6 @@
return suggestedResolutions;
}
- @NonNull
- public CameraInfoInternal getCameraInfoInternal() {
- return mCameraInternal.getCameraInfoInternal();
- }
-
- @NonNull
- public CameraControlInternal getCameraControlInternal() {
- return mCameraInternal.getCameraControlInternal();
- }
-
/**
* An identifier for a {@link CameraUseCaseAdapter}.
*
@@ -381,4 +372,25 @@
super(cause);
}
}
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Camera interface
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ @NonNull
+ @Override
+ public CameraControl getCameraControl() {
+ return mCameraInternal.getCameraControlInternal();
+ }
+
+ @NonNull
+ @Override
+ public CameraInfo getCameraInfo() {
+ return mCameraInternal.getCameraInfoInternal();
+ }
+
+ @NonNull
+ @Override
+ public Collection<CameraInternal> getCameraInternals() {
+ return mCameraInternals;
+ }
}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index 7dacb3c..31d8cee 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -312,7 +312,7 @@
);
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(ApplicationProvider.getApplicationContext(),
+ CameraUtil.createCameraUseCaseAdapter(ApplicationProvider.getApplicationContext(),
CameraSelector.DEFAULT_BACK_CAMERA);
cameraUseCaseAdapter.setViewPort(viewPort);
cameraUseCaseAdapter.addUseCases(Collections.singleton(mImageAnalysis));
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
index c4a470e..b38856c 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
@@ -71,6 +71,7 @@
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executor
import java.util.concurrent.atomic.AtomicReference
+import kotlin.jvm.Throws
private const val MAX_IMAGES = 3
@@ -360,7 +361,7 @@
.setSessionOptionUnpacker(sessionOptionUnpacker)
.build()
- cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(ApplicationProvider
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(ApplicationProvider
.getApplicationContext<Context>(), CameraSelector.DEFAULT_BACK_CAMERA)
cameraUseCaseAdapter.setViewPort(viewPort)
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 3b36ab1..5483966 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
@@ -23,12 +23,12 @@
import android.util.Rational
import android.util.Size
import android.view.Surface
-import android.view.Surface.ROTATION_0
import androidx.camera.core.impl.CameraFactory
import androidx.camera.core.impl.CameraThreadConfig
import androidx.camera.core.impl.SessionConfig
import androidx.camera.core.impl.UseCaseConfig
import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.core.internal.CameraUseCaseAdapter
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.fakes.FakeAppConfig
import androidx.camera.testing.fakes.FakeCamera
@@ -37,7 +37,6 @@
import androidx.camera.testing.fakes.FakeUseCase
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -49,6 +48,9 @@
import org.robolectric.annotation.internal.DoNotInstrument
import java.util.Collections
import java.util.concurrent.ExecutionException
+import kotlin.jvm.Throws
+
+private val TEST_CAMERA_SELECTOR = CameraSelector.DEFAULT_BACK_CAMERA
/**
* Unit tests for [Preview].
@@ -61,6 +63,8 @@
)
class PreviewTest {
+ var cameraUseCaseAdapter: CameraUseCaseAdapter? = null
+
@Before
@Throws(ExecutionException::class, InterruptedException::class)
fun setUp() {
@@ -82,6 +86,10 @@
@After
@Throws(ExecutionException::class, InterruptedException::class)
fun tearDown() {
+ with (cameraUseCaseAdapter) {
+ this?.removeUseCases(useCases)
+ }
+ cameraUseCaseAdapter = null
CameraX.shutdown().get()
}
@@ -149,16 +157,15 @@
val sessionOptionUnpacker =
{ _: UseCaseConfig<*>?, _: SessionConfig.Builder? -> }
val preview = Preview.Builder()
- .setTargetRotation(ROTATION_0)
+ .setTargetRotation(Surface.ROTATION_0)
.setSessionOptionUnpacker(sessionOptionUnpacker)
.build()
- val cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(
- ApplicationProvider
- .getApplicationContext<Context>(), CameraSelector.DEFAULT_BACK_CAMERA
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(
+ ApplicationProvider.getApplicationContext(), TEST_CAMERA_SELECTOR
)
val rational1 = Rational(1, 1)
- cameraUseCaseAdapter.setViewPort(ViewPort.Builder(rational1, ROTATION_0).build())
- cameraUseCaseAdapter.addUseCases(Collections.singleton<UseCase>(preview))
+ cameraUseCaseAdapter!!.setViewPort(ViewPort.Builder(rational1, Surface.ROTATION_0).build())
+ cameraUseCaseAdapter!!.addUseCases(Collections.singleton<UseCase>(preview))
// Set SurfaceProvider
var receivedTransformationInfo: SurfaceRequest.TransformationInfo? = null
@@ -175,8 +182,8 @@
// Act: bind another use case with a different viewport.
val fakeUseCase = FakeUseCase()
val rational2 = Rational(2, 1)
- cameraUseCaseAdapter.setViewPort(ViewPort.Builder(rational2, ROTATION_0).build())
- cameraUseCaseAdapter.addUseCases(listOf(preview, fakeUseCase))
+ cameraUseCaseAdapter!!.setViewPort(ViewPort.Builder(rational2, Surface.ROTATION_0).build())
+ cameraUseCaseAdapter!!.addUseCases(listOf(preview, fakeUseCase))
shadowOf(getMainLooper()).idle()
// Assert: received viewport's aspect ratio is the latest one.
@@ -193,13 +200,13 @@
val sessionOptionUnpacker =
{ _: UseCaseConfig<*>?, _: SessionConfig.Builder? -> }
val preview = Preview.Builder()
- .setTargetRotation(ROTATION_0)
+ .setTargetRotation(Surface.ROTATION_0)
.setSessionOptionUnpacker(sessionOptionUnpacker)
.build()
- val cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(
- ApplicationProvider.getApplicationContext(), CameraSelector.DEFAULT_BACK_CAMERA
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(
+ ApplicationProvider.getApplicationContext(), TEST_CAMERA_SELECTOR
)
- cameraUseCaseAdapter.addUseCases(Collections.singleton<UseCase>(preview))
+ cameraUseCaseAdapter!!.addUseCases(Collections.singleton<UseCase>(preview))
var receivedTransformationInfo: SurfaceRequest.TransformationInfo? = null
preview.setSurfaceProvider { request ->
request.setTransformationInfoListener(
@@ -228,9 +235,9 @@
.setTargetRotation(Surface.ROTATION_0)
.setSessionOptionUnpacker(sessionOptionUnpacker)
.build()
- val cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(
+ val cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(
ApplicationProvider
- .getApplicationContext(), CameraSelector.DEFAULT_BACK_CAMERA
+ .getApplicationContext(), TEST_CAMERA_SELECTOR
)
cameraUseCaseAdapter.addUseCases(Collections.singleton<UseCase>(preview))
@@ -269,6 +276,42 @@
assertThat(receivedSurfaceRequest).isNotSameInstanceAs(pendingSurfaceRequest)
}
+ @Test
+ fun setSurfaceProviderAfterDetach_receivesSurfaceRequestAfterAttach() {
+ // Arrange: attach Preview without a SurfaceProvider.
+ val sessionOptionUnpacker =
+ { _: UseCaseConfig<*>?, _: SessionConfig.Builder? -> }
+ val preview = Preview.Builder()
+ .setTargetRotation(Surface.ROTATION_0)
+ .setSessionOptionUnpacker(sessionOptionUnpacker)
+ .build()
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(
+ ApplicationProvider
+ .getApplicationContext(), TEST_CAMERA_SELECTOR
+ )
+ // Attach
+ cameraUseCaseAdapter!!.addUseCases(Collections.singleton<UseCase>(preview))
+ // Detach
+ cameraUseCaseAdapter!!.removeUseCases(Collections.singleton<UseCase>(preview))
+
+ // Act: set a SurfaceProvider after detaching
+ var receivedSurfaceRequest = false
+ preview.setSurfaceProvider { receivedSurfaceRequest = true }
+ shadowOf(getMainLooper()).idle()
+
+ val receivedWhileDetached = receivedSurfaceRequest
+
+ // Attach
+ cameraUseCaseAdapter!!.addUseCases(Collections.singleton<UseCase>(preview))
+ shadowOf(getMainLooper()).idle()
+
+ val receivedAfterAttach = receivedSurfaceRequest
+
+ // Assert: received a SurfaceRequest.
+ assertThat(receivedWhileDetached).isFalse()
+ assertThat(receivedAfterAttach).isTrue()
+ }
+
private fun bindToLifecycleAndGetSurfaceRequest(): SurfaceRequest {
return bindToLifecycleAndGetResult(null).first
}
@@ -299,14 +342,12 @@
}
// Act.
- val cameraUseCaseAdapter = CameraUtil.getCameraUseCaseAdapter(
- ApplicationProvider
- .getApplicationContext<Context>(), CameraSelector.DEFAULT_BACK_CAMERA
+ cameraUseCaseAdapter = CameraUtil.createCameraUseCaseAdapter(
+ ApplicationProvider.getApplicationContext(), TEST_CAMERA_SELECTOR
)
-
- cameraUseCaseAdapter.setViewPort(viewPort)
- cameraUseCaseAdapter.addUseCases(Collections.singleton<UseCase>(preview))
- InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ cameraUseCaseAdapter!!.setViewPort(viewPort)
+ cameraUseCaseAdapter!!.addUseCases(Collections.singleton<UseCase>(preview))
+ shadowOf(getMainLooper()).idle()
return Pair(surfaceRequest!!, transformationInfo!!)
}
}
\ No newline at end of file
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
index dd497ae..1f52190 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
@@ -93,12 +93,17 @@
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private final Context mContext = ApplicationProvider.getApplicationContext();
- private EffectMode mEffectMode;
+ private final EffectMode mEffectMode;
+ @Extensions.ExtensionMode
+ private final int mExtensionMode;
@CameraSelector.LensFacing
- private int mLensFacing;
+ private final int mLensFacing;
+
+ private CameraUseCaseAdapter mCamera;
public ExtensionTest(EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
mEffectMode = effectMode;
+ mExtensionMode = ExtensionsTestUtil.effectModeToExtensionMode(mEffectMode);
mLensFacing = lensFacing;
}
@@ -111,8 +116,12 @@
assumeTrue(CameraUtil.hasCameraWithLensFacing(mLensFacing));
assumeTrue(ExtensionsTestUtil.initExtensions(mContext));
- assumeTrue(ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing));
assumeTrue(isTargetDeviceAvailableForExtensions(mLensFacing));
+ CameraSelector cameraSelector =
+ new CameraSelector.Builder().requireLensFacing(mLensFacing).build();
+ mCamera = CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
+ Extensions extensions = ExtensionsManager.getExtensions(mContext);
+ assumeTrue(extensions.isExtensionAvailable(mCamera, mExtensionMode));
}
@After
@@ -123,6 +132,8 @@
@Test
public void testCanBindToLifeCycleAndTakePicture() {
+
+
ImageCapture.OnImageCapturedCallback mockOnImageCapturedCallback = mock(
ImageCapture.OnImageCapturedCallback.class);
@@ -131,10 +142,7 @@
mLensFacing);
Preview preview = ExtensionsTestUtil.createPreviewWithEffect(mEffectMode, mLensFacing);
- CameraSelector cameraSelector =
- new CameraSelector.Builder().requireLensFacing(mLensFacing).build();
- CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+
mInstrumentation.runOnMainSync(
() -> {
// To set the update listener and Preview will change to active state.
@@ -155,7 +163,7 @@
}));
try {
- cameraUseCaseAdapter.addUseCases(Arrays.asList(preview, imageCapture));
+ mCamera.addUseCases(Arrays.asList(preview, imageCapture));
} catch (CameraUseCaseAdapter.CameraException e) {
throw new IllegalArgumentException("Unable to bind preview and image "
+ "capture");
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsTest.kt
new file mode 100644
index 0000000..b5557095
--- /dev/null
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 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.extensions
+
+import android.content.Context
+import android.os.Build
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.CameraSelector.LensFacing
+import androidx.camera.core.CameraX
+import androidx.camera.extensions.Extensions.ExtensionMode
+import androidx.camera.extensions.ExtensionsManager.EffectMode
+import androidx.camera.extensions.util.ExtensionsTestUtil
+import androidx.camera.testing.CameraUtil
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+import kotlin.jvm.Throws
+
+@MediumTest
+@RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
+class ExtensionsTest(
+ @field:ExtensionMode @param:ExtensionMode private val mExtensionMode: Int,
+ @field:LensFacing @param:LensFacing private val mLensFacing: Int
+) {
+ private val mContext =
+ ApplicationProvider.getApplicationContext<Context>()
+
+ private val mEffectMode: EffectMode =
+ ExtensionsTestUtil.extensionModeToEffectMode(mExtensionMode)
+
+ private lateinit var mExtensions: Extensions
+
+ @Before
+ @Throws(Exception::class)
+ fun setUp() {
+ assumeTrue(CameraUtil.deviceHasCamera())
+ val cameraXConfig = Camera2Config.defaultConfig()
+ CameraX.initialize(mContext, cameraXConfig).get()
+ assumeTrue(
+ CameraUtil.hasCameraWithLensFacing(
+ mLensFacing
+ )
+ )
+ assumeTrue(ExtensionsTestUtil.initExtensions(mContext))
+ mExtensions = ExtensionsManager.getExtensions(mContext)
+ }
+
+ @After
+ @Throws(
+ InterruptedException::class,
+ ExecutionException::class,
+ TimeoutException::class
+ )
+ fun cleanUp() {
+ CameraX.shutdown()[10000, TimeUnit.MILLISECONDS]
+ ExtensionsManager.deinit().get()
+ }
+
+ companion object {
+ @JvmStatic
+ @get:Parameterized.Parameters(name = "extension = {0}, facing = {1}")
+ val parameters: Collection<Array<Any>>
+ get() = ExtensionsTestUtil.getAllExtensionsLensFacingCombinations()
+ }
+
+ // TODO: Can be removed after the Extensions class is fully implemented.
+ @Test
+ fun isExtensionAvailable() {
+ val cameraSelector = CameraSelector.Builder().requireLensFacing(mLensFacing).build()
+ val camera = CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector)
+
+ assertThat(
+ ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing) ==
+ mExtensions.isExtensionAvailable(camera, mExtensionMode)
+ ).isTrue()
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
index 93fd396..12ffc3e 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
@@ -129,7 +129,7 @@
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(lensFacing).build();
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
mInstrumentation.runOnMainSync(() -> {
try {
cameraUseCaseAdapter.addUseCases(Collections.singleton(useCase));
@@ -186,7 +186,7 @@
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(lensFacing).build();
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
mInstrumentation.runOnMainSync(() -> {
try {
cameraUseCaseAdapter.addUseCases(Collections.singleton(useCase));
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
index 2de4432..062dd05 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
@@ -150,7 +150,7 @@
Preview useCase = configBuilder.build();
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
mInstrumentation.runOnMainSync(() -> {
// To set the update listener and Preview will change to active state.
useCase.setSurfaceProvider(
@@ -228,7 +228,7 @@
Preview preview = configBuilder.build();
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
mInstrumentation.runOnMainSync(() -> {
// To set the update listener and Preview will change to active state.
preview.setSurfaceProvider(
@@ -284,7 +284,7 @@
Preview preview = configBuilder.build();
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
mInstrumentation.runOnMainSync(() -> {
// To set the update listener and Preview will change to active state.
preview.setSurfaceProvider(
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
index 4b9ee8d..a6e2ba6 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
@@ -39,6 +39,7 @@
import androidx.camera.extensions.BeautyPreviewExtender;
import androidx.camera.extensions.BokehImageCaptureExtender;
import androidx.camera.extensions.BokehPreviewExtender;
+import androidx.camera.extensions.Extensions;
import androidx.camera.extensions.ExtensionsManager;
import androidx.camera.extensions.ExtensionsManager.EffectMode;
import androidx.camera.extensions.ExtensionsManager.ExtensionsAvailability;
@@ -87,6 +88,22 @@
});
}
+ @NonNull
+ public static Collection<Object[]> getAllExtensionsLensFacingCombinations() {
+ return Arrays.asList(new Object[][]{
+ {Extensions.EXTENSION_MODE_BOKEH, CameraSelector.LENS_FACING_FRONT},
+ {Extensions.EXTENSION_MODE_BOKEH, CameraSelector.LENS_FACING_BACK},
+ {Extensions.EXTENSION_MODE_HDR, CameraSelector.LENS_FACING_FRONT},
+ {Extensions.EXTENSION_MODE_HDR, CameraSelector.LENS_FACING_BACK},
+ {Extensions.EXTENSION_MODE_BEAUTY, CameraSelector.LENS_FACING_FRONT},
+ {Extensions.EXTENSION_MODE_BEAUTY, CameraSelector.LENS_FACING_BACK},
+ {Extensions.EXTENSION_MODE_NIGHT, CameraSelector.LENS_FACING_FRONT},
+ {Extensions.EXTENSION_MODE_NIGHT, CameraSelector.LENS_FACING_BACK},
+ {Extensions.EXTENSION_MODE_AUTO, CameraSelector.LENS_FACING_FRONT},
+ {Extensions.EXTENSION_MODE_AUTO, CameraSelector.LENS_FACING_BACK}
+ });
+ }
+
/**
* Initializes the extensions for running the following tests.
*
@@ -108,6 +125,43 @@
return true;
}
+ @Extensions.ExtensionMode
+ public static int effectModeToExtensionMode(@NonNull EffectMode effectMode) {
+ switch (effectMode) {
+ case NORMAL:
+ return Extensions.EXTENSION_MODE_NONE;
+ case BOKEH:
+ return Extensions.EXTENSION_MODE_BOKEH;
+ case HDR:
+ return Extensions.EXTENSION_MODE_HDR;
+ case NIGHT:
+ return Extensions.EXTENSION_MODE_NIGHT;
+ case BEAUTY:
+ return Extensions.EXTENSION_MODE_BEAUTY;
+ case AUTO:
+ return Extensions.EXTENSION_MODE_AUTO;
+ }
+ throw new IllegalArgumentException("Effect mode not found: " + effectMode);
+ }
+
+ public static EffectMode extensionModeToEffectMode(@Extensions.ExtensionMode int mode) {
+ switch (mode) {
+ case Extensions.EXTENSION_MODE_NONE:
+ return EffectMode.NORMAL;
+ case Extensions.EXTENSION_MODE_BOKEH:
+ return EffectMode.BOKEH;
+ case Extensions.EXTENSION_MODE_HDR:
+ return EffectMode.HDR;
+ case Extensions.EXTENSION_MODE_NIGHT:
+ return EffectMode.NIGHT;
+ case Extensions.EXTENSION_MODE_BEAUTY:
+ return EffectMode.BEAUTY;
+ case Extensions.EXTENSION_MODE_AUTO:
+ return EffectMode.AUTO;
+ }
+ throw new IllegalArgumentException("Extension mode not found: " + mode);
+ }
+
/**
* Creates an {@link ImageCapture.Builder} object for specific {@link EffectMode} and
* {@link CameraSelector.LensFacing}.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
index 2b30d8c..8a71864 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
@@ -19,8 +19,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.experimental.UseExperimental;
+import androidx.camera.camera2.interop.Camera2CameraInfo;
+import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraFilter;
+import androidx.camera.core.CameraInfo;
import androidx.camera.core.ExperimentalCameraFilter;
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
@@ -35,8 +38,8 @@
*/
@UseExperimental(markerClass = ExperimentalCameraFilter.class)
public final class ExtensionCameraFilter implements CameraFilter {
- private PreviewExtenderImpl mPreviewExtenderImpl;
- private ImageCaptureExtenderImpl mImageCaptureExtenderImpl;
+ private final PreviewExtenderImpl mPreviewExtenderImpl;
+ private final ImageCaptureExtenderImpl mImageCaptureExtenderImpl;
ExtensionCameraFilter(@Nullable PreviewExtenderImpl previewExtenderImpl) {
mPreviewExtenderImpl = previewExtenderImpl;
@@ -54,6 +57,7 @@
mImageCaptureExtenderImpl = imageCaptureExtenderImpl;
}
+ @UseExperimental(markerClass = ExperimentalCamera2Interop.class)
@NonNull
@Override
public LinkedHashSet<Camera> filter(@NonNull LinkedHashSet<Camera> cameras) {
@@ -62,6 +66,7 @@
Preconditions.checkState(camera instanceof CameraInternal,
"The camera doesn't contain internal implementation.");
String cameraId = ((CameraInternal) camera).getCameraInfoInternal().getCameraId();
+ CameraInfo cameraInfo = camera.getCameraInfo();
boolean available = true;
@@ -69,12 +74,12 @@
if (mPreviewExtenderImpl != null) {
available =
mPreviewExtenderImpl.isExtensionAvailable(cameraId,
- CameraUtil.getCameraCharacteristics(cameraId));
+ Camera2CameraInfo.extractCameraCharacteristics(cameraInfo));
}
// If image capture extender impl isn't null, check if the camera id is supported.
if (mImageCaptureExtenderImpl != null) {
available = mImageCaptureExtenderImpl.isExtensionAvailable(cameraId,
- CameraUtil.getCameraCharacteristics(cameraId));
+ Camera2CameraInfo.extractCameraCharacteristics(cameraInfo));
}
if (available) {
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
index 7d1e65b..42cd607 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
@@ -21,11 +21,26 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
+import androidx.annotation.experimental.UseExperimental;
import androidx.camera.core.Camera;
+import androidx.camera.core.CameraFilter;
+import androidx.camera.core.ExperimentalCameraFilter;
import androidx.camera.core.UseCase;
+import androidx.camera.core.impl.CameraFilters;
+import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
+import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl;
+import androidx.camera.extensions.impl.BokehImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.BokehPreviewExtenderImpl;
+import androidx.camera.extensions.impl.HdrImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.HdrPreviewExtenderImpl;
+import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.LinkedHashSet;
import java.util.List;
/**
@@ -127,10 +142,51 @@
* #checkUseCases(Camera, List, int)}.
*
* @param camera The Camera to check if it supports the extension.
- * @param mode The extension mode to check
+ * @param mode The extension mode to check
*/
+ @UseExperimental(markerClass = ExperimentalCameraFilter.class)
public boolean isExtensionAvailable(@NonNull Camera camera, @ExtensionMode int mode) {
- throw new UnsupportedOperationException("not yet implemented");
+ CameraFilter filter = getFilter(mode);
+
+ // Extension is available for the camera if it contains a CameraInternal which supports
+ // the extension
+ return !filter.filter(new LinkedHashSet<>(camera.getCameraInternals())).isEmpty();
+ }
+
+ @UseExperimental(markerClass = ExperimentalCameraFilter.class)
+ private CameraFilter getFilter(@ExtensionMode int mode) {
+ CameraFilter filter;
+ try {
+ switch (mode) {
+ case EXTENSION_MODE_BOKEH:
+ filter = new ExtensionCameraFilter(new BokehPreviewExtenderImpl(),
+ new BokehImageCaptureExtenderImpl());
+ break;
+ case EXTENSION_MODE_HDR:
+ filter = new ExtensionCameraFilter(new HdrPreviewExtenderImpl(),
+ new HdrImageCaptureExtenderImpl());
+ break;
+ case EXTENSION_MODE_NIGHT:
+ filter = new ExtensionCameraFilter(new NightPreviewExtenderImpl(),
+ new NightImageCaptureExtenderImpl());
+ break;
+ case EXTENSION_MODE_BEAUTY:
+ filter = new ExtensionCameraFilter(new BeautyPreviewExtenderImpl(),
+ new BeautyImageCaptureExtenderImpl());
+ break;
+ case EXTENSION_MODE_AUTO:
+ filter = new ExtensionCameraFilter(new AutoPreviewExtenderImpl(),
+ new AutoImageCaptureExtenderImpl());
+ break;
+ case EXTENSION_MODE_NONE:
+ default:
+ filter = CameraFilters.ANY;
+ }
+ } catch (NoClassDefFoundError e) {
+ filter = CameraFilters.NONE;
+ }
+
+ return filter;
}
/**
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
index 1c1fb28..a5b7bed 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
@@ -22,6 +22,7 @@
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.UseCase;
+import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Lifecycle.State;
@@ -223,15 +224,24 @@
}
}
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Camera interface
+ ////////////////////////////////////////////////////////////////////////////////////////////////
@NonNull
@Override
public CameraControl getCameraControl() {
- return mCameraUseCaseAdapter.getCameraControlInternal();
+ return mCameraUseCaseAdapter.getCameraControl();
}
@NonNull
@Override
public CameraInfo getCameraInfo() {
- return mCameraUseCaseAdapter.getCameraInfoInternal();
+ return mCameraUseCaseAdapter.getCameraInfo();
+ }
+
+ @NonNull
+ @Override
+ public Collection<CameraInternal> getCameraInternals() {
+ return mCameraUseCaseAdapter.getCameraInternals();
}
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index bb93ca4..3c9294a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -260,17 +260,23 @@
/**
- * Retrieves the CameraUseCaseAdapter that would be created with the given CameraSelector.
+ * Creates the CameraUseCaseAdapter that would be created with the given CameraSelector.
*
* <p> This requires that {@link CameraX#initialize(Context, CameraXConfig)} has been called
* to properly initialize the cameras.
*
+ * <p>A new CameraUseCaseAdapter instance will be created every time this method is called.
+ * UseCases previously attached to CameraUseCasesAdapters returned by this method or
+ * {@link #createCameraAndAttachUseCase(Context, CameraSelector, UseCase...)} will not be
+ * attached to the new CameraUseCaseAdapter returned by this method.
+ *
* @param context The context used to initialize CameraX
* @param cameraSelector The selector to select cameras with.
* @hide
*/
@RestrictTo(RestrictTo.Scope.TESTS)
- public static CameraUseCaseAdapter getCameraUseCaseAdapter(@NonNull Context context,
+ @NonNull
+ public static CameraUseCaseAdapter createCameraUseCaseAdapter(@NonNull Context context,
@NonNull CameraSelector cameraSelector) {
try {
CameraX cameraX = CameraX.getOrCreateInstance(context).get(5000, TimeUnit.MILLISECONDS);
@@ -284,21 +290,27 @@
}
/**
- * Retrieves the CameraUseCaseAdapter that would be created with the given CameraSelector and
+ * Creates the CameraUseCaseAdapter that would be created with the given CameraSelector and
* attaches the UseCases.
*
* <p> This requires that {@link CameraX#initialize(Context, CameraXConfig)} has been called
* to properly initialize the cameras.
*
+ * <p>A new CameraUseCaseAdapter instance will be created every time this method is called.
+ * UseCases previously attached to CameraUseCasesAdapters returned by this method or
+ * {@link #createCameraUseCaseAdapter(Context, CameraSelector)} will not be
+ * attached to the new CameraUseCaseAdapter returned by this method.
+ *
* @param context The context used to initialize CameraX
* @param cameraSelector The selector to select cameras with.
* @param useCases The UseCases to attach to the CameraUseCaseAdapter.
* @hide
*/
@RestrictTo(RestrictTo.Scope.TESTS)
- public static CameraUseCaseAdapter getCameraAndAttachUseCase(@NonNull Context context,
+ @NonNull
+ public static CameraUseCaseAdapter createCameraAndAttachUseCase(@NonNull Context context,
@NonNull CameraSelector cameraSelector, @NonNull UseCase... useCases) {
- CameraUseCaseAdapter cameraUseCaseAdapter = getCameraUseCaseAdapter(context,
+ CameraUseCaseAdapter cameraUseCaseAdapter = createCameraUseCaseAdapter(context,
cameraSelector);
// TODO(b/160249108) move off of main thread once UseCases can be attached on any
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
index 250af83..3a6ef21 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
@@ -22,8 +22,6 @@
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.camera.core.CameraControl;
-import androidx.camera.core.CameraInfo;
import androidx.camera.core.Logger;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CameraControlInternal;
@@ -378,17 +376,4 @@
// notifySurfaceDetached calls.
mConfiguredDeferrableSurfaces.clear();
}
-
- @NonNull
- @Override
- public CameraControl getCameraControl() {
- return getCameraControlInternal();
- }
-
- @NonNull
- @Override
- public CameraInfo getCameraInfo() {
- return getCameraInfoInternal();
- }
-
}
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 0ec749a..7d99923 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -145,7 +145,7 @@
private final Preview.SurfaceProvider mSurfaceProvider = surfaceRequest -> {
Logger.d(TAG, "Surface requested by Preview.");
- CameraInternal camera = (CameraInternal) surfaceRequest.getCamera();
+ CameraInternal camera = surfaceRequest.getCamera();
mPreviewTransform.setSensorDimensionFlipNeeded(
isSensorDimensionFlipNeeded(camera.getCameraInfo()));
mImplementation = surfaceRequest.isRGBA8888Required() || shouldUseTextureView(
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
index 48f35b2..0aeb641 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/PreviewProcessorTimestampTest.java
@@ -261,7 +261,7 @@
}));
CameraUseCaseAdapter cameraUseCaseAdapter =
- CameraUtil.getCameraUseCaseAdapter(mContext, cameraSelector);
+ CameraUtil.createCameraUseCaseAdapter(mContext, cameraSelector);
try {
cameraUseCaseAdapter.addUseCases(Arrays.asList(preview, imageCapture));
} catch (CameraUseCaseAdapter.CameraException e) {
diff --git a/camera/integration-tests/uiwidgetstestapp/build.gradle b/camera/integration-tests/uiwidgetstestapp/build.gradle
index 7c32484..c6d1b24 100644
--- a/camera/integration-tests/uiwidgetstestapp/build.gradle
+++ b/camera/integration-tests/uiwidgetstestapp/build.gradle
@@ -59,7 +59,7 @@
implementation(project(":camera:camera-view"))
// Android Support Library
- implementation("androidx.appcompat:appcompat:1.1.0")
+ implementation("androidx.appcompat:appcompat:1.2.0")
implementation("androidx.viewpager2:viewpager2:1.0.0")
// Testing framework
@@ -73,5 +73,5 @@
androidTestImplementation(project(':internal-testutils-runtime'))
androidTestImplementation(TRUTH)
debugImplementation(ANDROIDX_TEST_CORE)
- debugImplementation("androidx.fragment:fragment-testing:1.2.3")
+ debugImplementation("androidx.fragment:fragment-testing:1.2.5")
}
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
index f0709a4..c06425b 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
@@ -18,6 +18,7 @@
import android.content.Intent
import android.os.Build
+import android.os.Environment
import android.view.View
import androidx.camera.core.CameraSelector
import androidx.camera.integration.uiwidgets.R
@@ -29,8 +30,8 @@
import androidx.test.uiautomator.UiDevice
import androidx.testutils.withActivity
import com.google.common.truth.Truth.assertThat
-import org.junit.Assume
import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import java.util.concurrent.TimeUnit
/**
@@ -59,17 +60,29 @@
)
CoreAppTestUtil.assumeCompatibleDevice()
- Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing))
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing))
// Clear the device's UI and ensure it's in a natural orientation
CoreAppTestUtil.clearDeviceUI(InstrumentationRegistry.getInstrumentation())
mDevice.setOrientationNatural()
+
+ // Create pictures folder if it doesn't exist on the device. If this fails, abort test.
+ assumeTrue("Failed to create pictures directory", createPicturesFolder())
}
protected fun tearDown() {
mDevice.unfreezeRotation()
}
+ @Suppress("DEPRECATION")
+ private fun createPicturesFolder(): Boolean {
+ val folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ if (folder.exists()) {
+ return true
+ }
+ return folder.mkdir()
+ }
+
protected inline fun <reified A : CameraActivity> verifyRotation(
lensFacing: Int,
captureMode: Int,
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
index 50e8ebd..7cd8d9a 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
@@ -36,6 +36,7 @@
import androidx.camera.core.impl.utils.executor.CameraXExecutors
import androidx.camera.integration.uiwidgets.R
import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_rotations_main.previewView
import java.io.File
@@ -56,7 +57,7 @@
setContentView(R.layout.activity_rotations_main)
mAnalysisExecutor = Executors.newSingleThreadExecutor()
if (shouldRequestPermissionsAtRuntime() && !hasPermissions()) {
- requestPermissions(PERMISSIONS, REQUEST_CODE_PERMISSIONS)
+ ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_CODE_PERMISSIONS)
} else {
setUpCamera()
}
@@ -163,12 +164,12 @@
mCaptureResult = ImageCaptureResult.InMemory(image)
mCaptureDone.release()
image.close()
- Log.d(TAG, "MediaStore captured successful")
+ Log.d(TAG, "InMemory image capture successful")
}
override fun onError(exception: ImageCaptureException) {
mCaptureDone.release()
- Log.e(TAG, "InMemory capture failed", exception)
+ Log.e(TAG, "InMemory image capture failed", exception)
}
})
}
@@ -183,12 +184,12 @@
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
mCaptureDone.release()
- Log.d(TAG, "MediaStore captured successful")
+ Log.d(TAG, "File image capture successful")
}
override fun onError(exception: ImageCaptureException) {
mCaptureDone.release()
- Log.e(TAG, "File capture failed", exception)
+ Log.e(TAG, "File image capture failed", exception)
}
})
}
@@ -204,12 +205,12 @@
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
mCaptureDone.release()
- Log.d(TAG, "MediaStore captured successful")
+ Log.d(TAG, "OutputStream image capture successful")
}
override fun onError(exception: ImageCaptureException) {
mCaptureDone.release()
- Log.e(TAG, "OutputStream capture failed", exception)
+ Log.e(TAG, "OutputStream image capture failed", exception)
}
})
}
@@ -230,12 +231,12 @@
mCaptureResult =
ImageCaptureResult.MediaStore(contentResolver, outputFileResults.savedUri!!)
mCaptureDone.release()
- Log.d(TAG, "MediaStore captured successful")
+ Log.d(TAG, "MediaStore image capture successful")
}
override fun onError(exception: ImageCaptureException) {
mCaptureDone.release()
- Log.e(TAG, "MediaStore capture failed", exception)
+ Log.e(TAG, "MediaStore image capture failed", exception)
}
})
}
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index a5be571..06bf3318 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -86,7 +86,11 @@
}
public final class ButtonConstants {
- method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-hoVAPrg(boolean enabled, androidx.compose.foundation.InteractionState interactionState, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-qDazgog(androidx.compose.foundation.InteractionState interactionState, boolean enabled, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public long defaultButtonBackgroundColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledBackgroundColor);
+ method @androidx.compose.runtime.Composable public long defaultButtonContentColor-Q31_wr0(boolean enabled, long defaultColor, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultOutlinedButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultTextButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
method public androidx.compose.foundation.layout.PaddingValues getDefaultContentPadding();
method public long getDefaultDisabledBackgroundColor();
method public long getDefaultDisabledContentColor();
@@ -112,15 +116,15 @@
}
public final class ButtonKt {
- method @androidx.compose.runtime.Composable public static void Button-Vgmpx9w(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+ method @androidx.compose.runtime.Composable public static void Button-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = ButtonConstants.defaultAnimatedElevation(enabled, interactionState).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = MaterialTheme.colors.primary, long disabledBackgroundColor = ButtonConstants.defaultDisabledBackgroundColor, long contentColor = contentColorFor(backgroundColor), long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void OutlinedButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = ButtonConstants.defaultAnimatedElevation(interactionState, enabled).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = ButtonConstants.defaultButtonBackgroundColor(enabled), long contentColor = ButtonConstants.defaultButtonContentColor(enabled, contentColorFor(backgroundColor)), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void OutlinedButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void TextButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = ButtonConstants.defaultOutlinedButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void TextButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = ButtonConstants.defaultTextButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
}
public final class CardKt {
@@ -567,8 +571,9 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
- method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ field public static final float ContainerAlpha = 0.12f;
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface ThresholdConfig {
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index a5be571..06bf3318 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -86,7 +86,11 @@
}
public final class ButtonConstants {
- method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-hoVAPrg(boolean enabled, androidx.compose.foundation.InteractionState interactionState, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-qDazgog(androidx.compose.foundation.InteractionState interactionState, boolean enabled, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public long defaultButtonBackgroundColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledBackgroundColor);
+ method @androidx.compose.runtime.Composable public long defaultButtonContentColor-Q31_wr0(boolean enabled, long defaultColor, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultOutlinedButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultTextButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
method public androidx.compose.foundation.layout.PaddingValues getDefaultContentPadding();
method public long getDefaultDisabledBackgroundColor();
method public long getDefaultDisabledContentColor();
@@ -112,15 +116,15 @@
}
public final class ButtonKt {
- method @androidx.compose.runtime.Composable public static void Button-Vgmpx9w(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+ method @androidx.compose.runtime.Composable public static void Button-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = ButtonConstants.defaultAnimatedElevation(enabled, interactionState).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = MaterialTheme.colors.primary, long disabledBackgroundColor = ButtonConstants.defaultDisabledBackgroundColor, long contentColor = contentColorFor(backgroundColor), long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void OutlinedButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = ButtonConstants.defaultAnimatedElevation(interactionState, enabled).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = ButtonConstants.defaultButtonBackgroundColor(enabled), long contentColor = ButtonConstants.defaultButtonContentColor(enabled, contentColorFor(backgroundColor)), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void OutlinedButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void TextButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = ButtonConstants.defaultOutlinedButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void TextButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = ButtonConstants.defaultTextButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
}
public final class CardKt {
@@ -567,8 +571,9 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
- method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ field public static final float ContainerAlpha = 0.12f;
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface ThresholdConfig {
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index a5be571..06bf3318 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -86,7 +86,11 @@
}
public final class ButtonConstants {
- method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-hoVAPrg(boolean enabled, androidx.compose.foundation.InteractionState interactionState, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public androidx.compose.animation.core.AnimatedValue<androidx.compose.ui.unit.Dp,androidx.compose.animation.core.AnimationVector1D> defaultAnimatedElevation-qDazgog(androidx.compose.foundation.InteractionState interactionState, boolean enabled, float defaultElevation = 2.dp, float pressedElevation = 8.dp, float disabledElevation = 0.dp);
+ method @androidx.compose.runtime.Composable public long defaultButtonBackgroundColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledBackgroundColor);
+ method @androidx.compose.runtime.Composable public long defaultButtonContentColor-Q31_wr0(boolean enabled, long defaultColor, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultOutlinedButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
+ method @androidx.compose.runtime.Composable public long defaultTextButtonContentColor-Q31_wr0(boolean enabled, long defaultColor = MaterialTheme.colors.primary, long disabledColor = defaultDisabledContentColor);
method public androidx.compose.foundation.layout.PaddingValues getDefaultContentPadding();
method public long getDefaultDisabledBackgroundColor();
method public long getDefaultDisabledContentColor();
@@ -112,15 +116,15 @@
}
public final class ButtonKt {
- method @androidx.compose.runtime.Composable public static void Button-Vgmpx9w(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+ method @androidx.compose.runtime.Composable public static void Button-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = ButtonConstants.defaultAnimatedElevation(enabled, interactionState).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = MaterialTheme.colors.primary, long disabledBackgroundColor = ButtonConstants.defaultDisabledBackgroundColor, long contentColor = contentColorFor(backgroundColor), long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void OutlinedButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = ButtonConstants.defaultAnimatedElevation(interactionState, enabled).value, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = ButtonConstants.defaultButtonBackgroundColor(enabled), long contentColor = ButtonConstants.defaultButtonContentColor(enabled, contentColorFor(backgroundColor)), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void OutlinedButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static inline void TextButton-UavO1Bo(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = ButtonConstants.defaultOutlinedBorder, long backgroundColor = MaterialTheme.colors.surface, long contentColor = ButtonConstants.defaultOutlinedButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static inline void TextButton-M91Patw(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.compose.ui.Modifier modifier = Modifier, boolean enabled = true, androidx.compose.foundation.InteractionState interactionState = remember({
return <init>()
-}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = MaterialTheme.colors.primary, long disabledContentColor = ButtonConstants.defaultDisabledContentColor, androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+}), float elevation = 0.dp, androidx.compose.ui.graphics.Shape shape = small, androidx.compose.foundation.BorderStroke? border = null, long backgroundColor = Color.Transparent, long contentColor = ButtonConstants.defaultTextButtonContentColor(enabled), androidx.compose.foundation.layout.PaddingValues contentPadding = ButtonConstants.DefaultTextContentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
}
public final class CardKt {
@@ -567,8 +571,9 @@
}
public final class TextFieldKt {
- method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
- method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface, androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-enE39lU(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ method @androidx.compose.runtime.Composable public static void TextField-tHV9mug(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, androidx.compose.ui.Modifier modifier = Modifier, androidx.compose.ui.text.TextStyle textStyle = currentTextStyle(), kotlin.jvm.functions.Function0<kotlin.Unit>? label = null, kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder = null, kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon = null, kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon = null, boolean isErrorValue = false, androidx.compose.ui.text.input.VisualTransformation visualTransformation = VisualTransformation.None, androidx.compose.ui.text.input.KeyboardType keyboardType = KeyboardType.Text, androidx.compose.ui.text.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function2<? super androidx.compose.ui.text.input.ImeAction,? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> _, _ -> }, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> long activeColor = MaterialTheme.colors.primary, long inactiveColor = MaterialTheme.colors.onSurface, long errorColor = MaterialTheme.colors.error, long backgroundColor = MaterialTheme.colors.onSurface.copy(ContainerAlpha), androidx.compose.ui.graphics.Shape shape = MaterialTheme.shapes.small.copy(ZeroCornerSize, ZeroCornerSize));
+ field public static final float ContainerAlpha = 0.12f;
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface ThresholdConfig {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ButtonTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ButtonTest.kt
index d62ada4..725776a 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ButtonTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ButtonTest.kt
@@ -397,7 +397,10 @@
Button(
>
enabled = false,
- backgroundColor = Color.Red,
+ backgroundColor = ButtonConstants.defaultButtonBackgroundColor(
+ enabled = false,
+ defaultColor = Color.Red
+ ),
shape = RectangleShape
) {}
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
index 2201056..b10ec7e 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
@@ -43,7 +43,6 @@
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.node.Ref
import androidx.compose.ui.onPositioned
@@ -697,7 +696,7 @@
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- fun testTextField_alphaNotSet_toBackgroundColorAndTransparentColors() {
+ fun testTextField_alphaNotApplied_toCustomBackgroundColorAndTransparentColors() {
val latch = CountDownLatch(1)
rule.setMaterialContent {
@@ -717,14 +716,12 @@
}
}
- val expectedColor = Color.Blue.copy(alpha = 0.12f).compositeOver(Color.White)
-
rule.onNodeWithTag(TextfieldTag)
.captureToBitmap()
.assertShape(
density = rule.density,
backgroundColor = Color.White,
- shapeColor = expectedColor,
+ shapeColor = Color.Blue,
shape = RectangleShape,
// avoid elevation artifacts
shapeOverlapPixelCount = with(rule.density) { 1.dp.toPx() }
@@ -738,7 +735,7 @@
.assertShape(
density = rule.density,
backgroundColor = Color.White,
- shapeColor = expectedColor,
+ shapeColor = Color.Blue,
shape = RectangleShape,
// avoid elevation artifacts
shapeOverlapPixelCount = with(rule.density) { 1.dp.toPx() }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
index 5fa4360..34f0015 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt
@@ -84,9 +84,7 @@
* @param shape Defines the button's shape as well as its shadow
* @param border Border to draw around the button
* @param backgroundColor The background color. Use [Color.Transparent] to have no color
- * @param disabledBackgroundColor The background color used when [enabled] is false
* @param contentColor The preferred content color. Will be used by text and iconography
- * @param disabledContentColor The preferred content color used when [enabled] is false
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@Composable
@@ -95,13 +93,14 @@
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
- elevation: Dp = ButtonConstants.defaultAnimatedElevation(enabled, interactionState).value,
+ elevation: Dp = ButtonConstants.defaultAnimatedElevation(interactionState, enabled).value,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
- backgroundColor: Color = MaterialTheme.colors.primary,
- disabledBackgroundColor: Color = ButtonConstants.defaultDisabledBackgroundColor,
- contentColor: Color = contentColorFor(backgroundColor),
- disabledContentColor: Color = ButtonConstants.defaultDisabledContentColor,
+ backgroundColor: Color = ButtonConstants.defaultButtonBackgroundColor(enabled),
+ contentColor: Color = ButtonConstants.defaultButtonContentColor(
+ enabled,
+ contentColorFor(backgroundColor)
+ ),
contentPadding: PaddingValues = ButtonConstants.DefaultContentPadding,
content: @Composable RowScope.() -> Unit
) {
@@ -111,8 +110,8 @@
// aosp/1361921)
Surface(
shape = shape,
- color = if (enabled) backgroundColor else disabledBackgroundColor,
- contentColor = if (enabled) contentColor else disabledContentColor,
+ color = backgroundColor,
+ contentColor = contentColor,
border = border,
elevation = elevation,
modifier = modifier.clickable(
@@ -175,7 +174,6 @@
* @param border Border to draw around the button
* @param backgroundColor The background color. Use [Color.Transparent] to have no color
* @param contentColor The preferred content color. Will be used by text and iconography
- * @param disabledContentColor The preferred content color used when [enabled] is false
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@Composable
@@ -188,8 +186,7 @@
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = ButtonConstants.defaultOutlinedBorder,
backgroundColor: Color = MaterialTheme.colors.surface,
- contentColor: Color = MaterialTheme.colors.primary,
- disabledContentColor: Color = ButtonConstants.defaultDisabledContentColor,
+ contentColor: Color = ButtonConstants.defaultOutlinedButtonContentColor(enabled),
contentPadding: PaddingValues = ButtonConstants.DefaultContentPadding,
noinline content: @Composable RowScope.() -> Unit
) = Button(
@@ -201,9 +198,7 @@
shape = shape,
border = border,
backgroundColor = backgroundColor,
- disabledBackgroundColor = backgroundColor,
contentColor = contentColor,
- disabledContentColor = disabledContentColor,
contentPadding = contentPadding,
content = content
)
@@ -240,7 +235,6 @@
* @param border Border to draw around the button
* @param backgroundColor The background color. Use [Color.Transparent] to have no color
* @param contentColor The preferred content color. Will be used by text and iconography
- * @param disabledContentColor The preferred content color used when [enabled] is false
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@Composable
@@ -253,8 +247,7 @@
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
backgroundColor: Color = Color.Transparent,
- contentColor: Color = MaterialTheme.colors.primary,
- disabledContentColor: Color = ButtonConstants.defaultDisabledContentColor,
+ contentColor: Color = ButtonConstants.defaultTextButtonContentColor(enabled),
contentPadding: PaddingValues = ButtonConstants.DefaultTextContentPadding,
noinline content: @Composable RowScope.() -> Unit
) = Button(
@@ -266,9 +259,7 @@
shape = shape,
border = border,
backgroundColor = backgroundColor,
- disabledBackgroundColor = backgroundColor,
contentColor = contentColor,
- disabledContentColor = disabledContentColor,
contentPadding = contentPadding,
content = content
)
@@ -292,13 +283,13 @@
/**
* The default min width applied for the [Button].
- * Note that you can override it by applying [Modifier.widthIn] directly on [Button].
+ * Note that you can override it by applying Modifier.widthIn directly on [Button].
*/
val DefaultMinWidth = 64.dp
/**
* The default min width applied for the [Button].
- * Note that you can override it by applying [Modifier.heightIn] directly on [Button].
+ * Note that you can override it by applying Modifier.heightIn directly on [Button].
*/
val DefaultMinHeight = 36.dp
@@ -329,10 +320,10 @@
* Represents the default elevation for a button in different [Interaction]s, and how the
* elevation animates between them.
*
- * @param enabled whether the [Button] is enabled or not. If the [Button] is disabled then
- * [disabledElevation] will always be used, regardless of the state of [interactionState].
* @param interactionState the [InteractionState] for this [Button], representing the current
* visual state, such as whether it is [Interaction.Pressed] or not.
+ * @param enabled whether the [Button] is enabled or not. If the [Button] is disabled then
+ * [disabledElevation] will always be used, regardless of the state of [interactionState].
* @param defaultElevation the elevation to use when the [Button] is [enabled], and has no
* other [Interaction]s
* @param pressedElevation the elevation to use when the [Button] is [enabled] and
@@ -341,8 +332,8 @@
*/
@Composable
fun defaultAnimatedElevation(
- enabled: Boolean,
interactionState: InteractionState,
+ enabled: Boolean,
defaultElevation: Dp = 2.dp,
pressedElevation: Dp = 8.dp,
// focused: Dp = 4.dp,
@@ -387,7 +378,64 @@
}
/**
- * The default disabled background color used by Contained [Button]s
+ * Returns the recommended background color for a [Button] based on its current state.
+ *
+ * @param enabled whether the Button is enabled or not
+ * @param defaultColor the color to use when enabled
+ * @param disabledColor the color to use when disabled
+ */
+ @Composable
+ fun defaultButtonBackgroundColor(
+ enabled: Boolean,
+ defaultColor: Color = MaterialTheme.colors.primary,
+ disabledColor: Color = defaultDisabledBackgroundColor
+ ): Color = if (enabled) defaultColor else disabledColor
+
+ /**
+ * Returns the recommended content color for a [Button] based on its current state.
+ *
+ * @param defaultColor the content color to use when enabled. This should typically be
+ * [contentColorFor] the background color provided to the Button.
+ * @param enabled whether the Button is enabled or not
+ * @param disabledColor the content color to use when disabled
+ */
+ @Composable
+ fun defaultButtonContentColor(
+ enabled: Boolean,
+ defaultColor: Color,
+ disabledColor: Color = defaultDisabledContentColor
+ ): Color = if (enabled) defaultColor else disabledColor
+
+ /**
+ * Returns the recommended content color for an [OutlinedButton] based on its current state.
+ *
+ * @param enabled whether the OutlinedButton is enabled or not
+ * @param defaultColor the content color to use when enabled
+ * @param disabledColor the content color to use when disabled
+ */
+ @Composable
+ fun defaultOutlinedButtonContentColor(
+ enabled: Boolean,
+ defaultColor: Color = MaterialTheme.colors.primary,
+ disabledColor: Color = defaultDisabledContentColor
+ ): Color = if (enabled) defaultColor else disabledColor
+
+ /**
+ * Returns the recommended content color for a [TextButton] based on its current state.
+ *
+ * @param enabled whether the TextButton is enabled or not
+ * @param defaultColor the content color to use when enabled
+ * @param disabledColor the content color to use when disabled
+ */
+ @Composable
+ fun defaultTextButtonContentColor(
+ enabled: Boolean,
+ defaultColor: Color = MaterialTheme.colors.primary,
+ disabledColor: Color = defaultDisabledContentColor
+ ): Color = if (enabled) defaultColor else disabledColor
+
+ /**
+ * The default disabled background color used by [Button]
*/
@Composable
val defaultDisabledBackgroundColor
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
index cdb7b94..42c6169 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
@@ -134,8 +134,7 @@
* focus, and the color of the label and bottom indicator when the text field is not in focus
* @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
* used when [isErrorValue] is set to true
- * @param backgroundColor the background color of the text field's container. To the color provided
- * here there will be applied a transparency alpha defined by Material Design specifications
+ * @param backgroundColor the background color of the text field's container
* @param shape the shape of the text field's container
*/
@Composable
@@ -157,7 +156,7 @@
activeColor: Color = MaterialTheme.colors.primary,
inactiveColor: Color = MaterialTheme.colors.onSurface,
errorColor: Color = MaterialTheme.colors.error,
- backgroundColor: Color = MaterialTheme.colors.onSurface,
+ backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContainerAlpha),
shape: Shape =
MaterialTheme.shapes.small.copy(bottomLeft = ZeroCornerSize, bottomRight = ZeroCornerSize)
) {
@@ -254,8 +253,7 @@
* focus, and the color of the label and bottom indicator when the text field is not in focus
* @param errorColor the alternative color of the label, bottom indicator, cursor and trailing icon
* used when [isErrorValue] is set to true
- * @param backgroundColor the background color of the text field's container. To the color provided
- * here there will be applied a transparency alpha defined by Material Design specifications
+ * @param backgroundColor the background color of the text field's container
* @param shape the shape of the text field's container
*/
@Composable
@@ -277,7 +275,7 @@
activeColor: Color = MaterialTheme.colors.primary,
inactiveColor: Color = MaterialTheme.colors.onSurface,
errorColor: Color = MaterialTheme.colors.error,
- backgroundColor: Color = MaterialTheme.colors.onSurface,
+ backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContainerAlpha),
shape: Shape =
MaterialTheme.shapes.small.copy(bottomLeft = ZeroCornerSize, bottomRight = ZeroCornerSize)
) {
@@ -325,7 +323,7 @@
IconsWithTextFieldLayout(
modifier = modifier
.background(
- color = backgroundColor.applyAlpha(alpha = ContainerAlpha),
+ color = backgroundColor,
shape = shape
)
.drawIndicatorLine(
@@ -623,4 +621,4 @@
private val FirstBaselineOffset = 20.dp
private val LastBaselineOffset = 10.dp
private val TextFieldTopPadding = 4.dp
-private const val ContainerAlpha = 0.12f
\ No newline at end of file
+const val ContainerAlpha = 0.12f
\ No newline at end of file
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
index 3ee2762..ebf86a0 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
@@ -250,8 +250,8 @@
* Builds a LiveData that has values yielded from the given [block] that executes on a
* [LiveDataScope].
*
- * The [block] starts executing when the returned [LiveData] becomes active ([LiveData.onActive]).
- * If the [LiveData] becomes inactive ([LiveData.onInactive]) while the [block] is executing, it
+ * The [block] starts executing when the returned [LiveData] becomes [active](LiveData.onActive).
+ * If the [LiveData] becomes [inactive](LiveData.onInactive) while the [block] is executing, it
* will be cancelled after [timeoutInMs] milliseconds unless the [LiveData] becomes active again
* before that timeout (to gracefully handle cases like Activity rotation). Any value
* [LiveDataScope.emit]ed from a cancelled [block] will be ignored.
@@ -269,6 +269,12 @@
* coroutines documentation for details
* https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html.
*
+ * The [timeoutInMs] can be changed to fit different use cases better, for example increasing it
+ * will give more time to the [block] to complete even if [LiveData] is inactive. It is good for
+ * cases when [block] is finite (meaning it can complete successfully) and is costly to restart.
+ * Otherwise if a [block] is cheap to restart, decreasing the [timeoutInMs] value will allow to
+ * yield less values that aren't consumed by anything.
+ *
* ```
* // a simple LiveData that receives value 3, 3 seconds after being observed for the first time.
* val data : LiveData<Int> = liveData {
@@ -355,8 +361,8 @@
* Builds a LiveData that has values yielded from the given [block] that executes on a
* [LiveDataScope].
*
- * The [block] starts executing when the returned [LiveData] becomes active ([LiveData.onActive]).
- * If the [LiveData] becomes inactive ([LiveData.onInactive]) while the [block] is executing, it
+ * The [block] starts executing when the returned [LiveData] becomes [active](LiveData.onActive).
+ * If the [LiveData] becomes [inactive](LiveData.onInactive) while the [block] is executing, it
* will be cancelled after the [timeout] duration unless the [LiveData] becomes active again
* before that timeout (to gracefully handle cases like Activity rotation). Any value
* [LiveDataScope.emit]ed from a cancelled [block] will be ignored.
@@ -374,6 +380,12 @@
* coroutines documentation for details
* https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html.
*
+ * The [timeout] can be changed to fit different use cases better, for example increasing it
+ * will give more time to the [block] to complete even if [LiveData] is inactive. It is good for
+ * cases when [block] is finite (meaning it can complete successfully) and is costly to restart.
+ * Otherwise if a [block] is cheap to restart, decreasing the [timeout] value will allow to
+ * yield less values that aren't consumed by anything.
+ *
* ```
* // a simple LiveData that receives value 3, 3 seconds after being observed for the first time.
* val data : LiveData<Int> = liveData {
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
index 2e4e180..c11200d8 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
@@ -56,6 +56,11 @@
* expected to throw, you can use [catch operator][kotlinx.coroutines.flow.catch] on upstream flow
* to emit a helpful error object.
*
+ * The [timeoutInMs] can be changed to fit different use cases better, for example increasing it
+ * will give more time to flow to complete before being canceled and is good for finite flows
+ * that are costly to restart. Otherwise if a flow is cheap to restart decreasing the [timeoutInMs]
+ * value will allow to produce less values that aren't consumed by anything.
+ *
* @param context The CoroutineContext to collect the upstream flow in. Defaults to
* [EmptyCoroutineContext] combined with
* [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate]
@@ -125,6 +130,11 @@
* expected to throw, you can use [catch operator][kotlinx.coroutines.flow.catch] on upstream flow
* to emit a helpful error object.
*
+ * The [timeout] can be changed to fit different use cases better, for example increasing it
+ * will give more time to flow to complete before being canceled and is good for finite flows
+ * that are costly to restart. Otherwise if a flow is cheap to restart decreasing the [timeout]
+ * value will allow to produce less values that aren't consumed by anything.
+ *
* @param context The CoroutineContext to collect the upstream flow in. Defaults to
* [EmptyCoroutineContext] combined with
* [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate]
diff --git a/media2/common/api/1.1.0-beta01.txt b/media2/common/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..91a34fe
--- /dev/null
+++ b/media2/common/api/1.1.0-beta01.txt
@@ -0,0 +1,273 @@
+// Signature format: 3.0
+package androidx.media2.common {
+
+ public class CallbackMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media2.common.DataSourceCallback getDataSourceCallback();
+ }
+
+ public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
+ method public androidx.media2.common.CallbackMediaItem build();
+ method public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
+ }
+
+ public abstract class DataSourceCallback implements java.io.Closeable {
+ ctor public DataSourceCallback();
+ method public abstract long getSize() throws java.io.IOException;
+ method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+ }
+
+ public class FileMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+ method public long getFileDescriptorLength();
+ method public long getFileDescriptorOffset();
+ method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+ field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
+ method public androidx.media2.common.FileMediaItem build();
+ method public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
+ method public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
+ }
+
+ public class MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+ method public long getEndPosition();
+ method public androidx.media2.common.MediaMetadata? getMetadata();
+ method public long getStartPosition();
+ method public void setMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static class MediaItem.Builder {
+ ctor public MediaItem.Builder();
+ method public androidx.media2.common.MediaItem build();
+ method public androidx.media2.common.MediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.MediaItem.Builder setStartPosition(long);
+ }
+
+ public final class MediaMetadata implements androidx.versionedparcelable.VersionedParcelable {
+ method public boolean containsKey(String);
+ method public android.graphics.Bitmap? getBitmap(String);
+ method public android.os.Bundle? getExtras();
+ method public float getFloat(String);
+ method public long getLong(String);
+ method public String? getMediaId();
+ method public androidx.media2.common.Rating? getRating(String);
+ method public String? getString(String);
+ method public CharSequence? getText(String);
+ method public java.util.Set<java.lang.String!> keySet();
+ method public int size();
+ field public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
+ field public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
+ field public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
+ field public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
+ field public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
+ field public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
+ field public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
+ field public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
+ field public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
+ field public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+ field public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+ field public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+ field public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+ field public static final String METADATA_KEY_ART = "android.media.metadata.ART";
+ field public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+ field public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+ field public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+ field public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
+ field public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+ field public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+ field public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
+ field public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+ field public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+ field public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+ field public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+ field public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+ field public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+ field public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
+ field public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+ field public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
+ field public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+ field public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+ field public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+ field public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+ field public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
+ field public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
+ field public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+ field public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+ field public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+ field public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+ field public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+ field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+ field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+ field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+ }
+
+ public static final class MediaMetadata.Builder {
+ ctor public MediaMetadata.Builder();
+ ctor public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
+ method public androidx.media2.common.MediaMetadata build();
+ method public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
+ method public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
+ method public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
+ method public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
+ method public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
+ method public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
+ method public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
+ }
+
+ public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
+ method public boolean isRated();
+ }
+
+ public abstract class SessionPlayer implements java.io.Closeable {
+ ctor public SessionPlayer();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method @CallSuper public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public abstract long getBufferedPosition();
+ method public abstract int getBufferingState();
+ method protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
+ method public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
+ method public abstract long getCurrentPosition();
+ method public abstract long getDuration();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
+ method public abstract float getPlaybackSpeed();
+ method public abstract int getPlayerState();
+ method public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
+ method public abstract int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+ method public abstract int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
+ field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
+ field public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
+ field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
+ field public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
+ field public static final int PLAYER_STATE_ERROR = 3; // 0x3
+ field public static final int PLAYER_STATE_IDLE = 0; // 0x0
+ field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
+ field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
+ field public static final int REPEAT_MODE_ALL = 2; // 0x2
+ field public static final int REPEAT_MODE_GROUP = 3; // 0x3
+ field public static final int REPEAT_MODE_NONE = 0; // 0x0
+ field public static final int REPEAT_MODE_ONE = 1; // 0x1
+ field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+ field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+ field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+ field public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
+ }
+
+ public abstract static class SessionPlayer.PlayerCallback {
+ ctor public SessionPlayer.PlayerCallback();
+ method public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
+ method public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
+ method public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem);
+ method public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
+ method public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
+ method public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
+ method public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
+ }
+
+ public static class SessionPlayer.PlayerResult {
+ ctor public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
+ method public long getCompletionTime();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
+ field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
+ field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
+ field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa
+ field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc
+ field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public static class SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
+ method public android.media.MediaFormat? getFormat();
+ method public int getId();
+ method public java.util.Locale getLanguage();
+ method public int getTrackType();
+ method public boolean isSelectable();
+ field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+ field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
+ field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
+ field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+ }
+
+ public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SubtitleData(long, long, byte[]);
+ method public byte[] getData();
+ method public long getDurationUs();
+ method public long getStartTimeUs();
+ }
+
+ public class UriMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+ method public android.net.Uri getUri();
+ method public java.util.List<java.net.HttpCookie!>? getUriCookies();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
+ }
+
+ public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public UriMediaItem.Builder(android.net.Uri);
+ ctor public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
+ method public androidx.media2.common.UriMediaItem build();
+ method public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
+ }
+
+ public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
+ method @IntRange(from=0) public int getHeight();
+ method @IntRange(from=0) public int getWidth();
+ }
+
+}
+
diff --git a/media2/common/api/public_plus_experimental_1.1.0-beta01.txt b/media2/common/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..ecd925d
--- /dev/null
+++ b/media2/common/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,273 @@
+// Signature format: 3.0
+package androidx.media2.common {
+
+ public class CallbackMediaItem extends androidx.media2.common.MediaItem {
+ method public androidx.media2.common.DataSourceCallback getDataSourceCallback();
+ }
+
+ public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
+ method public androidx.media2.common.CallbackMediaItem build();
+ method public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
+ }
+
+ public abstract class DataSourceCallback implements java.io.Closeable {
+ ctor public DataSourceCallback();
+ method public abstract long getSize() throws java.io.IOException;
+ method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+ }
+
+ public class FileMediaItem extends androidx.media2.common.MediaItem {
+ method public long getFileDescriptorLength();
+ method public long getFileDescriptorOffset();
+ method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+ field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
+ method public androidx.media2.common.FileMediaItem build();
+ method public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
+ method public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class MediaItem extends androidx.versionedparcelable.CustomVersionedParcelable {
+ method public long getEndPosition();
+ method public androidx.media2.common.MediaMetadata? getMetadata();
+ method public long getStartPosition();
+ method public void setMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static class MediaItem.Builder {
+ ctor public MediaItem.Builder();
+ method public androidx.media2.common.MediaItem build();
+ method public androidx.media2.common.MediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.MediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public final class MediaMetadata extends androidx.versionedparcelable.CustomVersionedParcelable {
+ method public boolean containsKey(String);
+ method public android.graphics.Bitmap? getBitmap(String);
+ method public android.os.Bundle? getExtras();
+ method public float getFloat(String);
+ method public long getLong(String);
+ method public String? getMediaId();
+ method public androidx.media2.common.Rating? getRating(String);
+ method public String? getString(String);
+ method public CharSequence? getText(String);
+ method public java.util.Set<java.lang.String!> keySet();
+ method public int size();
+ field public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
+ field public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
+ field public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
+ field public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
+ field public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
+ field public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
+ field public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
+ field public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
+ field public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
+ field public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+ field public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+ field public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+ field public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+ field public static final String METADATA_KEY_ART = "android.media.metadata.ART";
+ field public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+ field public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+ field public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+ field public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
+ field public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+ field public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+ field public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
+ field public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+ field public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+ field public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+ field public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+ field public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+ field public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+ field public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
+ field public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+ field public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
+ field public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+ field public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+ field public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+ field public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+ field public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
+ field public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
+ field public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+ field public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+ field public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+ field public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+ field public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+ field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+ field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+ field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+ }
+
+ public static final class MediaMetadata.Builder {
+ ctor public MediaMetadata.Builder();
+ ctor public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
+ method public androidx.media2.common.MediaMetadata build();
+ method public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
+ method public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
+ method public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
+ method public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
+ method public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
+ method public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
+ method public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
+ }
+
+ public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
+ method public boolean isRated();
+ }
+
+ public abstract class SessionPlayer implements java.io.Closeable {
+ ctor public SessionPlayer();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method @CallSuper public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public abstract long getBufferedPosition();
+ method public abstract int getBufferingState();
+ method protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
+ method public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
+ method public abstract long getCurrentPosition();
+ method public abstract long getDuration();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
+ method public abstract float getPlaybackSpeed();
+ method public abstract int getPlayerState();
+ method public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
+ method public abstract int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+ method public abstract int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
+ field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
+ field public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
+ field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
+ field public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
+ field public static final int PLAYER_STATE_ERROR = 3; // 0x3
+ field public static final int PLAYER_STATE_IDLE = 0; // 0x0
+ field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
+ field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
+ field public static final int REPEAT_MODE_ALL = 2; // 0x2
+ field public static final int REPEAT_MODE_GROUP = 3; // 0x3
+ field public static final int REPEAT_MODE_NONE = 0; // 0x0
+ field public static final int REPEAT_MODE_ONE = 1; // 0x1
+ field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+ field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+ field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+ field public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
+ }
+
+ public abstract static class SessionPlayer.PlayerCallback {
+ ctor public SessionPlayer.PlayerCallback();
+ method public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
+ method public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
+ method public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem);
+ method public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
+ method public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
+ method public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
+ method public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
+ }
+
+ public static class SessionPlayer.PlayerResult {
+ ctor public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
+ method public long getCompletionTime();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
+ field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
+ field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
+ field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa
+ field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc
+ field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public static class SessionPlayer.TrackInfo extends androidx.versionedparcelable.CustomVersionedParcelable {
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
+ method public android.media.MediaFormat? getFormat();
+ method public int getId();
+ method public java.util.Locale getLanguage();
+ method public int getTrackType();
+ method public boolean isSelectable();
+ field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+ field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
+ field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
+ field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SubtitleData(long, long, byte[]);
+ method public byte[] getData();
+ method public long getDurationUs();
+ method public long getStartTimeUs();
+ }
+
+ public class UriMediaItem extends androidx.media2.common.MediaItem {
+ method public android.net.Uri getUri();
+ method public java.util.List<java.net.HttpCookie!>? getUriCookies();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
+ }
+
+ public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public UriMediaItem.Builder(android.net.Uri);
+ ctor public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
+ method public androidx.media2.common.UriMediaItem build();
+ method public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
+ method @IntRange(from=0) public int getHeight();
+ method @IntRange(from=0) public int getWidth();
+ }
+
+}
+
diff --git a/media2/common/api/res-1.1.0-beta01.txt b/media2/common/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media2/common/api/res-1.1.0-beta01.txt
diff --git a/media2/common/api/restricted_1.1.0-beta01.txt b/media2/common/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..ecd925d
--- /dev/null
+++ b/media2/common/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,273 @@
+// Signature format: 3.0
+package androidx.media2.common {
+
+ public class CallbackMediaItem extends androidx.media2.common.MediaItem {
+ method public androidx.media2.common.DataSourceCallback getDataSourceCallback();
+ }
+
+ public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
+ method public androidx.media2.common.CallbackMediaItem build();
+ method public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
+ }
+
+ public abstract class DataSourceCallback implements java.io.Closeable {
+ ctor public DataSourceCallback();
+ method public abstract long getSize() throws java.io.IOException;
+ method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+ }
+
+ public class FileMediaItem extends androidx.media2.common.MediaItem {
+ method public long getFileDescriptorLength();
+ method public long getFileDescriptorOffset();
+ method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+ field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
+ method public androidx.media2.common.FileMediaItem build();
+ method public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
+ method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
+ method public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class MediaItem extends androidx.versionedparcelable.CustomVersionedParcelable {
+ method public long getEndPosition();
+ method public androidx.media2.common.MediaMetadata? getMetadata();
+ method public long getStartPosition();
+ method public void setMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+ }
+
+ public static class MediaItem.Builder {
+ ctor public MediaItem.Builder();
+ method public androidx.media2.common.MediaItem build();
+ method public androidx.media2.common.MediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.MediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public final class MediaMetadata extends androidx.versionedparcelable.CustomVersionedParcelable {
+ method public boolean containsKey(String);
+ method public android.graphics.Bitmap? getBitmap(String);
+ method public android.os.Bundle? getExtras();
+ method public float getFloat(String);
+ method public long getLong(String);
+ method public String? getMediaId();
+ method public androidx.media2.common.Rating? getRating(String);
+ method public String? getString(String);
+ method public CharSequence? getText(String);
+ method public java.util.Set<java.lang.String!> keySet();
+ method public int size();
+ field public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
+ field public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
+ field public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
+ field public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
+ field public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
+ field public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
+ field public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
+ field public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
+ field public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
+ field public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+ field public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+ field public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+ field public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+ field public static final String METADATA_KEY_ART = "android.media.metadata.ART";
+ field public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+ field public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+ field public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+ field public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
+ field public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+ field public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+ field public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
+ field public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+ field public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+ field public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+ field public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+ field public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+ field public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+ field public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
+ field public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+ field public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
+ field public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+ field public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+ field public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+ field public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+ field public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
+ field public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
+ field public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+ field public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+ field public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+ field public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+ field public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+ field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+ field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+ field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+ }
+
+ public static final class MediaMetadata.Builder {
+ ctor public MediaMetadata.Builder();
+ ctor public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
+ method public androidx.media2.common.MediaMetadata build();
+ method public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
+ method public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
+ method public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
+ method public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
+ method public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
+ method public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
+ method public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
+ }
+
+ public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
+ method public boolean isRated();
+ }
+
+ public abstract class SessionPlayer implements java.io.Closeable {
+ ctor public SessionPlayer();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method @CallSuper public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public abstract long getBufferedPosition();
+ method public abstract int getBufferingState();
+ method protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
+ method public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
+ method public abstract long getCurrentPosition();
+ method public abstract long getDuration();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
+ method public abstract float getPlaybackSpeed();
+ method public abstract int getPlayerState();
+ method public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
+ method public abstract int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+ method public abstract int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
+ field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
+ field public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
+ field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
+ field public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
+ field public static final int PLAYER_STATE_ERROR = 3; // 0x3
+ field public static final int PLAYER_STATE_IDLE = 0; // 0x0
+ field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
+ field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
+ field public static final int REPEAT_MODE_ALL = 2; // 0x2
+ field public static final int REPEAT_MODE_GROUP = 3; // 0x3
+ field public static final int REPEAT_MODE_NONE = 0; // 0x0
+ field public static final int REPEAT_MODE_ONE = 1; // 0x1
+ field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+ field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+ field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+ field public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
+ }
+
+ public abstract static class SessionPlayer.PlayerCallback {
+ ctor public SessionPlayer.PlayerCallback();
+ method public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
+ method public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
+ method public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem);
+ method public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
+ method public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
+ method public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
+ method public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
+ method public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
+ }
+
+ public static class SessionPlayer.PlayerResult {
+ ctor public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
+ method public long getCompletionTime();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
+ field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
+ field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
+ field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa
+ field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc
+ field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public static class SessionPlayer.TrackInfo extends androidx.versionedparcelable.CustomVersionedParcelable {
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
+ ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
+ method public android.media.MediaFormat? getFormat();
+ method public int getId();
+ method public java.util.Locale getLanguage();
+ method public int getTrackType();
+ method public boolean isSelectable();
+ field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+ field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
+ field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
+ field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SubtitleData(long, long, byte[]);
+ method public byte[] getData();
+ method public long getDurationUs();
+ method public long getStartTimeUs();
+ }
+
+ public class UriMediaItem extends androidx.media2.common.MediaItem {
+ method public android.net.Uri getUri();
+ method public java.util.List<java.net.HttpCookie!>? getUriCookies();
+ method public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
+ }
+
+ public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+ ctor public UriMediaItem.Builder(android.net.Uri);
+ ctor public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
+ method public androidx.media2.common.UriMediaItem build();
+ method public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
+ method public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+ method public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
+ method @IntRange(from=0) public int getHeight();
+ method @IntRange(from=0) public int getWidth();
+ }
+
+}
+
diff --git a/media2/media2-exoplayer/api/1.1.0-beta01.txt b/media2/media2-exoplayer/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/media2/media2-exoplayer/api/1.1.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/media2/media2-exoplayer/api/public_plus_experimental_1.1.0-beta01.txt b/media2/media2-exoplayer/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/media2/media2-exoplayer/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/media2/media2-exoplayer/api/res-1.1.0-beta01.txt b/media2/media2-exoplayer/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media2/media2-exoplayer/api/res-1.1.0-beta01.txt
diff --git a/media2/media2-exoplayer/api/restricted_1.1.0-beta01.txt b/media2/media2-exoplayer/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/media2/media2-exoplayer/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/media2/player/api/1.1.0-beta01.txt b/media2/player/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..2aacb97
--- /dev/null
+++ b/media2/player/api/1.1.0-beta01.txt
@@ -0,0 +1,123 @@
+// Signature format: 3.0
+package androidx.media2.player {
+
+ public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public MediaPlayer(android.content.Context);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getAudioSessionId();
+ method public long getBufferedPosition();
+ method public int getBufferingState();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public float getMaxPlayerVolume();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.player.PlaybackParams getPlaybackParams();
+ method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
+ method public int getPlayerState();
+ method public float getPlayerVolume();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method public int getRepeatMode();
+ method public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
+ method public int getShuffleMode();
+ method public androidx.media2.player.MediaTimestamp? getTimestamp();
+ method @Deprecated public java.util.List<androidx.media2.player.MediaPlayer.TrackInfo!> getTrackInfo();
+ method public androidx.media2.player.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public void reset();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
+ method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.player.MediaPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
+ field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+ field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
+ field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+ field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
+ field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+ field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+ field @Deprecated public static final int NO_TRACK_SELECTED = -2147483648; // 0x80000000
+ field public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
+ field public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
+ field public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
+ field public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
+ field public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int SEEK_CLOSEST = 3; // 0x3
+ field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
+ field public static final int SEEK_NEXT_SYNC = 1; // 0x1
+ field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
+ }
+
+ public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public MediaPlayer.PlayerCallback();
+ method public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
+ method public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
+ method @Deprecated public void onVideoSizeChanged(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.VideoSize);
+ }
+
+ public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
+ }
+
+ public final class MediaTimestamp {
+ method public long getAnchorMediaTimeUs();
+ method public long getAnchorSystemNanoTime();
+ method public float getMediaClockRate();
+ field public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
+ }
+
+ public final class PlaybackParams {
+ method public Integer? getAudioFallbackMode();
+ method public Float? getPitch();
+ method public Float? getSpeed();
+ field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
+ field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
+ field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
+ }
+
+ public static final class PlaybackParams.Builder {
+ ctor public PlaybackParams.Builder();
+ ctor public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
+ method public androidx.media2.player.PlaybackParams build();
+ method public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
+ method public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ }
+
+ public class TimedMetaData {
+ method public byte[]! getMetaData();
+ method public long getTimestamp();
+ }
+
+ public final class VideoSize extends androidx.media2.common.VideoSize {
+ ctor public VideoSize(int, int);
+ }
+
+}
+
diff --git a/media2/player/api/public_plus_experimental_1.1.0-beta01.txt b/media2/player/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..8a75ae5
--- /dev/null
+++ b/media2/player/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,123 @@
+// Signature format: 3.0
+package androidx.media2.player {
+
+ public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public MediaPlayer(android.content.Context);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getAudioSessionId();
+ method public long getBufferedPosition();
+ method @androidx.media2.common.SessionPlayer.BuffState public int getBufferingState();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public float getMaxPlayerVolume();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.player.PlaybackParams getPlaybackParams();
+ method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
+ method @androidx.media2.common.SessionPlayer.PlayerState public int getPlayerState();
+ method public float getPlayerVolume();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method public int getRepeatMode();
+ method public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
+ method public int getShuffleMode();
+ method public androidx.media2.player.MediaTimestamp? getTimestamp();
+ method @Deprecated public java.util.List<androidx.media2.player.MediaPlayer.TrackInfo!> getTrackInfo();
+ method public androidx.media2.player.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public void reset();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
+ method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.player.MediaPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
+ field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+ field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
+ field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+ field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
+ field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+ field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+ field @Deprecated public static final int NO_TRACK_SELECTED = -2147483648; // 0x80000000
+ field public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
+ field public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
+ field public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
+ field public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
+ field public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int SEEK_CLOSEST = 3; // 0x3
+ field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
+ field public static final int SEEK_NEXT_SYNC = 1; // 0x1
+ field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
+ }
+
+ public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public MediaPlayer.PlayerCallback();
+ method public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
+ method public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
+ method @Deprecated public void onVideoSizeChanged(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.VideoSize);
+ }
+
+ public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo {
+ }
+
+ public final class MediaTimestamp {
+ method public long getAnchorMediaTimeUs();
+ method public long getAnchorSystemNanoTime();
+ method public float getMediaClockRate();
+ field public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
+ }
+
+ public final class PlaybackParams {
+ method public Integer? getAudioFallbackMode();
+ method public Float? getPitch();
+ method public Float? getSpeed();
+ field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
+ field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
+ field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
+ }
+
+ public static final class PlaybackParams.Builder {
+ ctor public PlaybackParams.Builder();
+ ctor public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
+ method public androidx.media2.player.PlaybackParams build();
+ method public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
+ method public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ }
+
+ public class TimedMetaData {
+ method public byte[]! getMetaData();
+ method public long getTimestamp();
+ }
+
+ public final class VideoSize extends androidx.media2.common.VideoSize {
+ ctor public VideoSize(int, int);
+ }
+
+}
+
diff --git a/media2/player/api/res-1.1.0-beta01.txt b/media2/player/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media2/player/api/res-1.1.0-beta01.txt
diff --git a/media2/player/api/restricted_1.1.0-beta01.txt b/media2/player/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..8a75ae5
--- /dev/null
+++ b/media2/player/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,123 @@
+// Signature format: 3.0
+package androidx.media2.player {
+
+ public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public MediaPlayer(android.content.Context);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getAudioSessionId();
+ method public long getBufferedPosition();
+ method @androidx.media2.common.SessionPlayer.BuffState public int getBufferingState();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public float getMaxPlayerVolume();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.player.PlaybackParams getPlaybackParams();
+ method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
+ method @androidx.media2.common.SessionPlayer.PlayerState public int getPlayerState();
+ method public float getPlayerVolume();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method public int getRepeatMode();
+ method public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
+ method public int getShuffleMode();
+ method public androidx.media2.player.MediaTimestamp? getTimestamp();
+ method @Deprecated public java.util.List<androidx.media2.player.MediaPlayer.TrackInfo!> getTrackInfo();
+ method public androidx.media2.player.VideoSize getVideoSize();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+ method public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+ method public void reset();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
+ method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.player.MediaPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+ method public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
+ field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+ field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
+ field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+ field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
+ field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+ field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+ field @Deprecated public static final int NO_TRACK_SELECTED = -2147483648; // 0x80000000
+ field public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
+ field public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
+ field public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
+ field public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
+ field public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int SEEK_CLOSEST = 3; // 0x3
+ field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
+ field public static final int SEEK_NEXT_SYNC = 1; // 0x1
+ field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
+ }
+
+ public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public MediaPlayer.PlayerCallback();
+ method public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+ method public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
+ method public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
+ method @Deprecated public void onVideoSizeChanged(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.VideoSize);
+ }
+
+ public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo {
+ }
+
+ public final class MediaTimestamp {
+ method public long getAnchorMediaTimeUs();
+ method public long getAnchorSystemNanoTime();
+ method public float getMediaClockRate();
+ field public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
+ }
+
+ public final class PlaybackParams {
+ method public Integer? getAudioFallbackMode();
+ method public Float? getPitch();
+ method public Float? getSpeed();
+ field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
+ field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
+ field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
+ }
+
+ public static final class PlaybackParams.Builder {
+ ctor public PlaybackParams.Builder();
+ ctor public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
+ method public androidx.media2.player.PlaybackParams build();
+ method public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
+ method public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ method public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+ }
+
+ public class TimedMetaData {
+ method public byte[]! getMetaData();
+ method public long getTimestamp();
+ }
+
+ public final class VideoSize extends androidx.media2.common.VideoSize {
+ ctor public VideoSize(int, int);
+ }
+
+}
+
diff --git a/media2/session/api/1.1.0-beta01.txt b/media2/session/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..d5c19ab
--- /dev/null
+++ b/media2/session/api/1.1.0-beta01.txt
@@ -0,0 +1,447 @@
+// Signature format: 3.0
+package androidx.media2.session {
+
+ public final class HeartRating implements androidx.media2.common.Rating {
+ ctor public HeartRating();
+ ctor public HeartRating(boolean);
+ method public boolean hasHeart();
+ method public boolean isRated();
+ }
+
+ public class LibraryResult implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public LibraryResult(int);
+ ctor public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ ctor public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public long getCompletionTime();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
+ field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
+ field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
+ field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa
+ field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public class MediaBrowser extends androidx.media2.session.MediaController {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
+ }
+
+ public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
+ ctor public MediaBrowser.BrowserCallback();
+ method public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaBrowser.Builder {
+ ctor public MediaBrowser.Builder(android.content.Context);
+ method public androidx.media2.session.MediaBrowser build();
+ method public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public class MediaConstants {
+ field public static final String MEDIA_URI_AUTHORITY = "media2-session";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
+ field public static final String MEDIA_URI_QUERY_ID = "id";
+ field public static final String MEDIA_URI_QUERY_QUERY = "query";
+ field public static final String MEDIA_URI_SCHEME = "androidx";
+ }
+
+ public class MediaController implements java.io.Closeable {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
+ method public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
+ method public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
+ method public long getBufferedPosition();
+ method public int getBufferingState();
+ method public androidx.media2.session.SessionToken? getConnectedToken();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
+ method public float getPlaybackSpeed();
+ method public int getPlayerState();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method public int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+ method public android.app.PendingIntent? getSessionActivity();
+ method public int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public boolean isConnected();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ }
+
+ public static final class MediaController.Builder {
+ ctor public MediaController.Builder(android.content.Context);
+ method public androidx.media2.session.MediaController build();
+ method public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
+ method public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public abstract static class MediaController.ControllerCallback {
+ ctor public MediaController.ControllerCallback();
+ method public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, int);
+ method public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaController);
+ method public void onPlaybackCompleted(androidx.media2.session.MediaController);
+ method public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
+ method public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
+ method public void onPlayerStateChanged(androidx.media2.session.MediaController, int);
+ method public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.session.MediaController, int);
+ method public void onSeekCompleted(androidx.media2.session.MediaController, long);
+ method public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void onShuffleModeChanged(androidx.media2.session.MediaController, int);
+ method public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
+ }
+
+ public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getControlType();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getPlaybackType();
+ field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+ field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+ }
+
+ public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
+ ctor public MediaLibraryService();
+ method public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
+ }
+
+ public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
+ method public android.os.Bundle? getExtras();
+ method public boolean isOffline();
+ method public boolean isRecent();
+ method public boolean isSuggested();
+ }
+
+ public static final class MediaLibraryService.LibraryParams.Builder {
+ ctor public MediaLibraryService.LibraryParams.Builder();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams build();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
+ method public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession.Builder {
+ ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
+ }
+
+ public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
+ ctor public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
+ method public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ }
+
+ public class MediaSession implements java.io.Closeable {
+ method public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void close();
+ method public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
+ method public String getId();
+ method public androidx.media2.common.SessionPlayer getPlayer();
+ method public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
+ method public androidx.media2.session.SessionToken getToken();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void updatePlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static final class MediaSession.Builder {
+ ctor public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
+ method public androidx.media2.session.MediaSession build();
+ method public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaSession.Builder setId(String);
+ method public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
+ method public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
+ }
+
+ public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media2.session.SessionCommand? getCommand();
+ method public CharSequence? getDisplayName();
+ method public android.os.Bundle? getExtras();
+ method public int getIconResId();
+ method public boolean isEnabled();
+ }
+
+ public static final class MediaSession.CommandButton.Builder {
+ ctor public MediaSession.CommandButton.Builder();
+ method public androidx.media2.session.MediaSession.CommandButton build();
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
+ }
+
+ public static final class MediaSession.ControllerInfo {
+ method public android.os.Bundle getConnectionHints();
+ method public String getPackageName();
+ method public int getUid();
+ }
+
+ public abstract static class MediaSession.SessionCallback {
+ ctor public MediaSession.SessionCallback();
+ method public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
+ method public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
+ method public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ }
+
+ public final class MediaSessionManager {
+ method public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
+ method public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
+ }
+
+ public abstract class MediaSessionService extends android.app.Service {
+ ctor public MediaSessionService();
+ method public final void addSession(androidx.media2.session.MediaSession);
+ method public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
+ method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+ method public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
+ method public final void removeSession(androidx.media2.session.MediaSession);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
+ }
+
+ public static class MediaSessionService.MediaNotification {
+ ctor public MediaSessionService.MediaNotification(int, android.app.Notification);
+ method public android.app.Notification getNotification();
+ method public int getNotificationId();
+ }
+
+ public final class PercentageRating implements androidx.media2.common.Rating {
+ ctor public PercentageRating();
+ ctor public PercentageRating(float);
+ method public float getPercentRating();
+ method public boolean isRated();
+ }
+
+ public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public RemoteSessionPlayer();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
+ method public abstract int getMaxVolume();
+ method public abstract int getVolume();
+ method public abstract int getVolumeControlType();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
+ field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+ field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+ field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+ }
+
+ public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public RemoteSessionPlayer.Callback();
+ method public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
+ }
+
+ public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommand(int);
+ ctor public SessionCommand(String, android.os.Bundle?);
+ method public int getCommandCode();
+ method public String? getCustomAction();
+ method public android.os.Bundle? getCustomExtras();
+ field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+ field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
+ field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
+ field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
+ field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
+ field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
+ field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
+ field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
+ field public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
+ field public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
+ field public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
+ field public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
+ field public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
+ field public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
+ field public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
+ field public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
+ field public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
+ field public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
+ field public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
+ field public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
+ field public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
+ field public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
+ field public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
+ field public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
+ field public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
+ field public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
+ field public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
+ field public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
+ field public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
+ field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
+ field public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
+ field public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
+ field public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
+ field public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
+ field public static final int COMMAND_VERSION_1 = 1; // 0x1
+ field public static final int COMMAND_VERSION_2 = 2; // 0x2
+ }
+
+ public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommandGroup();
+ ctor public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
+ method public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
+ method public boolean hasCommand(androidx.media2.session.SessionCommand);
+ method public boolean hasCommand(int);
+ }
+
+ public static final class SessionCommandGroup.Builder {
+ ctor public SessionCommandGroup.Builder();
+ ctor public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
+ method public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
+ method public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup build();
+ method public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
+ }
+
+ public class SessionResult implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionResult(int, android.os.Bundle?);
+ method public long getCompletionTime();
+ method public android.os.Bundle? getCustomCommandResult();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
+ field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
+ field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
+ field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa
+ field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionToken(android.content.Context, android.content.ComponentName);
+ method public android.os.Bundle getExtras();
+ method public String getPackageName();
+ method public String? getServiceName();
+ method public int getType();
+ method public int getUid();
+ field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+ field public static final int TYPE_SESSION = 0; // 0x0
+ field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+ }
+
+ public final class StarRating implements androidx.media2.common.Rating {
+ ctor public StarRating(@IntRange(from=1) int);
+ ctor public StarRating(@IntRange(from=1) int, float);
+ method public int getMaxStars();
+ method public float getStarRating();
+ method public boolean isRated();
+ }
+
+ public final class ThumbRating implements androidx.media2.common.Rating {
+ ctor public ThumbRating();
+ ctor public ThumbRating(boolean);
+ method public boolean isRated();
+ method public boolean isThumbUp();
+ }
+
+}
+
diff --git a/media2/session/api/public_plus_experimental_1.1.0-beta01.txt b/media2/session/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..646d255
--- /dev/null
+++ b/media2/session/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,432 @@
+// Signature format: 3.0
+package androidx.media2.session {
+
+ @androidx.versionedparcelable.VersionedParcelize public final class HeartRating implements androidx.media2.common.Rating {
+ ctor public HeartRating();
+ ctor public HeartRating(boolean);
+ method public boolean hasHeart();
+ method public boolean isRated();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class LibraryResult extends androidx.versionedparcelable.CustomVersionedParcelable implements androidx.media2.common.BaseResult {
+ ctor public LibraryResult(int);
+ ctor public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ ctor public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public long getCompletionTime();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ }
+
+ public class MediaBrowser extends androidx.media2.session.MediaController {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
+ }
+
+ public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
+ ctor public MediaBrowser.BrowserCallback();
+ method public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaBrowser.Builder {
+ ctor public MediaBrowser.Builder(android.content.Context);
+ method public androidx.media2.session.MediaBrowser build();
+ method public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public class MediaConstants {
+ field public static final String MEDIA_URI_AUTHORITY = "media2-session";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
+ field public static final String MEDIA_URI_QUERY_ID = "id";
+ field public static final String MEDIA_URI_QUERY_QUERY = "query";
+ field public static final String MEDIA_URI_SCHEME = "androidx";
+ }
+
+ public class MediaController implements java.io.Closeable {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
+ method public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
+ method public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
+ method public long getBufferedPosition();
+ method @androidx.media2.common.SessionPlayer.BuffState public int getBufferingState();
+ method public androidx.media2.session.SessionToken? getConnectedToken();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
+ method public float getPlaybackSpeed();
+ method public int getPlayerState();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method @androidx.media2.common.SessionPlayer.RepeatMode public int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(@androidx.media2.common.SessionPlayer.TrackInfo.MediaTrackType int);
+ method public android.app.PendingIntent? getSessionActivity();
+ method @androidx.media2.common.SessionPlayer.ShuffleMode public int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public boolean isConnected();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(@androidx.media2.common.SessionPlayer.RepeatMode int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(@androidx.media2.common.SessionPlayer.ShuffleMode int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ }
+
+ public static final class MediaController.Builder {
+ ctor public MediaController.Builder(android.content.Context);
+ method public androidx.media2.session.MediaController build();
+ method public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
+ method public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public abstract static class MediaController.ControllerCallback {
+ ctor public MediaController.ControllerCallback();
+ method public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, @androidx.media2.common.SessionPlayer.BuffState int);
+ method public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaController);
+ method public void onPlaybackCompleted(androidx.media2.session.MediaController);
+ method public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
+ method public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
+ method public void onPlayerStateChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.PlayerState int);
+ method public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.RepeatMode int);
+ method public void onSeekCompleted(androidx.media2.session.MediaController, long);
+ method public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void onShuffleModeChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.ShuffleMode int);
+ method public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getControlType();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getPlaybackType();
+ field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+ field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+ }
+
+ public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
+ ctor public MediaLibraryService();
+ method public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
+ method public android.os.Bundle? getExtras();
+ method public boolean isOffline();
+ method public boolean isRecent();
+ method public boolean isSuggested();
+ }
+
+ public static final class MediaLibraryService.LibraryParams.Builder {
+ ctor public MediaLibraryService.LibraryParams.Builder();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams build();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
+ method public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession.Builder {
+ ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
+ }
+
+ public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
+ ctor public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
+ method public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ }
+
+ public class MediaSession implements java.io.Closeable {
+ method public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void close();
+ method public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
+ method public String getId();
+ method public androidx.media2.common.SessionPlayer getPlayer();
+ method public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
+ method public androidx.media2.session.SessionToken getToken();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void updatePlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static final class MediaSession.Builder {
+ ctor public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
+ method public androidx.media2.session.MediaSession build();
+ method public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaSession.Builder setId(String);
+ method public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
+ method public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media2.session.SessionCommand? getCommand();
+ method public CharSequence? getDisplayName();
+ method public android.os.Bundle? getExtras();
+ method public int getIconResId();
+ method public boolean isEnabled();
+ }
+
+ public static final class MediaSession.CommandButton.Builder {
+ ctor public MediaSession.CommandButton.Builder();
+ method public androidx.media2.session.MediaSession.CommandButton build();
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
+ }
+
+ public static final class MediaSession.ControllerInfo {
+ method public android.os.Bundle getConnectionHints();
+ method public String getPackageName();
+ method public int getUid();
+ }
+
+ public abstract static class MediaSession.SessionCallback {
+ ctor public MediaSession.SessionCallback();
+ method public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
+ method public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
+ method public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ }
+
+ public final class MediaSessionManager {
+ method public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
+ method public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
+ }
+
+ public abstract class MediaSessionService extends android.app.Service {
+ ctor public MediaSessionService();
+ method public final void addSession(androidx.media2.session.MediaSession);
+ method public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
+ method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+ method public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
+ method public final void removeSession(androidx.media2.session.MediaSession);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
+ }
+
+ public static class MediaSessionService.MediaNotification {
+ ctor public MediaSessionService.MediaNotification(int, android.app.Notification);
+ method public android.app.Notification getNotification();
+ method public int getNotificationId();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class PercentageRating implements androidx.media2.common.Rating {
+ ctor public PercentageRating();
+ ctor public PercentageRating(float);
+ method public float getPercentRating();
+ method public boolean isRated();
+ }
+
+ public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public RemoteSessionPlayer();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
+ method public abstract int getMaxVolume();
+ method public abstract int getVolume();
+ method public abstract int getVolumeControlType();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
+ field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+ field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+ field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+ }
+
+ public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public RemoteSessionPlayer.Callback();
+ method public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommand(int);
+ ctor public SessionCommand(String, android.os.Bundle?);
+ method public int getCommandCode();
+ method public String? getCustomAction();
+ method public android.os.Bundle? getCustomExtras();
+ field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+ field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
+ field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
+ field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
+ field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
+ field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
+ field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
+ field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
+ field public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
+ field public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
+ field public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
+ field public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
+ field public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
+ field public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
+ field public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
+ field public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
+ field public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
+ field public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
+ field public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
+ field public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
+ field public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
+ field public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
+ field public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
+ field public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
+ field public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
+ field public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
+ field public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
+ field public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
+ field public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
+ field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
+ field public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
+ field public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
+ field public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
+ field public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
+ field public static final int COMMAND_VERSION_1 = 1; // 0x1
+ field public static final int COMMAND_VERSION_2 = 2; // 0x2
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommandGroup();
+ ctor public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
+ method public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
+ method public boolean hasCommand(androidx.media2.session.SessionCommand);
+ method public boolean hasCommand(int);
+ }
+
+ public static final class SessionCommandGroup.Builder {
+ ctor public SessionCommandGroup.Builder();
+ ctor public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
+ method public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
+ method public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup build();
+ method public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class SessionResult extends androidx.versionedparcelable.CustomVersionedParcelable implements androidx.media2.common.BaseResult {
+ ctor public SessionResult(int, android.os.Bundle?);
+ method public long getCompletionTime();
+ method public android.os.Bundle? getCustomCommandResult();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionToken(android.content.Context, android.content.ComponentName);
+ method public android.os.Bundle getExtras();
+ method public String getPackageName();
+ method public String? getServiceName();
+ method public int getType();
+ method public int getUid();
+ field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+ field public static final int TYPE_SESSION = 0; // 0x0
+ field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class StarRating implements androidx.media2.common.Rating {
+ ctor public StarRating(@IntRange(from=1) int);
+ ctor public StarRating(@IntRange(from=1) int, float);
+ method public int getMaxStars();
+ method public float getStarRating();
+ method public boolean isRated();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class ThumbRating implements androidx.media2.common.Rating {
+ ctor public ThumbRating();
+ ctor public ThumbRating(boolean);
+ method public boolean isRated();
+ method public boolean isThumbUp();
+ }
+
+}
+
diff --git a/media2/session/api/res-1.1.0-beta01.txt b/media2/session/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media2/session/api/res-1.1.0-beta01.txt
diff --git a/media2/session/api/restricted_1.1.0-beta01.txt b/media2/session/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..646d255
--- /dev/null
+++ b/media2/session/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,432 @@
+// Signature format: 3.0
+package androidx.media2.session {
+
+ @androidx.versionedparcelable.VersionedParcelize public final class HeartRating implements androidx.media2.common.Rating {
+ ctor public HeartRating();
+ ctor public HeartRating(boolean);
+ method public boolean hasHeart();
+ method public boolean isRated();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class LibraryResult extends androidx.versionedparcelable.CustomVersionedParcelable implements androidx.media2.common.BaseResult {
+ ctor public LibraryResult(int);
+ ctor public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ ctor public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public long getCompletionTime();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ }
+
+ public class MediaBrowser extends androidx.media2.session.MediaController {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
+ }
+
+ public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
+ ctor public MediaBrowser.BrowserCallback();
+ method public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaBrowser.Builder {
+ ctor public MediaBrowser.Builder(android.content.Context);
+ method public androidx.media2.session.MediaBrowser build();
+ method public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public class MediaConstants {
+ field public static final String MEDIA_URI_AUTHORITY = "media2-session";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
+ field public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
+ field public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
+ field public static final String MEDIA_URI_QUERY_ID = "id";
+ field public static final String MEDIA_URI_QUERY_QUERY = "query";
+ field public static final String MEDIA_URI_SCHEME = "androidx";
+ }
+
+ public class MediaController implements java.io.Closeable {
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
+ method public void close();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
+ method public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
+ method public long getBufferedPosition();
+ method @androidx.media2.common.SessionPlayer.BuffState public int getBufferingState();
+ method public androidx.media2.session.SessionToken? getConnectedToken();
+ method public androidx.media2.common.MediaItem? getCurrentMediaItem();
+ method public int getCurrentMediaItemIndex();
+ method public long getCurrentPosition();
+ method public long getDuration();
+ method public int getNextMediaItemIndex();
+ method public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
+ method public float getPlaybackSpeed();
+ method public int getPlayerState();
+ method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+ method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+ method public int getPreviousMediaItemIndex();
+ method @androidx.media2.common.SessionPlayer.RepeatMode public int getRepeatMode();
+ method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(@androidx.media2.common.SessionPlayer.TrackInfo.MediaTrackType int);
+ method public android.app.PendingIntent? getSessionActivity();
+ method @androidx.media2.common.SessionPlayer.ShuffleMode public int getShuffleMode();
+ method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+ method public androidx.media2.common.VideoSize getVideoSize();
+ method public boolean isConnected();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(@androidx.media2.common.SessionPlayer.RepeatMode int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(@androidx.media2.common.SessionPlayer.ShuffleMode int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+ }
+
+ public static final class MediaController.Builder {
+ ctor public MediaController.Builder(android.content.Context);
+ method public androidx.media2.session.MediaController build();
+ method public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
+ method public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
+ method public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+ method public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
+ }
+
+ public abstract static class MediaController.ControllerCallback {
+ ctor public MediaController.ControllerCallback();
+ method public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, @androidx.media2.common.SessionPlayer.BuffState int);
+ method public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+ method public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaController);
+ method public void onPlaybackCompleted(androidx.media2.session.MediaController);
+ method public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
+ method public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
+ method public void onPlayerStateChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.PlayerState int);
+ method public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+ method public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
+ method public void onRepeatModeChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.RepeatMode int);
+ method public void onSeekCompleted(androidx.media2.session.MediaController, long);
+ method public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void onShuffleModeChanged(androidx.media2.session.MediaController, @androidx.media2.common.SessionPlayer.ShuffleMode int);
+ method public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+ method public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+ method public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+ method public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media.AudioAttributesCompat? getAudioAttributes();
+ method public int getControlType();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getPlaybackType();
+ field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+ field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+ }
+
+ public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
+ ctor public MediaLibraryService();
+ method public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
+ method public android.os.Bundle? getExtras();
+ method public boolean isOffline();
+ method public boolean isRecent();
+ method public boolean isSuggested();
+ }
+
+ public static final class MediaLibraryService.LibraryParams.Builder {
+ ctor public MediaLibraryService.LibraryParams.Builder();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams build();
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
+ method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
+ method public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ }
+
+ public static final class MediaLibraryService.MediaLibrarySession.Builder {
+ ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
+ method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
+ }
+
+ public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
+ ctor public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
+ method public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+ method public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ }
+
+ public class MediaSession implements java.io.Closeable {
+ method public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void close();
+ method public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
+ method public String getId();
+ method public androidx.media2.common.SessionPlayer getPlayer();
+ method public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
+ method public androidx.media2.session.SessionToken getToken();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+ method public void updatePlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static final class MediaSession.Builder {
+ ctor public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
+ method public androidx.media2.session.MediaSession build();
+ method public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
+ method public androidx.media2.session.MediaSession.Builder setId(String);
+ method public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
+ method public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
+ method public androidx.media2.session.SessionCommand? getCommand();
+ method public CharSequence? getDisplayName();
+ method public android.os.Bundle? getExtras();
+ method public int getIconResId();
+ method public boolean isEnabled();
+ }
+
+ public static final class MediaSession.CommandButton.Builder {
+ ctor public MediaSession.CommandButton.Builder();
+ method public androidx.media2.session.MediaSession.CommandButton build();
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
+ method public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
+ }
+
+ public static final class MediaSession.ControllerInfo {
+ method public android.os.Bundle getConnectionHints();
+ method public String getPackageName();
+ method public int getUid();
+ }
+
+ public abstract static class MediaSession.SessionCallback {
+ ctor public MediaSession.SessionCallback();
+ method public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
+ method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+ method public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
+ method public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
+ method public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ method public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+ }
+
+ public final class MediaSessionManager {
+ method public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
+ method public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
+ }
+
+ public abstract class MediaSessionService extends android.app.Service {
+ ctor public MediaSessionService();
+ method public final void addSession(androidx.media2.session.MediaSession);
+ method public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
+ method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+ method public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+ method public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
+ method public final void removeSession(androidx.media2.session.MediaSession);
+ field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
+ }
+
+ public static class MediaSessionService.MediaNotification {
+ ctor public MediaSessionService.MediaNotification(int, android.app.Notification);
+ method public android.app.Notification getNotification();
+ method public int getNotificationId();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class PercentageRating implements androidx.media2.common.Rating {
+ ctor public PercentageRating();
+ ctor public PercentageRating(float);
+ method public float getPercentRating();
+ method public boolean isRated();
+ }
+
+ public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
+ ctor public RemoteSessionPlayer();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
+ method public abstract int getMaxVolume();
+ method public abstract int getVolume();
+ method public abstract int getVolumeControlType();
+ method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
+ field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+ field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+ field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+ }
+
+ public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+ ctor public RemoteSessionPlayer.Callback();
+ method public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommand(int);
+ ctor public SessionCommand(String, android.os.Bundle?);
+ method public int getCommandCode();
+ method public String? getCustomAction();
+ method public android.os.Bundle? getCustomExtras();
+ field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+ field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
+ field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
+ field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
+ field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
+ field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
+ field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
+ field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
+ field public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
+ field public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
+ field public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
+ field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
+ field public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
+ field public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
+ field public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
+ field public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
+ field public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
+ field public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
+ field public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
+ field public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
+ field public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
+ field public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
+ field public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
+ field public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
+ field public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
+ field public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
+ field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
+ field public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
+ field public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
+ field public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
+ field public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
+ field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
+ field public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
+ field public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
+ field public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
+ field public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
+ field public static final int COMMAND_VERSION_1 = 1; // 0x1
+ field public static final int COMMAND_VERSION_2 = 2; // 0x2
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionCommandGroup();
+ ctor public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
+ method public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
+ method public boolean hasCommand(androidx.media2.session.SessionCommand);
+ method public boolean hasCommand(int);
+ }
+
+ public static final class SessionCommandGroup.Builder {
+ ctor public SessionCommandGroup.Builder();
+ ctor public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
+ method public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
+ method public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
+ method public androidx.media2.session.SessionCommandGroup build();
+ method public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class SessionResult extends androidx.versionedparcelable.CustomVersionedParcelable implements androidx.media2.common.BaseResult {
+ ctor public SessionResult(int, android.os.Bundle?);
+ method public long getCompletionTime();
+ method public android.os.Bundle? getCustomCommandResult();
+ method public androidx.media2.common.MediaItem? getMediaItem();
+ method public int getResultCode();
+ field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a
+ field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98
+ field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c
+ field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96
+ field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97
+ field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99
+ field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94
+ field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
+ ctor public SessionToken(android.content.Context, android.content.ComponentName);
+ method public android.os.Bundle getExtras();
+ method public String getPackageName();
+ method public String? getServiceName();
+ method public int getType();
+ method public int getUid();
+ field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+ field public static final int TYPE_SESSION = 0; // 0x0
+ field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class StarRating implements androidx.media2.common.Rating {
+ ctor public StarRating(@IntRange(from=1) int);
+ ctor public StarRating(@IntRange(from=1) int, float);
+ method public int getMaxStars();
+ method public float getStarRating();
+ method public boolean isRated();
+ }
+
+ @androidx.versionedparcelable.VersionedParcelize public final class ThumbRating implements androidx.media2.common.Rating {
+ ctor public ThumbRating();
+ ctor public ThumbRating(boolean);
+ method public boolean isRated();
+ method public boolean isThumbUp();
+ }
+
+}
+
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 1fa48ff..1352b13 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -948,7 +948,7 @@
sessionHandler.postAndSync(new Runnable() {
@Override
public void run() {
- mSession = new MediaSession.Builder(mContext, mPlayer)
+ mSession = new MediaSession.Builder(mContext, player)
.setSessionCallback(sHandlerExecutor, new SessionCallback() {})
.setId("testDeadlock").build();
}
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 443d768..883db40 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -856,7 +856,7 @@
sessionHandler.postAndSync(new Runnable() {
@Override
public void run() {
- mSession = new MediaSession.Builder(mContext, mPlayer)
+ mSession = new MediaSession.Builder(mContext, player)
.setSessionCallback(sHandlerExecutor, new SessionCallback() {})
.setId("testDeadlock").build();
}
diff --git a/media2/widget/api/1.1.0-beta01.txt b/media2/widget/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..b614f1a
--- /dev/null
+++ b/media2/widget/api/1.1.0-beta01.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.media2.widget {
+
+ public class MediaControlView extends android.view.ViewGroup {
+ ctor public MediaControlView(android.content.Context);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
+ method public void requestPlayButtonFocus();
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static interface MediaControlView.OnFullScreenListener {
+ method public void onFullScreen(android.view.View, boolean);
+ }
+
+ public class VideoView extends android.view.ViewGroup {
+ ctor public VideoView(android.content.Context);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.media2.widget.MediaControlView? getMediaControlView();
+ method public int getViewType();
+ method public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ method public void setViewType(int);
+ field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
+ field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
+ }
+
+ public static interface VideoView.OnViewTypeChangedListener {
+ method public void onViewTypeChanged(android.view.View, int);
+ }
+
+}
+
diff --git a/media2/widget/api/public_plus_experimental_1.1.0-beta01.txt b/media2/widget/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..b614f1a
--- /dev/null
+++ b/media2/widget/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.media2.widget {
+
+ public class MediaControlView extends android.view.ViewGroup {
+ ctor public MediaControlView(android.content.Context);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
+ method public void requestPlayButtonFocus();
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static interface MediaControlView.OnFullScreenListener {
+ method public void onFullScreen(android.view.View, boolean);
+ }
+
+ public class VideoView extends android.view.ViewGroup {
+ ctor public VideoView(android.content.Context);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.media2.widget.MediaControlView? getMediaControlView();
+ method public int getViewType();
+ method public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ method public void setViewType(int);
+ field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
+ field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
+ }
+
+ public static interface VideoView.OnViewTypeChangedListener {
+ method public void onViewTypeChanged(android.view.View, int);
+ }
+
+}
+
diff --git a/media2/widget/api/res-1.1.0-beta01.txt b/media2/widget/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..9015818
--- /dev/null
+++ b/media2/widget/api/res-1.1.0-beta01.txt
@@ -0,0 +1,2 @@
+attr enableControlView
+attr viewType
diff --git a/media2/widget/api/restricted_1.1.0-beta01.txt b/media2/widget/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..b614f1a
--- /dev/null
+++ b/media2/widget/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.media2.widget {
+
+ public class MediaControlView extends android.view.ViewGroup {
+ ctor public MediaControlView(android.content.Context);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?);
+ ctor public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
+ method public void requestPlayButtonFocus();
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ }
+
+ public static interface MediaControlView.OnFullScreenListener {
+ method public void onFullScreen(android.view.View, boolean);
+ }
+
+ public class VideoView extends android.view.ViewGroup {
+ ctor public VideoView(android.content.Context);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?);
+ ctor public VideoView(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.media2.widget.MediaControlView? getMediaControlView();
+ method public int getViewType();
+ method public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
+ method public void setMediaController(androidx.media2.session.MediaController);
+ method public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
+ method public void setPlayer(androidx.media2.common.SessionPlayer);
+ method public void setViewType(int);
+ field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
+ field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
+ }
+
+ public static interface VideoView.OnViewTypeChangedListener {
+ method public void onViewTypeChanged(android.view.View, int);
+ }
+
+}
+
diff --git a/mediarouter/mediarouter/build.gradle b/mediarouter/mediarouter/build.gradle
index 14516e3..2015482 100644
--- a/mediarouter/mediarouter/build.gradle
+++ b/mediarouter/mediarouter/build.gradle
@@ -24,12 +24,10 @@
}
dependencies {
- api("androidx.media:media:1.2.0-beta01")
+ api("androidx.media:media:1.2.0-rc01")
api(GUAVA_LISTENABLE_FUTURE)
implementation("androidx.appcompat:appcompat:1.1.0")
- // TODO: remove core:1.3.0 once media:1.2.0-alpha05 or beta01 is released.
- implementation("androidx.core:core:1.3.0")
implementation("androidx.palette:palette:1.0.0")
implementation("androidx.recyclerview:recyclerview:1.1.0")
diff --git a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
index 146ab24..1c26321 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
@@ -33,9 +33,20 @@
private val fetchDispatcher: CoroutineDispatcher = DirectDispatcher,
internal val dataSourceFactory: () -> DataSource<Key, Value>
) : PagingSource<Key, Value>() {
+ // Lazily initialize because it must be created on fetchDispatcher, but PagingSourceFactory
+ // passed to Pager is a non-suspending method.
internal val dataSource by lazy {
- dataSourceFactory().also {
- it.addInvalidatedCallback { invalidate() }
+ dataSourceFactory().also { dataSource ->
+ dataSource.addInvalidatedCallback(::invalidate)
+ // LegacyPagingSource registers invalidate callback after DataSource is created, so we
+ // need to check for race condition here. If DataSource is already invalid, simply
+ // propagate invalidation manually.
+ if (dataSource.isInvalid && !invalid) {
+ dataSource.removeInvalidatedCallback(::invalidate)
+ // Note: Calling this.invalidate directly will re-evaluate dataSource's by lazy
+ // init block, since we haven't returned a value for dataSource yet.
+ super.invalidate()
+ }
}
}
diff --git a/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
index 4383e6f..7e490dd 100644
--- a/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
@@ -251,6 +251,43 @@
assertTrue { initialized }
}
+ @Test
+ fun dataSourceInvalidateBeforePagingSourceInvalidateCallbackAdded() {
+ val dataSourceFactory = object : DataSource.Factory<Int, String>() {
+ val dataSources = mutableListOf<DataSource<Int, String>>()
+ var i = 0
+
+ override fun create(): DataSource<Int, String> {
+ return when (i++) {
+ 0 -> createTestPositionalDataSource().apply {
+ // Invalidate before we give LegacyPagingSource a chance to register
+ // invalidate callback.
+ invalidate()
+ }
+ else -> createTestPositionalDataSource()
+ }.also { dataSources.add(it) }
+ }
+ }
+
+ val pagingSourceFactory = dataSourceFactory.asPagingSourceFactory().let {
+ { it() as LegacyPagingSource }
+ }
+
+ val pagingSource0 = pagingSourceFactory()
+ assertTrue { pagingSource0.dataSource.isInvalid }
+ assertTrue { pagingSource0.invalid }
+ assertTrue { dataSourceFactory.dataSources[0].isInvalid }
+ assertEquals(dataSourceFactory.dataSources[0], pagingSource0.dataSource)
+
+ val pagingSource1 = pagingSourceFactory()
+ assertFalse { pagingSource1.dataSource.isInvalid }
+ assertFalse { pagingSource1.invalid }
+ assertFalse { dataSourceFactory.dataSources[1].isInvalid }
+ assertEquals(dataSourceFactory.dataSources[1], pagingSource1.dataSource)
+
+ assertEquals(2, dataSourceFactory.dataSources.size)
+ }
+
@Suppress("DEPRECATION")
private fun createTestPositionalDataSource(expectInitialLoad: Boolean = false) =
object : PositionalDataSource<String>() {
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DisallowInterceptFilterTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DisallowInterceptFilterTest.java
new file mode 100644
index 0000000..ee5316e
--- /dev/null
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DisallowInterceptFilterTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 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.recyclerview.selection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.recyclerview.selection.testing.TestEvents;
+import androidx.recyclerview.selection.testing.TestOnItemTouchListener;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DisallowInterceptFilterTest {
+
+ private TestOnItemTouchListener mListener;
+ private DisallowInterceptFilter mFilter;
+
+ @Before
+ public void setUp() {
+ mListener = new TestOnItemTouchListener();
+ mFilter = new DisallowInterceptFilter(mListener);
+ }
+
+ @Test
+ public void testForwardsEventsToDelegate() {
+ mFilter.onInterceptTouchEvent(null, TestEvents.Touch.DOWN);
+ mListener.assertOnInterceptTouchEventCalled(1);
+ }
+
+ @Test
+ public void testReflectsDelegateReturnValue() {
+ assertFalse(mFilter.onInterceptTouchEvent(null, TestEvents.Touch.UP));
+ mListener.consumeEvents(true);
+ assertTrue(mFilter.onInterceptTouchEvent(null, TestEvents.Touch.MOVE));
+ }
+
+ @Test
+ public void testRespectsDisallowRequest() {
+ mFilter.onRequestDisallowInterceptTouchEvent(true);
+ mFilter.onInterceptTouchEvent(null, TestEvents.Touch.UP);
+ mListener.assertOnInterceptTouchEventCalled(0);
+ }
+
+ @Test
+ public void testResetsDisallowOnDown() {
+ mFilter.onRequestDisallowInterceptTouchEvent(true);
+ mFilter.onInterceptTouchEvent(null, TestEvents.Touch.DOWN);
+ mListener.assertOnInterceptTouchEventCalled(1);
+ }
+
+ @Test
+ public void testIsResettable() {
+ assertFalse(mFilter.isResetRequired());
+ mFilter.onRequestDisallowInterceptTouchEvent(true);
+ assertTrue(mFilter.isResetRequired());
+ mFilter.reset();
+ assertFalse(mFilter.isResetRequired());
+ }
+
+ @Test
+ public void testResetClearsDisallowBit() {
+ mFilter.onRequestDisallowInterceptTouchEvent(true);
+ mFilter.reset();
+ mFilter.onInterceptTouchEvent(null, TestEvents.Touch.MOVE);
+ mListener.assertOnInterceptTouchEventCalled(1);
+ }
+}
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventBackstopTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventBackstopTest.java
new file mode 100644
index 0000000..0c159ec
--- /dev/null
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventBackstopTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 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.recyclerview.selection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.recyclerview.selection.testing.TestEvents;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class EventBackstopTest {
+
+ private EventBackstop mBackstop;
+
+ @Before
+ public void setUp() {
+ mBackstop = new EventBackstop();
+ }
+
+ @Test
+ public void testConsumesOneUpAfterLongPress() {
+ mBackstop.onLongPress();
+ assertTrue(mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.UP));
+ }
+
+ @Test
+ public void testIgnoresUpActionsAfterFirst() {
+ mBackstop.onLongPress();
+ mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.UP);
+ assertFalse(mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.UP));
+ }
+
+ @Test
+ public void testIgnoresUpWithoutLongPress() {
+ assertFalse(mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.UP));
+ }
+
+ @Test
+ public void testIgnoresOtherActionsAfterLongPress() {
+ mBackstop.onLongPress();
+ assertFalse(mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.DOWN));
+ assertFalse(mBackstop.onInterceptTouchEvent(null, TestEvents.Touch.MOVE));
+ }
+}
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventRouterTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventRouterTest.java
index 1d7c911..b3a01ff 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventRouterTest.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/EventRouterTest.java
@@ -16,16 +16,14 @@
package androidx.recyclerview.selection;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.view.MotionEvent;
-import androidx.annotation.NonNull;
import androidx.recyclerview.selection.testing.TestEvents;
+import androidx.recyclerview.selection.testing.TestOnItemTouchListener;
import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -34,9 +32,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
-import java.util.List;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public class EventRouterTest {
@@ -98,33 +93,4 @@
assertFalse(mRouter.isResetRequired());
}
-
- private static final class TestOnItemTouchListener implements OnItemTouchListener {
-
- private List<MotionEvent> mOnInterceptTouchEventCalls = new ArrayList<>();
- private List<MotionEvent> mOnTouchEventCalls = new ArrayList<>();
-
- @Override
- public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
- mOnInterceptTouchEventCalls.add(e);
- return false;
- }
-
- @Override
- public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
- mOnTouchEventCalls.add(e);
- }
-
- @Override
- public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
- }
-
- void assertOnInterceptTouchEventCalled(int expectedTimesCalled) {
- assertEquals(expectedTimesCalled, mOnInterceptTouchEventCalls.size());
- }
-
- void assertOnTouchEventCalled(int expectedTimesCalled) {
- assertEquals(expectedTimesCalled, mOnTouchEventCalls.size());
- }
- }
}
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
index 3065df1..7444d12 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
@@ -55,6 +55,7 @@
private TestItemDetailsLookup mDetailsLookup;
private SelectionProbe mSelection;
private TestDragListener mDragInitiatedListener;
+ private TestRunnable mLongPressCallback;
@Before
public void setUp() {
@@ -66,6 +67,7 @@
mHapticPerformer = new TestRunnable();
mActivationCallbacks = new TestOnItemActivatedListener<>();
mDragInitiatedListener = new TestDragListener();
+ mLongPressCallback = new TestRunnable();
mInputDelegate = new TouchInputHandler<>(
mSelectionMgr,
@@ -78,7 +80,8 @@
mDragInitiatedListener,
mActivationCallbacks,
new TestFocusDelegate<>(),
- mHapticPerformer);
+ mHapticPerformer,
+ mLongPressCallback::run);
}
@Test
@@ -107,6 +110,16 @@
mSelection.assertSelection(7);
}
+
+ @Test
+ public void testLongPress_NotifiesLongPressCallback() {
+ mSelectionPredicate.setReturnValue(true);
+ mDetailsLookup.initAt(7);
+
+ mInputDelegate.onLongPress(DOWN);
+ mLongPressCallback.assertRun();
+ }
+
@Test
public void testLongPress_UnselectedItem_PerformsHapticFeedback() {
mSelectionPredicate.setReturnValue(true);
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemTouchListener.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemTouchListener.java
new file mode 100644
index 0000000..1f2e8f9
--- /dev/null
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemTouchListener.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 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.recyclerview.selection.testing;
+
+import static org.junit.Assert.assertEquals;
+
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.selection.Resettable;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class TestOnItemTouchListener implements OnItemTouchListener, Resettable {
+
+ private final List<MotionEvent> mOnInterceptTouchEventCalls = new ArrayList<>();
+ private final List<MotionEvent> mOnTouchEventCalls = new ArrayList<>();
+ private boolean mConsumeEvents;
+
+ @Override
+ public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ mOnInterceptTouchEventCalls.add(e);
+ return mConsumeEvents;
+ }
+
+ @Override
+ public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ mOnTouchEventCalls.add(e);
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ }
+
+ public void consumeEvents(boolean enabled) {
+ mConsumeEvents = enabled;
+ }
+
+ public void assertOnInterceptTouchEventCalled(int expectedTimesCalled) {
+ assertEquals(expectedTimesCalled, mOnInterceptTouchEventCalls.size());
+ }
+
+ public void assertOnTouchEventCalled(int expectedTimesCalled) {
+ assertEquals(expectedTimesCalled, mOnTouchEventCalls.size());
+ }
+
+ @Override
+ public boolean isResetRequired() {
+ return !mOnInterceptTouchEventCalls.isEmpty()
+ || !mOnTouchEventCalls.isEmpty()
+ || mConsumeEvents;
+ }
+
+ @Override
+ public void reset() {
+ mOnInterceptTouchEventCalls.clear();
+ mOnTouchEventCalls.clear();
+ mConsumeEvents = false;
+ }
+}
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/DisallowInterceptFilter.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/DisallowInterceptFilter.java
new file mode 100644
index 0000000..6c60805
--- /dev/null
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/DisallowInterceptFilter.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020 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.recyclerview.selection;
+
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
+
+/**
+ * Wrapper class that regulates delivery of MotionEvents to delegate listeners, uniformly
+ * honoring requests to onRequestDisallowInterceptTouchEvent.
+ * Wrap this class around other OnItemTouchListeners to bestow them with
+ * proper support for onRequestDisallowInterceptTouchEvent.
+ */
+// TODO: Replace in-situ "disallow" implementation in EventRouter, ResetManager,
+// BandSelectionHelper, GestureSelectionHelper by wrapping w/ this class.
+class DisallowInterceptFilter implements
+ OnItemTouchListener, Resettable {
+
+ private final OnItemTouchListener mDelegate;
+ private boolean mDisallowIntercept;
+
+ DisallowInterceptFilter(@NonNull OnItemTouchListener delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ // Reset disallow when the event is down as advised in http://b/139141511#comment20.
+ if (mDisallowIntercept && MotionEvents.isActionDown(e)) {
+ mDisallowIntercept = false;
+ }
+ return !mDisallowIntercept && mDelegate.onInterceptTouchEvent(rv, e);
+ }
+
+ @Override
+ public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ mDelegate.onInterceptTouchEvent(rv, e);
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ mDisallowIntercept = true;
+ }
+
+ @Override
+ public boolean isResetRequired() {
+ return mDisallowIntercept;
+ }
+
+ @Override
+ public void reset() {
+ mDisallowIntercept = false;
+ }
+}
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBackstop.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBackstop.java
new file mode 100644
index 0000000..c56daa7
--- /dev/null
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBackstop.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2020 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.recyclerview.selection;
+
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
+
+/**
+ * OnItemTouchListener that claims all ACTION_UP events in streams that have otherwise gone
+ * unclaimed after a LongPress has been detected by GestureDetector.
+ * This addresses issue described in b/166836317, where child view
+ * OnClickListeners were being called unexpectedly.
+ */
+class EventBackstop implements OnItemTouchListener, Resettable {
+
+ private boolean mLongPressFired;
+
+ @Override
+ public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ // We only claim ACTION_UP events after a LongPress event. Were we to claim
+ // all ACTION_UP events we'd deprive RecyclerView of the signal it needs to
+ // initiate fling scrolling.
+ if (MotionEvents.isActionUp(e) && mLongPressFired) {
+ mLongPressFired = false;
+ return true;
+ }
+
+ // Recover from disallow state.
+ if (MotionEvents.isActionDown(e) && isResetRequired()) {
+ reset();
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
+ // We should never receive any events, but were we to...we want to ignore them.
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ throw new UnsupportedOperationException("Wrap me in an InterceptFilter.");
+ }
+
+ @Override
+ public boolean isResetRequired() {
+ return mLongPressFired;
+ }
+
+ @Override
+ public void reset() {
+ mLongPressFired = false;
+ }
+
+ void onLongPress() {
+ mLongPressFired = true;
+ }
+}
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
index 89df922..fa2f1f8 100644
--- a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
@@ -744,9 +744,18 @@
GestureDetectorWrapper gestureDetectorWrapper =
new GestureDetectorWrapper(gestureDetector);
+ // Temp fix for b/166836317.
+ // TODO: Add support for multiple listeners per tool type to EventRouter, then
+ // register backstop with primary router.
+ EventRouter backstopRouter = new EventRouter();
+ EventBackstop backstop = new EventBackstop();
+ DisallowInterceptFilter backstopWrapper = new DisallowInterceptFilter(backstop);
+ backstopRouter.set(MotionEvent.TOOL_TYPE_FINGER, backstopWrapper);
+
// Finally hook the framework up to listening to RecycleView events.
mRecyclerView.addOnItemTouchListener(eventRouter);
mRecyclerView.addOnItemTouchListener(gestureDetectorWrapper);
+ mRecyclerView.addOnItemTouchListener(backstopRouter);
// Reset manager listens for cancel events from RecyclerView. In response to that it
// advises other classes it is time to reset state.
@@ -773,6 +782,9 @@
resetMgr.addResetHandler(gestureSelectionHelper);
resetMgr.addResetHandler(gestureDetectorWrapper);
resetMgr.addResetHandler(eventRouter);
+ resetMgr.addResetHandler(backstopRouter);
+ resetMgr.addResetHandler(backstop);
+ resetMgr.addResetHandler(backstopWrapper);
// But before you move on, there's more work to do. Event plumbing has been
// installed, but we haven't registered any of our helpers or callbacks.
@@ -820,14 +832,7 @@
mKeyProvider,
mDetailsLookup,
mSelectionPredicate,
- new Runnable() {
- @Override
- public void run() {
- if (mSelectionPredicate.canSelectMultiple()) {
- gestureSelectionHelper.start();
- }
- }
- },
+ gestureSelectionHelper::start,
mOnDragInitiatedListener,
mOnItemActivatedListener,
mFocusDelegate,
@@ -836,7 +841,9 @@
public void run() {
mRecyclerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
- });
+ },
+ // Provide temporary glue to address b/166836317
+ backstop::onLongPress);
for (int toolType : mGestureToolTypes) {
gestureRouter.register(toolType, touchHandler);
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
index 5f8d327..5a10446 100644
--- a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
@@ -45,6 +45,7 @@
private final OnDragInitiatedListener mOnDragInitiatedListener;
private final Runnable mGestureStarter;
private final Runnable mHapticPerformer;
+ private final Runnable mLongPressCallback;
TouchInputHandler(
@NonNull SelectionTracker<K> selectionTracker,
@@ -55,7 +56,8 @@
@NonNull OnDragInitiatedListener onDragInitiatedListener,
@NonNull OnItemActivatedListener<K> onItemActivatedListener,
@NonNull FocusDelegate<K> focusDelegate,
- @NonNull Runnable hapticPerformer) {
+ @NonNull Runnable hapticPerformer,
+ @NonNull Runnable longPressCallback) {
super(selectionTracker, keyProvider, focusDelegate);
@@ -72,6 +74,7 @@
mOnItemActivatedListener = onItemActivatedListener;
mOnDragInitiatedListener = onDragInitiatedListener;
mHapticPerformer = hapticPerformer;
+ mLongPressCallback = longPressCallback;
}
@Override
@@ -143,6 +146,9 @@
return;
}
+ // Temprary fix to address b/166836317.
+ mLongPressCallback.run();
+
if (shouldExtendRange(e)) {
extendSelectionRange(item);
mHapticPerformer.run();
diff --git a/samples/Support7Demos/src/main/AndroidManifest.xml b/samples/Support7Demos/src/main/AndroidManifest.xml
index 94f76a2..1381479 100644
--- a/samples/Support7Demos/src/main/AndroidManifest.xml
+++ b/samples/Support7Demos/src/main/AndroidManifest.xml
@@ -277,6 +277,15 @@
</intent-filter>
</activity>
+ <activity android:name=".app.AppCompatWidgetsIcons"
+ android:label="@string/appcompat_widgets_icons"
+ android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".app.AppCompatWidgetsRatingBars"
android:label="@string/appcompat_widgets_ratingbars"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
diff --git a/samples/Support7Demos/src/main/java/com/example/android/supportv7/app/AppCompatWidgetsIcons.java b/samples/Support7Demos/src/main/java/com/example/android/supportv7/app/AppCompatWidgetsIcons.java
new file mode 100644
index 0000000..e7446ce
--- /dev/null
+++ b/samples/Support7Demos/src/main/java/com/example/android/supportv7/app/AppCompatWidgetsIcons.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 com.example.android.supportv7.app;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.android.supportv7.R;
+
+/**
+ * This demonstrates the styled {@link android.widget.Button} widgets in AppCompat.
+ */
+public class AppCompatWidgetsIcons extends AppCompatActivity {
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.appcompat_widgets_icons);
+ }
+
+}
diff --git a/samples/Support7Demos/src/main/res/layout/appcompat_widgets_icons.xml b/samples/Support7Demos/src/main/res/layout/appcompat_widgets_icons.xml
new file mode 100644
index 0000000..1eb3b45
--- /dev/null
+++ b/samples/Support7Demos/src/main/res/layout/appcompat_widgets_icons.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeCutDrawable" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeCopyDrawable" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModePasteDrawable" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeSelectAllDrawable" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="?attr/actionModeShareDrawable" />
+
+ </LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/samples/Support7Demos/src/main/res/values/strings.xml b/samples/Support7Demos/src/main/res/values/strings.xml
index cd873f5..e067d47 100644
--- a/samples/Support7Demos/src/main/res/values/strings.xml
+++ b/samples/Support7Demos/src/main/res/values/strings.xml
@@ -78,6 +78,7 @@
<string name="action_bar_action_mode">AppCompat/Action Bar/Action Mode</string>
<string name="action_bar_hide_scroll">AppCompat/Action Bar/Hide on Scroll</string>
<string name="appcompat_widgets_buttons">AppCompat/Widgets/Buttons</string>
+ <string name="appcompat_widgets_icons">AppCompat/Widgets/Icons</string>
<string name="appcompat_widgets_ratingbars">AppCompat/Widgets/Rating Bars</string>
<string name="appcompat_widgets_spinners">AppCompat/Widgets/Spinners</string>
<string name="appcompat_widgets_switches">AppCompat/Widgets/Switches</string>
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java b/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java
index 1d4ac84..0da01ad 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java
+++ b/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java
@@ -717,7 +717,7 @@
}
@Override
- public void onDrawInternal$wear_watchface_debug(
+ public void renderInternal$wear_watchface_debug(
@NotNull Calendar calendar) {
}
},
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
index 1e5f975..4ac16c6 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
@@ -34,12 +34,11 @@
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationsHolder
import androidx.wear.watchface.DrawMode
-import androidx.wear.watchface.UnitSquareBoundsProvider
-import androidx.wear.watchface.WatchFaceHost
-import androidx.wear.watchface.WatchState
import androidx.wear.watchface.WatchFace
+import androidx.wear.watchface.WatchFaceHost
import androidx.wear.watchface.WatchFaceService
import androidx.wear.watchface.WatchFaceType
+import androidx.wear.watchface.WatchState
import androidx.wear.watchface.style.BooleanUserStyleCategory
import androidx.wear.watchface.style.DoubleRangeUserStyleCategory
import androidx.wear.watchface.style.ListUserStyleCategory
@@ -114,9 +113,8 @@
)
val complicationSlots = ComplicationsHolder(
listOf(
- Complication(
+ Complication.Builder(
EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
watchFaceStyle.getComplicationDrawableRenderer(this, watchState),
intArrayOf(
ComplicationData.TYPE_RANGED_VALUE,
@@ -125,12 +123,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK),
- ComplicationData.TYPE_SHORT_TEXT
- ),
- Complication(
+ Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK)
+ ).setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build(),
+ Complication.Builder(
EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.6f, 0.4f, 0.8f, 0.6f)),
watchFaceStyle.getComplicationDrawableRenderer(this, watchState),
intArrayOf(
ComplicationData.TYPE_RANGED_VALUE,
@@ -139,9 +137,10 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT)
+ ).setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build()
)
)
val renderer = ExampleCanvasRenderer(
@@ -238,9 +237,8 @@
// Apply the userStyle to the complications. ComplicationDrawables for each of the
// styles are defined in XML so we need to replace the complication's drawables.
for ((_, complication) in complicationsHolder.complications) {
- complication.setRenderer(
+ complication.renderer =
watchFaceColorStyle.getComplicationDrawableRenderer(context, watchState)
- )
}
val drawPipsOption =
@@ -256,7 +254,7 @@
)
}
- override fun onDraw(canvas: Canvas, bounds: Rect, calendar: Calendar) {
+ override fun render(canvas: Canvas, bounds: Rect, calendar: Calendar) {
val style = if (drawMode == DrawMode.AMBIENT) {
watchFaceColorStyle.ambientStyle
} else {
@@ -466,7 +464,7 @@
if (drawMode == DrawMode.COMPLICATION_SELECT) {
drawComplicationSelectDashBorders(
canvas,
- complication.boundsProvider.computeBounds(complication, screen)
+ complication.computeBounds(screen)
)
}
}
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
index 5891e22..499c6de 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
@@ -437,7 +437,7 @@
}
}
- override fun onDraw(calendar: Calendar) {
+ override fun render(calendar: Calendar) {
// Draw background color and select the appropriate view projection matrix. The background
// should always be black in ambient mode. The view projection matrix used is overhead in
// ambient. In interactive mode, it's tilted depending on the current time.
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
index 8414197..813b5b4 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
@@ -32,12 +32,11 @@
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationDrawableRenderer
import androidx.wear.watchface.ComplicationsHolder
-import androidx.wear.watchface.UnitSquareBoundsProvider
-import androidx.wear.watchface.WatchFaceHost
-import androidx.wear.watchface.WatchState
import androidx.wear.watchface.WatchFace
+import androidx.wear.watchface.WatchFaceHost
import androidx.wear.watchface.WatchFaceService
import androidx.wear.watchface.WatchFaceType
+import androidx.wear.watchface.WatchState
import androidx.wear.watchface.style.ListUserStyleCategory
import androidx.wear.watchface.style.UserStyleCategory
import androidx.wear.watchface.style.UserStyleManager
@@ -99,9 +98,8 @@
)
val complicationSlots = ComplicationsHolder(
listOf(
- Complication(
+ Complication.Builder(
/*id */ 0,
- UnitSquareBoundsProvider(RectF(0.15625f, 0.1875f, 0.84375f, 0.3125f)),
ComplicationDrawableRenderer(
ComplicationDrawable(this),
watchState
@@ -113,14 +111,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK),
- ComplicationData.TYPE_SHORT_TEXT
- ),
- Complication(
+ Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK)
+ ).setUnitSquareBounds(RectF(0.15625f, 0.1875f, 0.84375f, 0.3125f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build(),
+ Complication.Builder(
/*id */ 1,
- UnitSquareBoundsProvider(
- RectF(0.1f, 0.5625f, 0.35f, 0.8125f)
- ),
ComplicationDrawableRenderer(
ComplicationDrawable(this),
watchState
@@ -132,9 +128,10 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT)
+ ).setUnitSquareBounds(RectF(0.1f, 0.5625f, 0.35f, 0.8125f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build()
)
)
@@ -155,7 +152,7 @@
})
}
- override fun onDraw(
+ override fun render(
canvas: Canvas,
bounds: Rect,
calendar: Calendar
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
index 54af2af..3ec41bd 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
@@ -26,20 +26,19 @@
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationsHolder
import androidx.wear.watchface.NoInvalidateWatchFaceHostApi
-import androidx.wear.watchface.UnitSquareBoundsProvider
-import androidx.wear.watchface.WatchFaceHost
-import androidx.wear.watchface.WatchState
import androidx.wear.watchface.WatchFace
+import androidx.wear.watchface.WatchFaceHost
import androidx.wear.watchface.WatchFaceService
import androidx.wear.watchface.WatchFaceType
+import androidx.wear.watchface.WatchState
import androidx.wear.watchface.samples.EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID
import androidx.wear.watchface.samples.EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID
import androidx.wear.watchface.samples.ExampleCanvasRenderer
import androidx.wear.watchface.samples.R
import androidx.wear.watchface.samples.WatchFaceColorStyle
import androidx.wear.watchface.style.BooleanUserStyleCategory
-import androidx.wear.watchface.style.ListUserStyleCategory
import androidx.wear.watchface.style.DoubleRangeUserStyleCategory
+import androidx.wear.watchface.style.ListUserStyleCategory
import androidx.wear.watchface.style.UserStyleManager
/** A simple canvas test watch face for integration tests. */
@@ -103,9 +102,8 @@
)
val complicationSlots = ComplicationsHolder(
listOf(
- Complication(
+ Complication.Builder(
EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
watchFaceStyle.getComplicationDrawableRenderer(this, watchState),
intArrayOf(
ComplicationData.TYPE_RANGED_VALUE,
@@ -114,12 +112,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK),
- ComplicationData.TYPE_SHORT_TEXT
- ),
- Complication(
+ Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK)
+ ).setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build(),
+ Complication.Builder(
EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.6f, 0.4f, 0.8f, 0.6f)),
watchFaceStyle.getComplicationDrawableRenderer(this, watchState),
intArrayOf(
ComplicationData.TYPE_RANGED_VALUE,
@@ -128,9 +126,10 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.STEP_COUNT)
+ ).setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
+ .setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .build()
)
)
val renderer = ExampleCanvasRenderer(
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
index 645071a..3c2d61f 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
@@ -46,7 +46,6 @@
import androidx.wear.watchface.WatchFaceService
import androidx.wear.watchface.samples.EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID
import org.junit.Before
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -267,7 +266,6 @@
}
@Test
- @Ignore("Needs fixed image")
fun testAmbientScreenshot() {
handler.post {
initCanvasWatchFace()
@@ -276,7 +274,7 @@
}
renderDoneLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
- bitmap.assertAgainstGolden(screenshotRule, "ambient_screenshot")
+ bitmap.assertAgainstGolden(screenshotRule, "ambient_screenshot2")
}
@Test
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
index fe3ea1d..caf9661 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
@@ -21,7 +21,6 @@
import android.graphics.Color
import android.graphics.Rect
import android.icu.util.Calendar
-import android.util.Log
import android.view.SurfaceHolder
import androidx.annotation.IntDef
import androidx.annotation.UiThread
@@ -61,25 +60,18 @@
/** The type of canvas to use. */
@CanvasType private val canvasType: Int
) : Renderer(surfaceHolder, userStyleManager, watchState) {
- private companion object {
- private const val TAG = "CanvasRenderer"
- }
- internal override fun onDrawInternal(
+ internal override fun renderInternal(
calendar: Calendar
) {
- val canvas = if (canvasType == CanvasType.HARDWARE) {
+ val canvas = (if (canvasType == CanvasType.HARDWARE) {
surfaceHolder.lockHardwareCanvas()
} else {
surfaceHolder.lockCanvas()
- }
- if (canvas == null) {
- Log.e(TAG, "Null canvas returned when locking the SurfaceHolder.")
- return
- }
+ }) ?: return
try {
if (watchState.isVisible) {
- onDraw(canvas, surfaceHolder.surfaceFrame, calendar)
+ render(canvas, surfaceHolder.surfaceFrame, calendar)
} else {
canvas.drawColor(Color.BLACK)
}
@@ -100,7 +92,7 @@
)
val prevDrawMode = drawMode
this.drawMode = drawMode
- onDraw(Canvas(bitmap), screenBounds, calendar)
+ render(Canvas(bitmap), screenBounds, calendar)
this.drawMode = prevDrawMode
return bitmap
}
@@ -116,7 +108,7 @@
* @param calendar The current {@link Calendar}
*/
@UiThread
- protected abstract fun onDraw(
+ abstract fun render(
canvas: Canvas,
bounds: Rect,
calendar: Calendar
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
index c32bd26..872747c 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
@@ -28,65 +28,6 @@
import androidx.wear.complications.SystemProviders
import androidx.wear.complications.rendering.ComplicationDrawable
-/**
- * Complications use a ComplicationBoundsProvider to compute their bounds.
- */
-interface ComplicationBoundsProvider {
- /**
- * Computes the screen space bounds of the complication. This can be animated.
- *
- * @param complication The {@link Complication} to compute bounds for
- * @param screen A {@link Rect} describing the bounds of the screen
- */
- fun computeBounds(complication: Complication, screen: Rect): Rect
-}
-
-/**
- * A {@link ComplicationBoundsProvider} for watch faces that wish to have a full screen user
- * selectable backdrop. This sort of complication isn't clickable and at most one may be present in
- * the list of complications.
- */
-class BackgroundComplicationBoundsProvider : ComplicationBoundsProvider {
- /** {@inheritDoc} */
- override fun computeBounds(
- complication: Complication,
- screen: Rect
- ) = screen // A BackgroundComplication covers the whole screen.
-}
-
-/**
- * A {@link ComplicationBoundsProvider} which converts bounds provided in the unit square [0..1] to
- * device pixels. NB 0 and 1 are included in the unit square.
- */
-class UnitSquareBoundsProvider(
- /**
- * Fractional bounds for the complication (clamped to the unit square.) which get converted
- * to screen space coordinates.
- */
- unitSquareBounds: RectF
-) : ComplicationBoundsProvider {
-
- private companion object {
- private val unitSquare = RectF(0f, 0f, 1f, 1f)
- }
-
- private val clampedUnitSquareBounds = RectF().apply {
- setIntersect(
- unitSquareBounds,
- unitSquare
- )
- }
-
- /** {@inheritDoc} */
- override fun computeBounds(complication: Complication, screen: Rect) =
- Rect(
- (clampedUnitSquareBounds.left * screen.width()).toInt(),
- (clampedUnitSquareBounds.top * screen.height()).toInt(),
- (clampedUnitSquareBounds.right * screen.width()).toInt(),
- (clampedUnitSquareBounds.bottom * screen.height()).toInt()
- )
-}
-
/** Common interface for rendering complications. */
interface ComplicationRenderer {
/**
@@ -254,31 +195,88 @@
* Represents a individual complication on the screen. The number of complications is fixed
* (see {@link ComplicationsHolder}) but complications can be enabled or disabled as needed.
*/
-class Complication @JvmOverloads constructor(
- /** The watch face's ID for this complication. */
+class Complication internal constructor(
internal val id: Int,
-
- /** An interface that can provide the bounds for this Complication. */
- val boundsProvider: ComplicationBoundsProvider,
-
- /**
- * The renderer for this Complication. Renderers may not be sharable between complications.
- */
- internal var renderer: ComplicationRenderer,
-
- /**
- * The types of complication supported by this Complication. Passed into {@link
- * ComplicationHelperActivity#createProviderChooserHelperIntent} during complication
- * configuration.
- */
+ @ComplicationBoundsType internal val boundsType: Int,
+ val unitSquareBounds: RectF,
+ renderer: ComplicationRenderer,
internal val supportedTypes: IntArray,
-
- /** Default complication provider. */
internal val defaultProvider: DefaultComplicationProvider,
-
- /** Default complication provider data type. */
- internal val defaultProviderType: Int = WatchFace.DEFAULT_PROVIDER_TYPE_NONE
+ internal val defaultProviderType: Int
) {
+ private companion object {
+ internal val unitSquare = RectF(0f, 0f, 1f, 1f)
+ }
+
+ class Builder(
+ /** The watch face's ID for this complication. */
+ private val id: Int,
+
+ /**
+ * The renderer for this Complication. Renderers may not be sharable between complications.
+ */
+ private val renderer: ComplicationRenderer,
+
+ /**
+ * The types of complication supported by this Complication. Passed into {@link
+ * ComplicationHelperActivity#createProviderChooserHelperIntent} during complication
+ * configuration.
+ */
+ private val supportedTypes: IntArray,
+
+ /** Default complication provider. */
+ private val defaultProvider: DefaultComplicationProvider
+ ) {
+ @ComplicationBoundsType
+ private var boundsType: Int = ComplicationBoundsType.ROUND_RECT
+ private lateinit var unitSquareBounds: RectF
+
+ private var defaultProviderType: Int = WatchFace.DEFAULT_PROVIDER_TYPE_NONE
+
+ /** Sets the default complication provider data type. */
+ fun setDefaultProviderType(defaultProviderType: Int): Builder {
+ this.defaultProviderType = defaultProviderType
+ return this
+ }
+
+ /**
+ * Fractional bounds for the complication, clamped to the unit square [0..1], which get
+ * converted to screen space coordinates. NB 0 and 1 are included in the unit square.
+ */
+ fun setUnitSquareBounds(unitSquareBounds: RectF): Builder {
+ boundsType = ComplicationBoundsType.ROUND_RECT
+
+ this.unitSquareBounds = RectF().apply {
+ setIntersect(
+ unitSquareBounds,
+ unitSquare
+ )
+ }
+ return this
+ }
+
+ /**
+ * A background complication is for watch faces that wish to have a full screen user
+ * selectable backdrop. This sort of complication isn't clickable and at most one may be
+ * present in the list of complications.
+ */
+ fun setBackgroundComplication(): Builder {
+ boundsType = ComplicationBoundsType.BACKGROUND
+ this.unitSquareBounds = RectF(0f, 0f, 1f, 1f)
+ return this
+ }
+
+ fun build() = Complication(
+ id,
+ boundsType,
+ unitSquareBounds,
+ renderer,
+ supportedTypes,
+ defaultProvider,
+ defaultProviderType
+ )
+ }
+
init {
renderer.onAttach(this)
}
@@ -310,7 +308,9 @@
private var _enabled = true
var enabled: Boolean
+ @UiThread
get() = _enabled
+ @UiThread
set(value) {
_enabled = value
@@ -319,18 +319,19 @@
complicationsHolder.scheduleUpdateActiveComplications()
}
- /**
- * Sets the current {@link ComplicationRenderer}. This is useful if based on the style the
- * watch face needs to use a different renderer.
- */
- @UiThread
- fun setRenderer(renderer: ComplicationRenderer) {
- renderer.onDetach()
- renderer.setData(this.renderer.getData())
- this.renderer = renderer
- renderer.onAttach(this)
- initRenderer()
- }
+ private var _renderer = renderer
+
+ var renderer: ComplicationRenderer
+ @UiThread
+ get() = _renderer
+ @UiThread
+ set(value) {
+ renderer.onDetach()
+ value.setData(renderer.getData())
+ _renderer = value
+ value.onAttach(this)
+ initRenderer()
+ }
/**
* Watch faces should use this method to render a complication. Note the system may call this.
@@ -345,10 +346,7 @@
calendar: Calendar,
@DrawMode drawMode: Int
) {
- val bounds = boundsProvider.computeBounds(
- this,
- Rect(0, 0, canvas.width, canvas.height)
- )
+ val bounds = computeBounds(Rect(0, 0, canvas.width, canvas.height))
renderer.onDraw(canvas, bounds, calendar, drawMode)
}
@@ -386,4 +384,13 @@
complicationsHolder.scheduleUpdateActiveComplications()
}
}
+
+ /** Computes the bounds of the complication by converting the unitSquareBounds to pixels. */
+ fun computeBounds(screen: Rect) =
+ Rect(
+ (unitSquareBounds.left * screen.width()).toInt(),
+ (unitSquareBounds.top * screen.height()).toInt(),
+ (unitSquareBounds.right * screen.width()).toInt(),
+ (unitSquareBounds.bottom * screen.height()).toInt()
+ )
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsHolder.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsHolder.kt
index 7ec06d0..0302f6f 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsHolder.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsHolder.kt
@@ -141,17 +141,14 @@
// Generate a ContentDescriptionLabel and send complication bounds for
// non-background complications.
val data = complication.renderer.getData()
- val complicationBounds = complication.boundsProvider.computeBounds(
- complication, renderer.screenBounds
- )
-
- if (complication.boundsProvider is BackgroundComplicationBoundsProvider) {
+ if (complication.boundsType == ComplicationBoundsType.BACKGROUND) {
watchFaceHostApi.setComplicationDetails(
id,
- complicationBounds,
+ renderer.screenBounds,
ComplicationBoundsType.BACKGROUND
)
} else {
+ val complicationBounds = complication.computeBounds(renderer.screenBounds)
if (data != null) {
labels.add(
ContentDescriptionLabel(
@@ -228,11 +225,8 @@
*/
fun getComplicationAt(x: Int, y: Int): Complication? {
return complications.entries.firstOrNull {
- it.value.enabled && it.value.boundsProvider !is BackgroundComplicationBoundsProvider &&
- it.value.boundsProvider.computeBounds(
- it.value,
- renderer.screenBounds
- ).contains(x, y)
+ it.value.enabled && it.value.boundsType != ComplicationBoundsType.BACKGROUND &&
+ it.value.computeBounds(renderer.screenBounds).contains(x, y)
}?.value
}
@@ -243,7 +237,7 @@
*/
fun getBackgroundComplication(): Complication? {
return complications.entries.firstOrNull {
- it.value.boundsProvider is BackgroundComplicationBoundsProvider
+ it.value.boundsType == ComplicationBoundsType.BACKGROUND
}?.value
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Gles2Renderer.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Gles2Renderer.kt
index 466814c..1f47904 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Gles2Renderer.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Gles2Renderer.kt
@@ -234,11 +234,11 @@
@UiThread
open fun onGlSurfaceCreated(width: Int, height: Int) {}
- internal override fun onDrawInternal(
+ internal override fun renderInternal(
calendar: Calendar
) {
makeContextCurrent()
- onDraw(calendar)
+ render(calendar)
if (!EGL14.eglSwapBuffers(eglDisplay, eglSurface)) {
Log.w(TAG, "eglSwapBuffers failed")
}
@@ -254,7 +254,7 @@
val pixelBuf = ByteBuffer.allocateDirect(width * height * 4)
makeContextCurrent()
this.drawMode = drawMode
- onDraw(calendar)
+ render(calendar)
GLES20.glFinish()
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuf)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
@@ -270,7 +270,5 @@
* @param calendar The current {@link Calendar}
*/
@UiThread
- protected abstract fun onDraw(
- calendar: Calendar
- )
+ abstract fun render(calendar: Calendar)
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Renderer.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Renderer.kt
index 8652946..8266444 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Renderer.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Renderer.kt
@@ -55,10 +55,9 @@
var drawMode: Int
get() = _drawMode ?: DrawMode.INTERACTIVE
internal set(value) {
- val newDrawMode = maybeOverrideDrawMode(value)
- if (newDrawMode != _drawMode) {
- _drawMode = newDrawMode
- onDrawModeChanged(newDrawMode)
+ if (value != _drawMode) {
+ _drawMode = value
+ onDrawModeChanged(value)
}
}
@@ -77,9 +76,7 @@
* @return A {@link Bitmap} containing a screenshot of the watch face
*/
@UiThread
- internal abstract fun onDrawInternal(
- calendar: Calendar
- )
+ internal abstract fun renderInternal(calendar: Calendar)
/**
* Renders the watch face into a Bitmap with the user style specified by the
@@ -140,7 +137,8 @@
/**
* The system periodically (at least once per minute) calls onTimeTick() to trigger a display
* update. If the watch face needs to animate with an interactive frame rate, calls to
- * invalidate must be scheduled. This method controls whether or not we should do that.
+ * invalidate must be scheduled. This method controls whether or not we should do that and if
+ * shouldAnimate returns true we inhibit entering {@link DrawMode#AMBIENT}.
*
* By default we remain at an interactive frame rate when the watch face is visible and we're
* not in ambient mode. Watchfaces with animated transitions for entering ambient mode may
@@ -150,15 +148,4 @@
*/
@UiThread
open fun shouldAnimate() = watchState.isVisible && !watchState.isAmbient
-
- /**
- * The {@link DrawMode} is recomputed before every onDraw call. This method allows the subclass
- * to override the {@link DrawMode}. e.g. to support enter/exit ambient animations which may
- * wish to defer rendering changes.
- *
- * @param proposedDrawMode The proposed {@link DrawMode} to use for rendering based
- * @return The {@link DrawMode} to actually use for rendering
- */
- @UiThread
- open fun maybeOverrideDrawMode(@DrawMode proposedDrawMode: Int) = proposedDrawMode
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index 22592fa..abff28e 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -676,7 +676,9 @@
} else {
DrawMode.INTERACTIVE
}
- if (watchState.isAmbient) {
+ // Watch faces may wish to run an animation while entering ambient mode and we let them
+ // defer entering ambient mode.
+ if (watchState.isAmbient && !renderer.shouldAnimate()) {
newDrawMode = DrawMode.AMBIENT
} else if (muteMode) {
newDrawMode = DrawMode.MUTE
@@ -689,7 +691,7 @@
internal fun onDraw() {
setCalendarTime(systemTimeProvider.getSystemTimeMillis())
maybeUpdateDrawMode()
- renderer.onDrawInternal(calendar)
+ renderer.renderInternal(calendar)
val currentTimeMillis = systemTimeProvider.getSystemTimeMillis()
setCalendarTime(currentTimeMillis)
@@ -703,7 +705,7 @@
internal fun onSurfaceRedrawNeeded() {
setCalendarTime(systemTimeProvider.getSystemTimeMillis())
maybeUpdateDrawMode()
- renderer.onDrawInternal(calendar)
+ renderer.renderInternal(calendar)
}
/** @hide */
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index d7c24ea..5fef9c6 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -523,10 +523,7 @@
}
val complication = watchFace.complicationsHolder[complicationId]
if (complication != null) {
- val bounds = complication.boundsProvider.computeBounds(
- complication,
- watchFace.renderer.screenBounds
- )
+ val bounds = complication.computeBounds(watchFace.renderer.screenBounds)
val complicationBitmap =
Bitmap.createBitmap(
bounds.width(), bounds.height(),
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
index 9f4d3b3..e80d7a9 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
@@ -34,6 +34,7 @@
* Whether or not the watch is in airplane mode. Only valid if
* {@link android.support.wearable.watchface.WatchFaceStyle#hideNotificationIndicator} is true.
*/
+ @get:JvmName("inAirplaneMode")
var inAirplaneMode = false
private set
@@ -92,10 +93,12 @@
private set
/** Whether or not the watch has low bit ambient support. */
+ @get:JvmName("hasLowBitAmbient")
var hasLowBitAmbient = false
private set
/** Whether or not the watch has burn in protection support. */
+ @get:JvmName("hasBurnInProtection")
var hasBurnInProtection = false
private set
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
index 3008b28..de2db2c 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
@@ -216,24 +216,30 @@
var configOption: ConfigOption? = null
}
-/**
- * Wraps a given [Drawable] with a standard background to match the normal preference icon
- * styling. The wrapping is idempotent, calling it multiple times will only wrap the icon once.
- *
- * @param context the current [Context], used for resolving resources.
- * @param icon the icon to wrap.
- * @return the wrapped icon.
- */
-internal fun wrapIcon(
- context: Context,
- icon: Drawable
-): Drawable {
- if (icon is LayerDrawable && icon.findDrawableByLayerId(R.id.nested_icon) != null) {
- return icon // icon was already wrapped, return the icon without modifying it
+internal class Helper {
+ companion object {
+ /**
+ * Wraps a given [Drawable] with a standard background to match the normal preference icon
+ * styling. The wrapping is idempotent, calling it multiple times will only wrap the icon
+ * once.
+ *
+ * @param context the current [Context], used for resolving resources.
+ * @param icon the icon to wrap.
+ * @return the wrapped icon.
+ */
+ fun wrapIcon(
+ context: Context,
+ icon: Drawable
+ ): Drawable {
+ if (icon is LayerDrawable && icon.findDrawableByLayerId(R.id.nested_icon) != null) {
+ return icon // icon was already wrapped, return the icon without modifying it
+ }
+ val wrappedDrawable =
+ (context.getDrawable(R.drawable.preference_wrapped_icon) as LayerDrawable)
+ wrappedDrawable.setDrawableByLayerId(R.id.nested_icon, icon)
+ return wrappedDrawable
+ }
}
- val wrappedDrawable = (context.getDrawable(R.drawable.preference_wrapped_icon) as LayerDrawable)
- wrappedDrawable.setDrawableByLayerId(R.id.nested_icon, icon)
- return wrappedDrawable
}
/** Adapter for top level config options. */
@@ -272,7 +278,7 @@
context,
{ drawable ->
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
- wrapIcon(context, drawable),
+ Helper.wrapIcon(context, drawable),
/* top = */ null,
/* end = */ null,
/* bottom = */ null
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
index 5b4b921..b545795 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
@@ -249,7 +249,7 @@
context,
{ drawable ->
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
- wrapIcon(context, drawable),
+ Helper.wrapIcon(context, drawable),
/* top = */ null,
/* end = */ null,
/* bottom = */ null
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/TestCommon.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/TestCommon.kt
index bba9724..72a714b 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/TestCommon.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/TestCommon.kt
@@ -203,7 +203,7 @@
}
}
-class TestRenderer(
+open class TestRenderer(
surfaceHolder: SurfaceHolder,
userStyleManager: UserStyleManager,
watchState: WatchState
@@ -212,7 +212,7 @@
var lastOnDrawCalendar: Calendar? = null
var lastDrawMode = DrawMode.INTERACTIVE
- override fun onDraw(
+ override fun render(
canvas: Canvas,
bounds: Rect,
calendar: Calendar
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index d46bf7d..33a074a 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -130,9 +130,8 @@
ListUserStyleCategory.ListOption("bad_option", "Bad", icon = null)
private val leftComplication =
- Complication(
+ Complication.Builder(
LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableLeft, systemState).apply {
setData(createComplicationData())
},
@@ -143,14 +142,14 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.SUNRISE_SUNSET),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.SUNRISE_SUNSET)
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .build()
private val rightComplication =
- Complication(
+ Complication.Builder(
RIGHT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.6f, 0.4f, 0.8f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableRight, systemState).apply {
setData(createComplicationData())
},
@@ -161,23 +160,24 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK)
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
+ .build()
private val backgroundComplication =
- Complication(
+ Complication.Builder(
BACKGROUND_COMPLICATION_ID,
- BackgroundComplicationBoundsProvider(),
ComplicationDrawableRenderer(complicationDrawableRight, systemState).apply {
setData(createComplicationData())
},
intArrayOf(
ComplicationData.TYPE_LARGE_IMAGE
),
- Complication.DefaultComplicationProvider(),
- ComplicationData.TYPE_LARGE_IMAGE
- )
+ Complication.DefaultComplicationProvider()
+ ).setDefaultProviderType(ComplicationData.TYPE_LARGE_IMAGE)
+ .setBackgroundComplication()
+ .build()
private lateinit var renderer: TestRenderer
private lateinit var complicationsHolder: ComplicationsHolder
@@ -1049,17 +1049,17 @@
fun defaultProvidersWithFallbacks_newApi() {
val provider1 = ComponentName("com.app1", "com.app1.App1")
val provider2 = ComponentName("com.app2", "com.app2.App2")
- val complication = Complication(
+ val complication = Complication.Builder(
LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableLeft, systemState),
intArrayOf(),
Complication.DefaultComplicationProvider(
listOf(provider1, provider2),
SystemProviders.SUNRISE_SUNSET
- ),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ )
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .build()
initEngine(WatchFaceType.ANALOG, listOf(complication), emptyList())
verify(iWatchFaceService).setDefaultComplicationProviderWithFallbacks(
@@ -1074,17 +1074,17 @@
fun defaultProvidersWithFallbacks_oldApi() {
val provider1 = ComponentName("com.app1", "com.app1.App1")
val provider2 = ComponentName("com.app2", "com.app2.App2")
- val complication = Complication(
+ val complication = Complication.Builder(
LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableLeft, systemState),
intArrayOf(),
Complication.DefaultComplicationProvider(
listOf(provider1, provider2),
SystemProviders.SUNRISE_SUNSET
- ),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ )
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .build()
initEngine(WatchFaceType.ANALOG, listOf(complication), emptyList(), apiVersion = 0)
verify(iWatchFaceService).setDefaultComplicationProvider(
@@ -1109,4 +1109,41 @@
initEngine(WatchFaceType.DIGITAL, emptyList(), emptyList(), apiVersion = 4)
verify(iWatchFaceService).registerIWatchFaceCommand(any())
}
+
+ @Test
+ fun shouldAnimateOverrideControlsEnteringAmbientMode() {
+ var styleManager = UserStyleManager(emptyList())
+ var testRenderer = object : TestRenderer(surfaceHolder, styleManager, systemState) {
+ var animate = true
+ override fun shouldAnimate() = animate
+ }
+ val service = TestWatchFaceService(
+ WatchFaceType.ANALOG,
+ ComplicationsHolder(emptyList()),
+ testRenderer,
+ UserStyleManager(emptyList()),
+ systemState,
+ handler,
+ INTERACTIVE_UPDATE_RATE_MS
+ )
+
+ engineWrapper = service.onCreateEngine() as WatchFaceService.EngineWrapper
+ engineWrapper.onCreate(surfaceHolder)
+ `when`(surfaceHolder.surfaceFrame).thenReturn(ONE_HUNDRED_BY_ONE_HUNDRED_RECT)
+
+ // Trigger watch face creation.
+ engineWrapper.onSurfaceChanged(surfaceHolder, 0, 100, 100)
+ sendBinder(engineWrapper, apiVersion = 2)
+ watchFace = service.watchFace
+
+ // Enter ambient mode.
+ systemState.onAmbientModeChanged(true)
+ watchFace.maybeUpdateDrawMode()
+ assertThat(testRenderer.drawMode).isEqualTo(DrawMode.INTERACTIVE)
+
+ // Simulate enter ambient animation finishing.
+ testRenderer.animate = false
+ watchFace.maybeUpdateDrawMode()
+ assertThat(testRenderer.drawMode).isEqualTo(DrawMode.AMBIENT)
+ }
}
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
index 62e8758..9d78007 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
@@ -29,11 +29,9 @@
import androidx.test.core.app.ApplicationProvider
import androidx.wear.complications.SystemProviders
import androidx.wear.complications.rendering.ComplicationDrawable
-import androidx.wear.watchface.BackgroundComplicationBoundsProvider
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationDrawableRenderer
import androidx.wear.watchface.ComplicationsHolder
-import androidx.wear.watchface.UnitSquareBoundsProvider
import androidx.wear.watchface.Renderer
import androidx.wear.watchface.WatchState
import androidx.wear.watchface.WatchFaceTestRunner
@@ -114,9 +112,8 @@
)
private val leftComplication =
- Complication(
+ Complication.Builder(
LEFT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.2f, 0.4f, 0.4f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableLeft, systemState).apply {
setData(createComplicationData() )
},
@@ -127,14 +124,14 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.SUNRISE_SUNSET),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.SUNRISE_SUNSET)
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
+ .build()
private val rightComplication =
- Complication(
+ Complication.Builder(
RIGHT_COMPLICATION_ID,
- UnitSquareBoundsProvider(RectF(0.6f, 0.4f, 0.8f, 0.6f)),
ComplicationDrawableRenderer(complicationDrawableRight, systemState).apply {
setData(createComplicationData() )
},
@@ -145,23 +142,24 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK),
- ComplicationData.TYPE_SHORT_TEXT
- )
+ Complication.DefaultComplicationProvider(SystemProviders.DAY_OF_WEEK)
+ ).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
+ .setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
+ .build()
private val backgroundComplication =
- Complication(
+ Complication.Builder(
BACKGROUND_COMPLICATION_ID,
- BackgroundComplicationBoundsProvider(),
ComplicationDrawableRenderer(complicationDrawableRight, systemState).apply {
setData(createComplicationData() )
},
intArrayOf(
ComplicationData.TYPE_LARGE_IMAGE
),
- Complication.DefaultComplicationProvider(),
- ComplicationData.TYPE_LARGE_IMAGE
- )
+ Complication.DefaultComplicationProvider()
+ ).setDefaultProviderType(ComplicationData.TYPE_LARGE_IMAGE)
+ .setBackgroundComplication()
+ .build()
private val calendar = Calendar.getInstance().apply {
timeInMillis = 1000L
@@ -184,7 +182,7 @@
val complicationSet = ComplicationsHolder(
complications,
object : Renderer(surfaceHolder, userStyleManager, WatchState()) {
- override fun onDrawInternal(calendar: Calendar) {}
+ override fun renderInternal(calendar: Calendar) {}
override fun takeScreenshot(calendar: Calendar, drawMode: Int): Bitmap {
throw RuntimeException("Not Implemented!")