aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Android.mk11
-rw-r--r--common/buildconfig.mk43
-rw-r--r--common/res/drawable/setup_selector_background.xml17
-rw-r--r--common/res/layout/activity_setup.xml (renamed from common/res/layout/activity_stepped_setup.xml)0
-rw-r--r--common/res/layout/fragment_setup_multi_pane.xml11
-rw-r--r--common/res/values-af/strings.xml21
-rw-r--r--common/res/values-am/strings.xml21
-rw-r--r--common/res/values-ar/strings.xml21
-rw-r--r--common/res/values-az-rAZ/strings.xml21
-rw-r--r--common/res/values-bg/strings.xml21
-rw-r--r--common/res/values-bn-rBD/strings.xml21
-rw-r--r--common/res/values-ca/strings.xml21
-rw-r--r--common/res/values-cs/strings.xml21
-rw-r--r--common/res/values-da/strings.xml21
-rw-r--r--common/res/values-de/strings.xml21
-rw-r--r--common/res/values-el/strings.xml21
-rw-r--r--common/res/values-en-rAU/strings.xml21
-rw-r--r--common/res/values-en-rGB/strings.xml21
-rw-r--r--common/res/values-en-rIN/strings.xml21
-rw-r--r--common/res/values-es-rUS/strings.xml21
-rw-r--r--common/res/values-es/strings.xml21
-rw-r--r--common/res/values-et-rEE/strings.xml21
-rw-r--r--common/res/values-eu-rES/strings.xml21
-rw-r--r--common/res/values-fa/strings.xml21
-rw-r--r--common/res/values-fi/strings.xml21
-rw-r--r--common/res/values-fr-rCA/strings.xml21
-rw-r--r--common/res/values-fr/strings.xml21
-rw-r--r--common/res/values-gl-rES/strings.xml21
-rw-r--r--common/res/values-hi/strings.xml21
-rw-r--r--common/res/values-hr/strings.xml21
-rw-r--r--common/res/values-hu/strings.xml21
-rw-r--r--common/res/values-hy-rAM/strings.xml21
-rw-r--r--common/res/values-in/strings.xml21
-rw-r--r--common/res/values-is-rIS/strings.xml21
-rw-r--r--common/res/values-it/strings.xml21
-rw-r--r--common/res/values-iw/strings.xml21
-rw-r--r--common/res/values-ja/strings.xml21
-rw-r--r--common/res/values-ka-rGE/strings.xml21
-rw-r--r--common/res/values-kk-rKZ/strings.xml21
-rw-r--r--common/res/values-km-rKH/strings.xml21
-rw-r--r--common/res/values-kn-rIN/strings.xml21
-rw-r--r--common/res/values-ko/strings.xml21
-rw-r--r--common/res/values-ky-rKG/strings.xml21
-rw-r--r--common/res/values-lo-rLA/strings.xml21
-rw-r--r--common/res/values-lt/strings.xml21
-rw-r--r--common/res/values-lv/strings.xml21
-rw-r--r--common/res/values-mk-rMK/strings.xml21
-rw-r--r--common/res/values-ml-rIN/strings.xml21
-rw-r--r--common/res/values-mn-rMN/strings.xml21
-rw-r--r--common/res/values-mr-rIN/strings.xml21
-rw-r--r--common/res/values-ms-rMY/strings.xml21
-rw-r--r--common/res/values-my-rMM/strings.xml21
-rw-r--r--common/res/values-nb/strings.xml21
-rw-r--r--common/res/values-ne-rNP/strings.xml21
-rw-r--r--common/res/values-nl/strings.xml21
-rw-r--r--common/res/values-pl/strings.xml21
-rw-r--r--common/res/values-pt-rPT/strings.xml21
-rw-r--r--common/res/values-pt/strings.xml21
-rw-r--r--common/res/values-ro/strings.xml21
-rw-r--r--common/res/values-ru/strings.xml21
-rw-r--r--common/res/values-si-rLK/strings.xml21
-rw-r--r--common/res/values-sk/strings.xml21
-rw-r--r--common/res/values-sl/strings.xml21
-rw-r--r--common/res/values-sr/strings.xml21
-rw-r--r--common/res/values-sv/strings.xml21
-rw-r--r--common/res/values-sw/strings.xml21
-rw-r--r--common/res/values-ta-rIN/strings.xml21
-rw-r--r--common/res/values-te-rIN/strings.xml21
-rw-r--r--common/res/values-th/strings.xml21
-rw-r--r--common/res/values-tl/strings.xml21
-rw-r--r--common/res/values-tr/strings.xml21
-rw-r--r--common/res/values-uk/strings.xml21
-rw-r--r--common/res/values-ur-rPK/strings.xml21
-rw-r--r--common/res/values-uz-rUZ/strings.xml21
-rw-r--r--common/res/values-vi/strings.xml21
-rw-r--r--common/res/values-zh-rCN/strings.xml21
-rw-r--r--common/res/values-zh-rHK/strings.xml21
-rw-r--r--common/res/values-zh-rTW/strings.xml21
-rw-r--r--common/res/values-zu/strings.xml21
-rw-r--r--common/res/values/attrs.xml25
-rw-r--r--common/res/values/colors.xml1
-rw-r--r--common/res/values/dimens.xml7
-rw-r--r--common/res/values/strings.xml3
-rw-r--r--common/res/values/styles.xml37
-rw-r--r--common/res/values/themes.xml16
-rw-r--r--common/res_leanback/animator/lb_onboarding_description_enter.xml31
-rw-r--r--common/res_leanback/animator/lb_onboarding_logo_enter.xml25
-rw-r--r--common/res_leanback/animator/lb_onboarding_logo_exit.xml25
-rw-r--r--common/res_leanback/animator/lb_onboarding_page_indicator_enter.xml25
-rw-r--r--common/res_leanback/animator/lb_onboarding_page_indicator_fade_in.xml25
-rw-r--r--common/res_leanback/animator/lb_onboarding_page_indicator_fade_out.xml25
-rw-r--r--common/res_leanback/animator/lb_onboarding_start_button_fade_in.xml31
-rw-r--r--common/res_leanback/animator/lb_onboarding_start_button_fade_out.xml31
-rw-r--r--common/res_leanback/animator/lb_onboarding_title_enter.xml31
-rw-r--r--common/res_leanback/animator/lb_page_indicator_dot_hide.xml37
-rw-r--r--common/res_leanback/animator/lb_page_indicator_dot_show.xml37
-rw-r--r--common/res_leanback/drawable-xhdpi/lb_ic_nav_arrow.pngbin0 -> 354 bytes
-rw-r--r--common/res_leanback/drawable/lb_onboarding_start_button_background.xml24
-rw-r--r--common/res_leanback/layout/lb_onboarding_fragment.xml120
-rw-r--r--common/res_leanback/values-af/strings.xml22
-rw-r--r--common/res_leanback/values-am/strings.xml22
-rw-r--r--common/res_leanback/values-ar/strings.xml22
-rw-r--r--common/res_leanback/values-az-rAZ/strings.xml22
-rw-r--r--common/res_leanback/values-bg/strings.xml22
-rw-r--r--common/res_leanback/values-bn-rBD/strings.xml22
-rw-r--r--common/res_leanback/values-ca/strings.xml22
-rw-r--r--common/res_leanback/values-cs/strings.xml22
-rw-r--r--common/res_leanback/values-da/strings.xml22
-rw-r--r--common/res_leanback/values-de/strings.xml22
-rw-r--r--common/res_leanback/values-el/strings.xml22
-rw-r--r--common/res_leanback/values-en-rAU/strings.xml22
-rw-r--r--common/res_leanback/values-en-rGB/strings.xml22
-rw-r--r--common/res_leanback/values-en-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-es-rUS/strings.xml22
-rw-r--r--common/res_leanback/values-es/strings.xml22
-rw-r--r--common/res_leanback/values-et-rEE/strings.xml22
-rw-r--r--common/res_leanback/values-eu-rES/strings.xml22
-rw-r--r--common/res_leanback/values-fa/strings.xml22
-rw-r--r--common/res_leanback/values-fi/strings.xml22
-rw-r--r--common/res_leanback/values-fr-rCA/strings.xml22
-rw-r--r--common/res_leanback/values-fr/strings.xml22
-rw-r--r--common/res_leanback/values-gl-rES/strings.xml22
-rw-r--r--common/res_leanback/values-hi/strings.xml22
-rw-r--r--common/res_leanback/values-hr/strings.xml22
-rw-r--r--common/res_leanback/values-hu/strings.xml22
-rw-r--r--common/res_leanback/values-hy-rAM/strings.xml22
-rw-r--r--common/res_leanback/values-in/strings.xml22
-rw-r--r--common/res_leanback/values-is-rIS/strings.xml22
-rw-r--r--common/res_leanback/values-it/strings.xml22
-rw-r--r--common/res_leanback/values-iw/strings.xml22
-rw-r--r--common/res_leanback/values-ja/strings.xml22
-rw-r--r--common/res_leanback/values-ka-rGE/strings.xml22
-rw-r--r--common/res_leanback/values-kk-rKZ/strings.xml22
-rw-r--r--common/res_leanback/values-km-rKH/strings.xml22
-rw-r--r--common/res_leanback/values-kn-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-ko/strings.xml22
-rw-r--r--common/res_leanback/values-ky-rKG/strings.xml22
-rw-r--r--common/res_leanback/values-lo-rLA/strings.xml22
-rw-r--r--common/res_leanback/values-lt/strings.xml22
-rw-r--r--common/res_leanback/values-lv/strings.xml22
-rw-r--r--common/res_leanback/values-mk-rMK/strings.xml22
-rw-r--r--common/res_leanback/values-ml-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-mn-rMN/strings.xml22
-rw-r--r--common/res_leanback/values-mr-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-ms-rMY/strings.xml22
-rw-r--r--common/res_leanback/values-my-rMM/strings.xml22
-rw-r--r--common/res_leanback/values-nb/strings.xml22
-rw-r--r--common/res_leanback/values-ne-rNP/strings.xml22
-rw-r--r--common/res_leanback/values-nl/strings.xml22
-rw-r--r--common/res_leanback/values-pl/strings.xml22
-rw-r--r--common/res_leanback/values-pt-rPT/strings.xml22
-rw-r--r--common/res_leanback/values-pt/strings.xml22
-rw-r--r--common/res_leanback/values-ro/strings.xml22
-rw-r--r--common/res_leanback/values-ru/strings.xml22
-rw-r--r--common/res_leanback/values-si-rLK/strings.xml22
-rw-r--r--common/res_leanback/values-sk/strings.xml22
-rw-r--r--common/res_leanback/values-sl/strings.xml22
-rw-r--r--common/res_leanback/values-sr/strings.xml22
-rw-r--r--common/res_leanback/values-sv/strings.xml22
-rw-r--r--common/res_leanback/values-sw/strings.xml22
-rw-r--r--common/res_leanback/values-ta-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-te-rIN/strings.xml22
-rw-r--r--common/res_leanback/values-th/strings.xml22
-rw-r--r--common/res_leanback/values-tl/strings.xml22
-rw-r--r--common/res_leanback/values-tr/strings.xml22
-rw-r--r--common/res_leanback/values-uk/strings.xml22
-rw-r--r--common/res_leanback/values-ur-rPK/strings.xml22
-rw-r--r--common/res_leanback/values-uz-rUZ/strings.xml22
-rw-r--r--common/res_leanback/values-vi/strings.xml22
-rw-r--r--common/res_leanback/values-zh-rCN/strings.xml22
-rw-r--r--common/res_leanback/values-zh-rHK/strings.xml22
-rw-r--r--common/res_leanback/values-zh-rTW/strings.xml22
-rw-r--r--common/res_leanback/values-zu/strings.xml22
-rw-r--r--common/res_leanback/values/colors.xml23
-rw-r--r--common/res_leanback/values/dimens.xml39
-rw-r--r--common/res_leanback/values/strings.xml25
-rw-r--r--common/src/com/android/tv/common/AutoCloseableUtils.java36
-rw-r--r--common/src/com/android/tv/common/CollectionUtils.java78
-rw-r--r--common/src/com/android/tv/common/MemoryManageable.java29
-rw-r--r--common/src/com/android/tv/common/SharedPreferencesUtils.java64
-rw-r--r--common/src/com/android/tv/common/TvCommonConstants.java5
-rw-r--r--common/src/com/android/tv/common/TvContentRatingCache.java145
-rw-r--r--common/src/com/android/tv/common/annotation/UsedByReflection.java29
-rw-r--r--common/src/com/android/tv/common/dvr/DvrSessionClient.java149
-rw-r--r--common/src/com/android/tv/common/dvr/DvrTvView.java67
-rw-r--r--common/src/com/android/tv/common/feature/CommonFeatures.java40
-rw-r--r--common/src/com/android/tv/common/feature/EngOnlyFeature.java40
-rw-r--r--common/src/com/android/tv/common/feature/PackageVersionFeature.java55
-rw-r--r--common/src/com/android/tv/common/feature/Sdk.java42
-rw-r--r--common/src/com/android/tv/common/feature/SharedPreferencesFeature.java9
-rw-r--r--common/src/com/android/tv/common/feature/TestableFeature.java21
-rw-r--r--common/src/com/android/tv/common/recording/PlaybackTvView.java191
-rw-r--r--common/src/com/android/tv/common/recording/RecordingCapability.java181
-rw-r--r--common/src/com/android/tv/common/recording/RecordingTvInputService.java (renamed from common/src/com/android/tv/common/dvr/DvrTvInputService.java)149
-rw-r--r--common/src/com/android/tv/common/recording/RecordingUtils.java (renamed from common/src/com/android/tv/common/dvr/DvrUtils.java)27
-rw-r--r--common/src/com/android/tv/common/recording/TvRecording.java384
-rw-r--r--common/src/com/android/tv/common/ui/setup/OnActionClickListener.java3
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupActionHelper.java45
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupActivity.java168
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupFragment.java150
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java49
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java17
-rw-r--r--common/src/com/android/tv/common/ui/setup/SetupStep.java75
-rw-r--r--common/src/com/android/tv/common/ui/setup/SteppedSetupActivity.java148
-rw-r--r--common/src/com/android/tv/common/ui/setup/animation/CustomTransition.java54
-rw-r--r--common/src/com/android/tv/common/ui/setup/animation/CustomTransitionProvider.java43
-rw-r--r--common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java126
-rw-r--r--common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java71
-rw-r--r--common/src/com/android/tv/common/ui/setup/leanback/OnboardingFragment.java531
-rw-r--r--common/src/com/android/tv/common/ui/setup/leanback/PagingIndicator.java377
210 files changed, 6664 insertions, 841 deletions
diff --git a/common/Android.mk b/common/Android.mk
index 2f9c32e2..878cbb8b 100644
--- a/common/Android.mk
+++ b/common/Android.mk
@@ -1,8 +1,14 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_BUILDCONFIG_CLASS := src/com/android/tv/common/BuildConfig.java
+BC_OUT_DIR := $(LOCAL_PATH)
+BC_APPLICATION_ID := "com.android.tv.common"
+include $(LOCAL_PATH)/buildconfig.mk
+
# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(LOCAL_BUILDCONFIG_CLASS)
LOCAL_MODULE := tv-common
LOCAL_MODULE_TAGS := optional
@@ -11,7 +17,8 @@ LOCAL_SDK_VERSION := system_current
LOCAL_RESOURCE_DIR := \
$(TOP)/prebuilts/sdk/current/support/v7/recyclerview/res \
$(TOP)/prebuilts/sdk/current/support/v17/leanback/res \
- $(LOCAL_PATH)/res
+ $(LOCAL_PATH)/res \
+ $(LOCAL_PATH)/res_leanback \
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-annotations \
diff --git a/common/buildconfig.mk b/common/buildconfig.mk
new file mode 100644
index 00000000..93fcbcb0
--- /dev/null
+++ b/common/buildconfig.mk
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+# Emulate gradles BuildConfig.java
+
+ifeq "$(TARGET_BUILD_VARIANT)" "eng"
+ BC_DEBUG_STATUS := "true"
+else ifeq "$(TARGET_BUILD_VARIANT)" "userdebug"
+ BC_DEBUG_STATUS := "true"
+else
+ BC_DEBUG_STATUS := "false"
+endif
+
+ifeq "$(TARGET_BUILD_VARIANT)" "eng"
+ BC_ENG_STATUS := "true"
+else
+ BC_ENG_STATUS := "false"
+endif
+
+$(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS): FORCE
+ echo "/**" > $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo "* Automatically generated file. DO NOT MODIFY" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo "*/" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo "package "$(BC_APPLICATION_ID)";" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo "public final class BuildConfig {" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo " public static final boolean DEBUG = "$(BC_DEBUG_STATUS)";" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo " public static final boolean ENG = "$(BC_ENG_STATUS)";" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo " private BuildConfig() {}" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+ echo "}" >> $(BC_OUT_DIR)/$(LOCAL_BUILDCONFIG_CLASS)
+FORCE:
diff --git a/common/res/drawable/setup_selector_background.xml b/common/res/drawable/setup_selector_background.xml
index 4f3ebfde..7351270b 100644
--- a/common/res/drawable/setup_selector_background.xml
+++ b/common/res/drawable/setup_selector_background.xml
@@ -14,11 +14,14 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <shape>
- <solid android:color="#26FFFFFF"/>
- <corners android:radius="2dp" />
- </shape>
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <!-- Note that android:start and android:end is not supported in L platform. -->
+ <item android:id="@android:id/mask" android:left="24dp" android:right="24dp">
+ <shape>
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="2dp" />
+ </shape>
</item>
-</selector>
+</ripple>
diff --git a/common/res/layout/activity_stepped_setup.xml b/common/res/layout/activity_setup.xml
index f742c539..f742c539 100644
--- a/common/res/layout/activity_stepped_setup.xml
+++ b/common/res/layout/activity_setup.xml
diff --git a/common/res/layout/fragment_setup_multi_pane.xml b/common/res/layout/fragment_setup_multi_pane.xml
index 32bf3188..84798c02 100644
--- a/common/res/layout/fragment_setup_multi_pane.xml
+++ b/common/res/layout/fragment_setup_multi_pane.xml
@@ -23,6 +23,12 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
+ <View
+ android:id="@+id/setup_common_guidance_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/setup_common_guidance_background_margin_start"
+ android:background="?attr/setupCommonGuidanceBackground" />
<!-- Guided step fragment container must be at the left of the done button at least by 1 pixel
for the focus navigation. If they overlap, the focus doesn't move from the button to the
fragment container.-->
@@ -33,13 +39,14 @@
android:layout_marginEnd="1dp"
android:clipChildren="false"
android:clipToPadding="false" />
+ // TODO: Use button action list in GuidedStepFragment
<FrameLayout
android:id="@+id/done_button_container"
android:layout_width="@dimen/setup_done_button_container_width"
android:layout_height="match_parent"
android:layout_gravity="end"
- android:background="@color/common_setup_done_container_background"
- android:transitionGroup="false"
+ style="?attr/doneButtonContainerStyle"
+ android:transitionGroup="true"
android:transitionName="buttonDoneTransition">
<TextView
android:id="@+id/button_done"
diff --git a/common/res/values-af/strings.xml b/common/res/values-af/strings.xml
new file mode 100644
index 00000000..11b3990a
--- /dev/null
+++ b/common/res/values-af/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Klaar"</string>
+</resources>
diff --git a/common/res/values-am/strings.xml b/common/res/values-am/strings.xml
new file mode 100644
index 00000000..b72ab7d0
--- /dev/null
+++ b/common/res/values-am/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"ተከናውኗል"</string>
+</resources>
diff --git a/common/res/values-ar/strings.xml b/common/res/values-ar/strings.xml
new file mode 100644
index 00000000..d234a33b
--- /dev/null
+++ b/common/res/values-ar/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"تم"</string>
+</resources>
diff --git a/common/res/values-az-rAZ/strings.xml b/common/res/values-az-rAZ/strings.xml
new file mode 100644
index 00000000..4770dd1e
--- /dev/null
+++ b/common/res/values-az-rAZ/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Hazırdır"</string>
+</resources>
diff --git a/common/res/values-bg/strings.xml b/common/res/values-bg/strings.xml
new file mode 100644
index 00000000..a8d42c3a
--- /dev/null
+++ b/common/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+</resources>
diff --git a/common/res/values-bn-rBD/strings.xml b/common/res/values-bn-rBD/strings.xml
new file mode 100644
index 00000000..ef20cd3f
--- /dev/null
+++ b/common/res/values-bn-rBD/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"সম্পন্ন"</string>
+</resources>
diff --git a/common/res/values-ca/strings.xml b/common/res/values-ca/strings.xml
new file mode 100644
index 00000000..790c58aa
--- /dev/null
+++ b/common/res/values-ca/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Fet"</string>
+</resources>
diff --git a/common/res/values-cs/strings.xml b/common/res/values-cs/strings.xml
new file mode 100644
index 00000000..6bc7a34d
--- /dev/null
+++ b/common/res/values-cs/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Hotovo"</string>
+</resources>
diff --git a/common/res/values-da/strings.xml b/common/res/values-da/strings.xml
new file mode 100644
index 00000000..a3ff65d6
--- /dev/null
+++ b/common/res/values-da/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Udført"</string>
+</resources>
diff --git a/common/res/values-de/strings.xml b/common/res/values-de/strings.xml
new file mode 100644
index 00000000..08cecfa4
--- /dev/null
+++ b/common/res/values-de/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Fertig"</string>
+</resources>
diff --git a/common/res/values-el/strings.xml b/common/res/values-el/strings.xml
new file mode 100644
index 00000000..8d178e29
--- /dev/null
+++ b/common/res/values-el/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Τέλος"</string>
+</resources>
diff --git a/common/res/values-en-rAU/strings.xml b/common/res/values-en-rAU/strings.xml
new file mode 100644
index 00000000..5b24567c
--- /dev/null
+++ b/common/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+</resources>
diff --git a/common/res/values-en-rGB/strings.xml b/common/res/values-en-rGB/strings.xml
new file mode 100644
index 00000000..5b24567c
--- /dev/null
+++ b/common/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+</resources>
diff --git a/common/res/values-en-rIN/strings.xml b/common/res/values-en-rIN/strings.xml
new file mode 100644
index 00000000..5b24567c
--- /dev/null
+++ b/common/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+</resources>
diff --git a/common/res/values-es-rUS/strings.xml b/common/res/values-es-rUS/strings.xml
new file mode 100644
index 00000000..76f39ab4
--- /dev/null
+++ b/common/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Listo"</string>
+</resources>
diff --git a/common/res/values-es/strings.xml b/common/res/values-es/strings.xml
new file mode 100644
index 00000000..76f39ab4
--- /dev/null
+++ b/common/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Listo"</string>
+</resources>
diff --git a/common/res/values-et-rEE/strings.xml b/common/res/values-et-rEE/strings.xml
new file mode 100644
index 00000000..58a71664
--- /dev/null
+++ b/common/res/values-et-rEE/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Valmis"</string>
+</resources>
diff --git a/common/res/values-eu-rES/strings.xml b/common/res/values-eu-rES/strings.xml
new file mode 100644
index 00000000..bdc86896
--- /dev/null
+++ b/common/res/values-eu-rES/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Eginda"</string>
+</resources>
diff --git a/common/res/values-fa/strings.xml b/common/res/values-fa/strings.xml
new file mode 100644
index 00000000..919c37fe
--- /dev/null
+++ b/common/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"تمام"</string>
+</resources>
diff --git a/common/res/values-fi/strings.xml b/common/res/values-fi/strings.xml
new file mode 100644
index 00000000..58a71664
--- /dev/null
+++ b/common/res/values-fi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Valmis"</string>
+</resources>
diff --git a/common/res/values-fr-rCA/strings.xml b/common/res/values-fr-rCA/strings.xml
new file mode 100644
index 00000000..a5334fed
--- /dev/null
+++ b/common/res/values-fr-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Terminé"</string>
+</resources>
diff --git a/common/res/values-fr/strings.xml b/common/res/values-fr/strings.xml
new file mode 100644
index 00000000..a018b053
--- /dev/null
+++ b/common/res/values-fr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"OK"</string>
+</resources>
diff --git a/common/res/values-gl-rES/strings.xml b/common/res/values-gl-rES/strings.xml
new file mode 100644
index 00000000..04167ec0
--- /dev/null
+++ b/common/res/values-gl-rES/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Feito"</string>
+</resources>
diff --git a/common/res/values-hi/strings.xml b/common/res/values-hi/strings.xml
new file mode 100644
index 00000000..93ddf14d
--- /dev/null
+++ b/common/res/values-hi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"हो गया"</string>
+</resources>
diff --git a/common/res/values-hr/strings.xml b/common/res/values-hr/strings.xml
new file mode 100644
index 00000000..e359fa47
--- /dev/null
+++ b/common/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Gotovo"</string>
+</resources>
diff --git a/common/res/values-hu/strings.xml b/common/res/values-hu/strings.xml
new file mode 100644
index 00000000..c7edacc5
--- /dev/null
+++ b/common/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Kész"</string>
+</resources>
diff --git a/common/res/values-hy-rAM/strings.xml b/common/res/values-hy-rAM/strings.xml
new file mode 100644
index 00000000..2832c576
--- /dev/null
+++ b/common/res/values-hy-rAM/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Պատրաստ է"</string>
+</resources>
diff --git a/common/res/values-in/strings.xml b/common/res/values-in/strings.xml
new file mode 100644
index 00000000..315e2eac
--- /dev/null
+++ b/common/res/values-in/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Selesai"</string>
+</resources>
diff --git a/common/res/values-is-rIS/strings.xml b/common/res/values-is-rIS/strings.xml
new file mode 100644
index 00000000..a2d8da79
--- /dev/null
+++ b/common/res/values-is-rIS/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Lokið"</string>
+</resources>
diff --git a/common/res/values-it/strings.xml b/common/res/values-it/strings.xml
new file mode 100644
index 00000000..ba1ecc42
--- /dev/null
+++ b/common/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Fine"</string>
+</resources>
diff --git a/common/res/values-iw/strings.xml b/common/res/values-iw/strings.xml
new file mode 100644
index 00000000..106e5453
--- /dev/null
+++ b/common/res/values-iw/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"סיום"</string>
+</resources>
diff --git a/common/res/values-ja/strings.xml b/common/res/values-ja/strings.xml
new file mode 100644
index 00000000..9cf0ba31
--- /dev/null
+++ b/common/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"完了"</string>
+</resources>
diff --git a/common/res/values-ka-rGE/strings.xml b/common/res/values-ka-rGE/strings.xml
new file mode 100644
index 00000000..d7297b9d
--- /dev/null
+++ b/common/res/values-ka-rGE/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"მზადაა"</string>
+</resources>
diff --git a/common/res/values-kk-rKZ/strings.xml b/common/res/values-kk-rKZ/strings.xml
new file mode 100644
index 00000000..9994dc20
--- /dev/null
+++ b/common/res/values-kk-rKZ/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Орындалды"</string>
+</resources>
diff --git a/common/res/values-km-rKH/strings.xml b/common/res/values-km-rKH/strings.xml
new file mode 100644
index 00000000..f12663fb
--- /dev/null
+++ b/common/res/values-km-rKH/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"រួចរាល់"</string>
+</resources>
diff --git a/common/res/values-kn-rIN/strings.xml b/common/res/values-kn-rIN/strings.xml
new file mode 100644
index 00000000..589ff1be
--- /dev/null
+++ b/common/res/values-kn-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"ಮುಗಿದಿದೆ"</string>
+</resources>
diff --git a/common/res/values-ko/strings.xml b/common/res/values-ko/strings.xml
new file mode 100644
index 00000000..e2e47fa4
--- /dev/null
+++ b/common/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"완료"</string>
+</resources>
diff --git a/common/res/values-ky-rKG/strings.xml b/common/res/values-ky-rKG/strings.xml
new file mode 100644
index 00000000..3397fc32
--- /dev/null
+++ b/common/res/values-ky-rKG/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Бүттү"</string>
+</resources>
diff --git a/common/res/values-lo-rLA/strings.xml b/common/res/values-lo-rLA/strings.xml
new file mode 100644
index 00000000..88653b54
--- /dev/null
+++ b/common/res/values-lo-rLA/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"ສຳເລັດແລ້ວ"</string>
+</resources>
diff --git a/common/res/values-lt/strings.xml b/common/res/values-lt/strings.xml
new file mode 100644
index 00000000..6f51b3fc
--- /dev/null
+++ b/common/res/values-lt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Atlikta"</string>
+</resources>
diff --git a/common/res/values-lv/strings.xml b/common/res/values-lv/strings.xml
new file mode 100644
index 00000000..8660efbd
--- /dev/null
+++ b/common/res/values-lv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Gatavs"</string>
+</resources>
diff --git a/common/res/values-mk-rMK/strings.xml b/common/res/values-mk-rMK/strings.xml
new file mode 100644
index 00000000..a8d42c3a
--- /dev/null
+++ b/common/res/values-mk-rMK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+</resources>
diff --git a/common/res/values-ml-rIN/strings.xml b/common/res/values-ml-rIN/strings.xml
new file mode 100644
index 00000000..81e9a8c6
--- /dev/null
+++ b/common/res/values-ml-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"പൂർത്തിയായി"</string>
+</resources>
diff --git a/common/res/values-mn-rMN/strings.xml b/common/res/values-mn-rMN/strings.xml
new file mode 100644
index 00000000..ac4435f3
--- /dev/null
+++ b/common/res/values-mn-rMN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Дууссан"</string>
+</resources>
diff --git a/common/res/values-mr-rIN/strings.xml b/common/res/values-mr-rIN/strings.xml
new file mode 100644
index 00000000..82edcb03
--- /dev/null
+++ b/common/res/values-mr-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"पूर्ण झाले"</string>
+</resources>
diff --git a/common/res/values-ms-rMY/strings.xml b/common/res/values-ms-rMY/strings.xml
new file mode 100644
index 00000000..315e2eac
--- /dev/null
+++ b/common/res/values-ms-rMY/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Selesai"</string>
+</resources>
diff --git a/common/res/values-my-rMM/strings.xml b/common/res/values-my-rMM/strings.xml
new file mode 100644
index 00000000..a7faa7d9
--- /dev/null
+++ b/common/res/values-my-rMM/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"ပြီးပါပြီ"</string>
+</resources>
diff --git a/common/res/values-nb/strings.xml b/common/res/values-nb/strings.xml
new file mode 100644
index 00000000..3ff3ede1
--- /dev/null
+++ b/common/res/values-nb/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Ferdig"</string>
+</resources>
diff --git a/common/res/values-ne-rNP/strings.xml b/common/res/values-ne-rNP/strings.xml
new file mode 100644
index 00000000..4a08d5ef
--- /dev/null
+++ b/common/res/values-ne-rNP/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"सम्पन्न भयो"</string>
+</resources>
diff --git a/common/res/values-nl/strings.xml b/common/res/values-nl/strings.xml
new file mode 100644
index 00000000..8756e624
--- /dev/null
+++ b/common/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Gereed"</string>
+</resources>
diff --git a/common/res/values-pl/strings.xml b/common/res/values-pl/strings.xml
new file mode 100644
index 00000000..97beca37
--- /dev/null
+++ b/common/res/values-pl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Gotowe"</string>
+</resources>
diff --git a/common/res/values-pt-rPT/strings.xml b/common/res/values-pt-rPT/strings.xml
new file mode 100644
index 00000000..a967a341
--- /dev/null
+++ b/common/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Concluído"</string>
+</resources>
diff --git a/common/res/values-pt/strings.xml b/common/res/values-pt/strings.xml
new file mode 100644
index 00000000..a967a341
--- /dev/null
+++ b/common/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Concluído"</string>
+</resources>
diff --git a/common/res/values-ro/strings.xml b/common/res/values-ro/strings.xml
new file mode 100644
index 00000000..2cbda306
--- /dev/null
+++ b/common/res/values-ro/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Terminat"</string>
+</resources>
diff --git a/common/res/values-ru/strings.xml b/common/res/values-ru/strings.xml
new file mode 100644
index 00000000..a8d42c3a
--- /dev/null
+++ b/common/res/values-ru/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+</resources>
diff --git a/common/res/values-si-rLK/strings.xml b/common/res/values-si-rLK/strings.xml
new file mode 100644
index 00000000..6293bbec
--- /dev/null
+++ b/common/res/values-si-rLK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"නිමයි"</string>
+</resources>
diff --git a/common/res/values-sk/strings.xml b/common/res/values-sk/strings.xml
new file mode 100644
index 00000000..6bc7a34d
--- /dev/null
+++ b/common/res/values-sk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Hotovo"</string>
+</resources>
diff --git a/common/res/values-sl/strings.xml b/common/res/values-sl/strings.xml
new file mode 100644
index 00000000..29c414ac
--- /dev/null
+++ b/common/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Končano"</string>
+</resources>
diff --git a/common/res/values-sr/strings.xml b/common/res/values-sr/strings.xml
new file mode 100644
index 00000000..a8d42c3a
--- /dev/null
+++ b/common/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+</resources>
diff --git a/common/res/values-sv/strings.xml b/common/res/values-sv/strings.xml
new file mode 100644
index 00000000..ded93590
--- /dev/null
+++ b/common/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Klar"</string>
+</resources>
diff --git a/common/res/values-sw/strings.xml b/common/res/values-sw/strings.xml
new file mode 100644
index 00000000..1cce7469
--- /dev/null
+++ b/common/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Nimemaliza"</string>
+</resources>
diff --git a/common/res/values-ta-rIN/strings.xml b/common/res/values-ta-rIN/strings.xml
new file mode 100644
index 00000000..df4ce9ab
--- /dev/null
+++ b/common/res/values-ta-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"முடிந்தது"</string>
+</resources>
diff --git a/common/res/values-te-rIN/strings.xml b/common/res/values-te-rIN/strings.xml
new file mode 100644
index 00000000..527f9e02
--- /dev/null
+++ b/common/res/values-te-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"పూర్తయింది"</string>
+</resources>
diff --git a/common/res/values-th/strings.xml b/common/res/values-th/strings.xml
new file mode 100644
index 00000000..ca4158ef
--- /dev/null
+++ b/common/res/values-th/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"เสร็จสิ้น"</string>
+</resources>
diff --git a/common/res/values-tl/strings.xml b/common/res/values-tl/strings.xml
new file mode 100644
index 00000000..4b53b66e
--- /dev/null
+++ b/common/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Tapos Na"</string>
+</resources>
diff --git a/common/res/values-tr/strings.xml b/common/res/values-tr/strings.xml
new file mode 100644
index 00000000..34e0cb58
--- /dev/null
+++ b/common/res/values-tr/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Bitti"</string>
+</resources>
diff --git a/common/res/values-uk/strings.xml b/common/res/values-uk/strings.xml
new file mode 100644
index 00000000..a8d42c3a
--- /dev/null
+++ b/common/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+</resources>
diff --git a/common/res/values-ur-rPK/strings.xml b/common/res/values-ur-rPK/strings.xml
new file mode 100644
index 00000000..87b1cec4
--- /dev/null
+++ b/common/res/values-ur-rPK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"ہو گیا"</string>
+</resources>
diff --git a/common/res/values-uz-rUZ/strings.xml b/common/res/values-uz-rUZ/strings.xml
new file mode 100644
index 00000000..67468cec
--- /dev/null
+++ b/common/res/values-uz-rUZ/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Tayyor"</string>
+</resources>
diff --git a/common/res/values-vi/strings.xml b/common/res/values-vi/strings.xml
new file mode 100644
index 00000000..756fb991
--- /dev/null
+++ b/common/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Xong"</string>
+</resources>
diff --git a/common/res/values-zh-rCN/strings.xml b/common/res/values-zh-rCN/strings.xml
new file mode 100644
index 00000000..b8bd7736
--- /dev/null
+++ b/common/res/values-zh-rCN/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+</resources>
diff --git a/common/res/values-zh-rHK/strings.xml b/common/res/values-zh-rHK/strings.xml
new file mode 100644
index 00000000..b8bd7736
--- /dev/null
+++ b/common/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+</resources>
diff --git a/common/res/values-zh-rTW/strings.xml b/common/res/values-zh-rTW/strings.xml
new file mode 100644
index 00000000..b8bd7736
--- /dev/null
+++ b/common/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+</resources>
diff --git a/common/res/values-zu/strings.xml b/common/res/values-zu/strings.xml
new file mode 100644
index 00000000..91b5042c
--- /dev/null
+++ b/common/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="action_text_done" msgid="298287050387266501">"Kwenziwe"</string>
+</resources>
diff --git a/common/res/values/attrs.xml b/common/res/values/attrs.xml
new file mode 100644
index 00000000..fb23f358
--- /dev/null
+++ b/common/res/values/attrs.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<resources>
+ <declare-styleable name="SetupGuidedStep">
+ <!-- Defines the background color of setup guidance background. -->
+ <attr name="setupCommonGuidanceBackground" format="reference" />
+ <!-- Defines the style of done button container. -->
+ <attr name="doneButtonContainerStyle" format="reference" />
+ </declare-styleable>
+</resources> \ No newline at end of file
diff --git a/common/res/values/colors.xml b/common/res/values/colors.xml
index 6e44b188..b6efb8ca 100644
--- a/common/res/values/colors.xml
+++ b/common/res/values/colors.xml
@@ -21,4 +21,5 @@
<color name="common_setup_action_background">#0374BF</color>
<color name="common_setup_done_container_background">#04549D</color>
<color name="common_setup_button_done_selected">#26FFFFFF</color>
+ <color name="common_setup_input_description">#EEEEEE</color>
</resources>
diff --git a/common/res/values/dimens.xml b/common/res/values/dimens.xml
index aded2876..4d8286cd 100644
--- a/common/res/values/dimens.xml
+++ b/common/res/values/dimens.xml
@@ -31,7 +31,12 @@
<dimen name="setup_guidedactions_item_container_padding_end">40dp</dimen>
<dimen name="setup_guidedactions_vertical_padding">12dp</dimen>
<dimen name="setup_guidedactions_vertical_spacing">5dp</dimen>
+ <item name="setup_guidedactions_width_weight" format="float" type="string">1</item>
+ <dimen name="setup_guidedactions_item_delimiter_padding">10dp</dimen>
<!-- Transition -->
- <dimen name="setup_fragment_transition_distance">80dp</dimen>
+ <dimen name="setup_fragment_transition_long_distance">80dp</dimen>
+ <dimen name="setup_fragment_transition_short_distance">48dp</dimen>
+ <!-- This values should be less then or equal to -1 * setup_fragment_transition_long_distance. -->
+ <dimen name="setup_common_guidance_background_margin_start">-100dp</dimen>
</resources>
diff --git a/common/res/values/strings.xml b/common/res/values/strings.xml
index 25782443..f337af42 100644
--- a/common/res/values/strings.xml
+++ b/common/res/values/strings.xml
@@ -16,6 +16,5 @@
-->
<resources>
- <!-- TODO: Change translatable to true once implemented. -->
- <string name="action_text_done" translatable="false">Done</string>
+ <string name="action_text_done">Done</string>
</resources>
diff --git a/common/res/values/styles.xml b/common/res/values/styles.xml
index 7d9575f0..3c3c71c9 100644
--- a/common/res/values/styles.xml
+++ b/common/res/values/styles.xml
@@ -23,49 +23,40 @@
<style name="Widget.Setup.GuidanceTitleStyle" parent="Widget.Leanback.GuidanceTitleStyle">
<item name="android:layout_alignParentStart">true</item>
+ <item name="android:layout_below">@id/guidance_breadcrumb</item>
<item name="android:layout_centerVertical">false</item>
- <item name="android:layout_marginTop">181dp</item>
+ <item name="android:layout_marginTop">4dp</item>
<item name="android:fontFamily">sans-serif-light</item>
<item name="android:gravity">start</item>
<item name="android:lineSpacingExtra">0sp</item>
<item name="android:lineSpacingMultiplier">1.13778</item>
+ <item name="android:textAlignment">viewStart</item>
<item name="android:textColor">#EEEEEE</item>
<item name="android:textSize">34sp</item>
</style>
<style name="Widget.Setup.GuidanceDescriptionStyle" parent="Widget.Leanback.GuidanceDescriptionStyle">
+ <item name="android:layout_alignParentStart">true</item>
<item name="android:layout_marginTop">4dp</item>
<item name="android:fontFamily">sans-serif-light</item>
<item name="android:gravity">start</item>
<item name="android:lineSpacingExtra">0sp</item>
<item name="android:lineSpacingMultiplier">1.465</item>
<item name="android:maxLines">10</item>
+ <item name="android:textAlignment">viewStart</item>
<item name="android:textColor">#CCEEEEEE</item>
</style>
<style name="Widget.Setup.GuidanceBreadcrumbStyle" parent="Widget.Leanback.GuidanceBreadcrumbStyle">
- <item name="android:layout_marginBottom">4dp</item>
+ <item name="android:layout_alignParentStart">true</item>
+ <item name="android:layout_above">@null</item>
+ <item name="android:layout_marginTop">156dp</item>
<item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textAlignment">viewStart</item>
<item name="android:textColor">#B3EEEEEE</item>
<item name="android:textSize">16sp</item>
</style>
- <style name="Widget.Setup.GuidedActionsContainerStyle" parent="Widget.Leanback.GuidedActionsContainerStyle">
- <item name="android:layout_width">match_parent</item>
- <item name="android:background">@color/common_setup_action_background</item>
- <item name="android:elevation">0dp</item>
- <item name="android:transitionName">guidedActionsBackgroundTransition</item>
- </style>
-
- <style name="Widget.Setup.GuidedActionsSelectorStyle" parent="Widget.Leanback.GuidedActionsSelectorStyle">
- <item name="android:layout_centerVertical">false</item>
- <item name="android:layout_marginStart">@dimen/setup_guidedactions_selector_margin_start</item>
- <item name="android:layout_marginEnd">@dimen/setup_guidedactions_selector_margin_end</item>
- <item name="android:layout_marginTop">@dimen/setup_guidedactions_selector_margin_top</item>
- <item name="android:background">@drawable/setup_selector_background</item>
- <item name="android:elevation">0dp</item>
- </style>
-
<style name="Widget.Setup.GuidedActionsListStyle" parent="Widget.Leanback.GuidedActionsListStyle">
<item name="android:elevation">0dp</item>
</style>
@@ -83,6 +74,10 @@
<item name="android:visibility">gone</item>
</style>
+ <style name="Widget.Setup.GuidedActionItemIconStyle" parent="Widget.Leanback.GuidedActionItemIconStyle">
+ <item name="android:layout_marginEnd">@dimen/setup_guidedactions_item_delimiter_padding</item>
+ </style>
+
<style name="Widget.Setup.GuidedActionItemTitleStyle" parent="Widget.Leanback.GuidedActionItemTitleStyle">
<item name="android:layout_height">18dp</item>
<item name="android:fontFamily">sans-serif</item>
@@ -94,7 +89,11 @@
<item name="android:layout_height">17dp</item>
<item name="android:alpha">0.5</item>
<item name="android:fontFamily">sans-serif</item>
- <item name="android:textColor">#EEEEEE</item>
+ <item name="android:textColor">@color/common_setup_input_description</item>
<item name="android:textSize">12sp</item>
</style>
+
+ <style name="DoneButtonContainerStyle">
+ <item name="android:background">@color/common_setup_done_container_background</item>
+ </style>
</resources>
diff --git a/common/res/values/themes.xml b/common/res/values/themes.xml
index 6d7ac0a5..598ae9a5 100644
--- a/common/res/values/themes.xml
+++ b/common/res/values/themes.xml
@@ -19,16 +19,22 @@
<style name="Theme.Setup.GuidedStep" parent="Theme.Leanback.GuidedStep">
<item name="android:windowBackground">@color/common_tv_background</item>
<item name="android:windowEnterTransition">@null</item>
+ <item name="guidanceBreadcrumbStyle">@style/Widget.Setup.GuidanceBreadcrumbStyle</item>
<item name="guidanceContainerStyle">@style/Widget.Setup.GuidanceContainerStyle</item>
- <item name="guidanceTitleStyle">@style/Widget.Setup.GuidanceTitleStyle</item>
<item name="guidanceDescriptionStyle">@style/Widget.Setup.GuidanceDescriptionStyle</item>
- <item name="guidanceBreadcrumbStyle">@style/Widget.Setup.GuidanceBreadcrumbStyle</item>
- <item name="guidedActionsContainerStyle">@style/Widget.Setup.GuidedActionsContainerStyle</item>
- <item name="guidedActionsSelectorStyle">@style/Widget.Setup.GuidedActionsSelectorStyle</item>
- <item name="guidedActionsListStyle">@style/Widget.Setup.GuidedActionsListStyle</item>
+ <item name="guidanceTitleStyle">@style/Widget.Setup.GuidanceTitleStyle</item>
+ <item name="guidedActionContentWidthWeight">@string/setup_guidedactions_width_weight</item>
<item name="guidedActionItemContainerStyle">@style/Widget.Setup.GuidedActionItemContainerStyle</item>
<item name="guidedActionItemCheckmarkStyle">@style/Widget.Setup.GuidedActionItemCheckmarkStyle</item>
+ <item name="guidedActionItemIconStyle">@style/Widget.Setup.GuidedActionItemIconStyle</item>
<item name="guidedActionItemTitleStyle">@style/Widget.Setup.GuidedActionItemTitleStyle</item>
<item name="guidedActionItemDescriptionStyle">@style/Widget.Setup.GuidedActionItemDescriptionStyle</item>
+ <item name="guidedActionsBackground">@color/common_setup_action_background</item>
+ <item name="guidedActionsElevation">0dp</item>
+ <item name="guidedActionsListStyle">@style/Widget.Setup.GuidedActionsListStyle</item>
+ <item name="guidedActionsSelectorDrawable">@drawable/setup_selector_background</item>
+ <item name="guidedStepBackground">@android:color/transparent</item>
+ <item name="setupCommonGuidanceBackground">@android:color/transparent</item>
+ <item name="doneButtonContainerStyle">@style/DoneButtonContainerStyle</item>
</style>
</resources>
diff --git a/common/res_leanback/animator/lb_onboarding_description_enter.xml b/common/res_leanback/animator/lb_onboarding_description_enter.xml
new file mode 100644
index 00000000..5f26cdd1
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_description_enter.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="533"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="60dp"
+ android:valueTo="0dp"
+ android:duration="533"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_logo_enter.xml b/common/res_leanback/animator/lb_onboarding_logo_enter.xml
new file mode 100644
index 00000000..76a4609a
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_logo_enter.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="333"
+ android:interpolator="@android:interpolator/linear_out_slow_in" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_logo_exit.xml b/common/res_leanback/animator/lb_onboarding_logo_exit.xml
new file mode 100644
index 00000000..40b618e6
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_logo_exit.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:duration="666"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_page_indicator_enter.xml b/common/res_leanback/animator/lb_onboarding_page_indicator_enter.xml
new file mode 100644
index 00000000..e9fc46ef
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_page_indicator_enter.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="500"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_page_indicator_fade_in.xml b/common/res_leanback/animator/lb_onboarding_page_indicator_fade_in.xml
new file mode 100644
index 00000000..f21fc23b
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_page_indicator_fade_in.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_page_indicator_fade_out.xml b/common/res_leanback/animator/lb_onboarding_page_indicator_fade_out.xml
new file mode 100644
index 00000000..4c69c5d0
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_page_indicator_fade_out.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_start_button_fade_in.xml b/common/res_leanback/animator/lb_onboarding_start_button_fade_in.xml
new file mode 100644
index 00000000..4125622b
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_start_button_fade_in.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="translationX"
+ android:valueFrom="16dp"
+ android:valueTo="0dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_start_button_fade_out.xml b/common/res_leanback/animator/lb_onboarding_start_button_fade_out.xml
new file mode 100644
index 00000000..26590ecd
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_start_button_fade_out.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="translationX"
+ android:valueFrom="0dp"
+ android:valueTo="16dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/animator/lb_onboarding_title_enter.xml b/common/res_leanback/animator/lb_onboarding_title_enter.xml
new file mode 100644
index 00000000..5f26cdd1
--- /dev/null
+++ b/common/res_leanback/animator/lb_onboarding_title_enter.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="533"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="60dp"
+ android:valueTo="0dp"
+ android:duration="533"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/common/res_leanback/animator/lb_page_indicator_dot_hide.xml b/common/res_leanback/animator/lb_page_indicator_dot_hide.xml
new file mode 100644
index 00000000..fdd60342
--- /dev/null
+++ b/common/res_leanback/animator/lb_page_indicator_dot_hide.xml
@@ -0,0 +1,37 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:duration="167"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="diameter"
+ android:valueFrom="36dp"
+ android:valueTo="10dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="translationX"
+ android:valueFrom="-16dp"
+ android:valueTo="0dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/animator/lb_page_indicator_dot_show.xml b/common/res_leanback/animator/lb_page_indicator_dot_show.xml
new file mode 100644
index 00000000..392fb2c6
--- /dev/null
+++ b/common/res_leanback/animator/lb_page_indicator_dot_show.xml
@@ -0,0 +1,37 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:duration="167"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="diameter"
+ android:valueFrom="10dp"
+ android:valueTo="36dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+ <objectAnimator
+ android:propertyName="translationX"
+ android:valueFrom="-16dp"
+ android:valueTo="0dp"
+ android:duration="417"
+ android:interpolator="@android:anim/decelerate_interpolator" />
+</set>
diff --git a/common/res_leanback/drawable-xhdpi/lb_ic_nav_arrow.png b/common/res_leanback/drawable-xhdpi/lb_ic_nav_arrow.png
new file mode 100644
index 00000000..04578a75
--- /dev/null
+++ b/common/res_leanback/drawable-xhdpi/lb_ic_nav_arrow.png
Binary files differ
diff --git a/common/res_leanback/drawable/lb_onboarding_start_button_background.xml b/common/res_leanback/drawable/lb_onboarding_start_button_background.xml
new file mode 100644
index 00000000..57c31387
--- /dev/null
+++ b/common/res_leanback/drawable/lb_onboarding_start_button_background.xml
@@ -0,0 +1,24 @@
+<?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.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="#EEEEEE"/>
+ <corners android:radius="2dp" />
+ </shape>
+ </item>
+</selector>
diff --git a/common/res_leanback/layout/lb_onboarding_fragment.xml b/common/res_leanback/layout/lb_onboarding_fragment.xml
new file mode 100644
index 00000000..61cb93bd
--- /dev/null
+++ b/common/res_leanback/layout/lb_onboarding_fragment.xml
@@ -0,0 +1,120 @@
+<?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.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/onboarding_fragment_root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <FrameLayout
+ android:id="@+id/background_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:id="@+id/page_container"
+ android:layout_width="@dimen/lb_onboarding_content_width"
+ android:layout_height="@dimen/lb_onboarding_header_height"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="@dimen/lb_onboarding_header_margin_top"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="0.5"
+ android:layout_marginBottom="3dp"
+ android:fontFamily="sans-serif-light"
+ android:gravity="center"
+ android:textColor="#EEEEEE"
+ android:textSize="34sp"
+ android:lineSpacingExtra="14sp"/>
+ <TextView
+ android:id="@+id/description"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="0.5"
+ android:layout_marginTop="3dp"
+ android:fontFamily="sans-serif-light"
+ android:gravity="center"
+ android:textColor="#B3EEEEEE"
+ android:textSize="14sp"
+ android:lineSpacingExtra="10sp" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/content_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_above="@+id/page_indicator"
+ android:layout_below="@id/page_container"
+ android:layout_centerHorizontal="true"
+ android:visibility="gone" />
+
+ <com.google.android.tv.common.ui.setup.leanback.PagingIndicator
+ android:id="@id/page_indicator"
+ android:layout_width="@dimen/lb_onboarding_content_width"
+ android:layout_height="@dimen/lb_onboarding_navigation_height"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="58dp"
+ android:focusable="true"
+ android:contentDescription="@string/lb_onboarding_accessibility_next"
+ android:visibility="gone" />
+
+ <Button
+ android:id="@+id/button_start"
+ android:layout_width="wrap_content"
+ android:layout_height="36dp"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="62dp"
+ android:alpha="0.0"
+ android:background="@drawable/lb_onboarding_start_button_background"
+ android:elevation="1.5dp"
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ android:paddingEnd="24dp"
+ android:paddingStart="24dp"
+ android:stateListAnimator="@null"
+ android:text="@string/lb_onboarding_get_started"
+ android:textAllCaps="true"
+ android:textColor="#014269"
+ android:textSize="16sp"
+ android:visibility="gone"/>
+
+ <FrameLayout
+ android:id="@+id/foreground_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/logo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:contentDescription="@null" />
+
+</RelativeLayout>
diff --git a/common/res_leanback/values-af/strings.xml b/common/res_leanback/values-af/strings.xml
new file mode 100644
index 00000000..d683758b
--- /dev/null
+++ b/common/res_leanback/values-af/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"BEGIN HIER"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Volgende"</string>
+</resources>
diff --git a/common/res_leanback/values-am/strings.xml b/common/res_leanback/values-am/strings.xml
new file mode 100644
index 00000000..e70214dc
--- /dev/null
+++ b/common/res_leanback/values-am/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ይጀምሩ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ቀጣይ"</string>
+</resources>
diff --git a/common/res_leanback/values-ar/strings.xml b/common/res_leanback/values-ar/strings.xml
new file mode 100644
index 00000000..f7ba5716
--- /dev/null
+++ b/common/res_leanback/values-ar/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"البدء"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"التالية"</string>
+</resources>
diff --git a/common/res_leanback/values-az-rAZ/strings.xml b/common/res_leanback/values-az-rAZ/strings.xml
new file mode 100644
index 00000000..2293accf
--- /dev/null
+++ b/common/res_leanback/values-az-rAZ/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"BAŞLAYIN"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Növbəti"</string>
+</resources>
diff --git a/common/res_leanback/values-bg/strings.xml b/common/res_leanback/values-bg/strings.xml
new file mode 100644
index 00000000..a6c3cc03
--- /dev/null
+++ b/common/res_leanback/values-bg/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ПЪРВИ СТЪПКИ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Напред"</string>
+</resources>
diff --git a/common/res_leanback/values-bn-rBD/strings.xml b/common/res_leanback/values-bn-rBD/strings.xml
new file mode 100644
index 00000000..31b7a515
--- /dev/null
+++ b/common/res_leanback/values-bn-rBD/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"শুরু করা যাক"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"পরবর্তী"</string>
+</resources>
diff --git a/common/res_leanback/values-ca/strings.xml b/common/res_leanback/values-ca/strings.xml
new file mode 100644
index 00000000..8de1bb62
--- /dev/null
+++ b/common/res_leanback/values-ca/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"COMENÇA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Següent"</string>
+</resources>
diff --git a/common/res_leanback/values-cs/strings.xml b/common/res_leanback/values-cs/strings.xml
new file mode 100644
index 00000000..231f92e7
--- /dev/null
+++ b/common/res_leanback/values-cs/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ZAČÍNÁME"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Další"</string>
+</resources>
diff --git a/common/res_leanback/values-da/strings.xml b/common/res_leanback/values-da/strings.xml
new file mode 100644
index 00000000..25375bc2
--- /dev/null
+++ b/common/res_leanback/values-da/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"KOM GODT I GANG"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Næste"</string>
+</resources>
diff --git a/common/res_leanback/values-de/strings.xml b/common/res_leanback/values-de/strings.xml
new file mode 100644
index 00000000..0f492e2f
--- /dev/null
+++ b/common/res_leanback/values-de/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"JETZT STARTEN"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Weiter"</string>
+</resources>
diff --git a/common/res_leanback/values-el/strings.xml b/common/res_leanback/values-el/strings.xml
new file mode 100644
index 00000000..1df4b216
--- /dev/null
+++ b/common/res_leanback/values-el/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ΕΝΑΡΞΗ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Επόμενο"</string>
+</resources>
diff --git a/common/res_leanback/values-en-rAU/strings.xml b/common/res_leanback/values-en-rAU/strings.xml
new file mode 100644
index 00000000..d6995936
--- /dev/null
+++ b/common/res_leanback/values-en-rAU/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"GET STARTED"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Next"</string>
+</resources>
diff --git a/common/res_leanback/values-en-rGB/strings.xml b/common/res_leanback/values-en-rGB/strings.xml
new file mode 100644
index 00000000..d6995936
--- /dev/null
+++ b/common/res_leanback/values-en-rGB/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"GET STARTED"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Next"</string>
+</resources>
diff --git a/common/res_leanback/values-en-rIN/strings.xml b/common/res_leanback/values-en-rIN/strings.xml
new file mode 100644
index 00000000..d6995936
--- /dev/null
+++ b/common/res_leanback/values-en-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"GET STARTED"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Next"</string>
+</resources>
diff --git a/common/res_leanback/values-es-rUS/strings.xml b/common/res_leanback/values-es-rUS/strings.xml
new file mode 100644
index 00000000..0a1bb255
--- /dev/null
+++ b/common/res_leanback/values-es-rUS/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"COMENZAR"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Siguiente"</string>
+</resources>
diff --git a/common/res_leanback/values-es/strings.xml b/common/res_leanback/values-es/strings.xml
new file mode 100644
index 00000000..0a17e9f2
--- /dev/null
+++ b/common/res_leanback/values-es/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"EMPEZAR"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Siguiente"</string>
+</resources>
diff --git a/common/res_leanback/values-et-rEE/strings.xml b/common/res_leanback/values-et-rEE/strings.xml
new file mode 100644
index 00000000..f74e1773
--- /dev/null
+++ b/common/res_leanback/values-et-rEE/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ALUSTAGE"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Järgmine"</string>
+</resources>
diff --git a/common/res_leanback/values-eu-rES/strings.xml b/common/res_leanback/values-eu-rES/strings.xml
new file mode 100644
index 00000000..25dadb75
--- /dev/null
+++ b/common/res_leanback/values-eu-rES/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"LEHEN URRATSAK"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Hurrengoa"</string>
+</resources>
diff --git a/common/res_leanback/values-fa/strings.xml b/common/res_leanback/values-fa/strings.xml
new file mode 100644
index 00000000..21b1f969
--- /dev/null
+++ b/common/res_leanback/values-fa/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"شروع به‌ کار"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"بعدی"</string>
+</resources>
diff --git a/common/res_leanback/values-fi/strings.xml b/common/res_leanback/values-fi/strings.xml
new file mode 100644
index 00000000..c8474c4a
--- /dev/null
+++ b/common/res_leanback/values-fi/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ALOITA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Seuraava"</string>
+</resources>
diff --git a/common/res_leanback/values-fr-rCA/strings.xml b/common/res_leanback/values-fr-rCA/strings.xml
new file mode 100644
index 00000000..9f7933bc
--- /dev/null
+++ b/common/res_leanback/values-fr-rCA/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"COMMENCER"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Suivant"</string>
+</resources>
diff --git a/common/res_leanback/values-fr/strings.xml b/common/res_leanback/values-fr/strings.xml
new file mode 100644
index 00000000..9f7933bc
--- /dev/null
+++ b/common/res_leanback/values-fr/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"COMMENCER"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Suivant"</string>
+</resources>
diff --git a/common/res_leanback/values-gl-rES/strings.xml b/common/res_leanback/values-gl-rES/strings.xml
new file mode 100644
index 00000000..8fa1ed80
--- /dev/null
+++ b/common/res_leanback/values-gl-rES/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"COMEZAR"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Seguinte"</string>
+</resources>
diff --git a/common/res_leanback/values-hi/strings.xml b/common/res_leanback/values-hi/strings.xml
new file mode 100644
index 00000000..c966d80d
--- /dev/null
+++ b/common/res_leanback/values-hi/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"प्रारंभ करें"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"अगला"</string>
+</resources>
diff --git a/common/res_leanback/values-hr/strings.xml b/common/res_leanback/values-hr/strings.xml
new file mode 100644
index 00000000..31676fcf
--- /dev/null
+++ b/common/res_leanback/values-hr/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"POČETAK"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Dalje"</string>
+</resources>
diff --git a/common/res_leanback/values-hu/strings.xml b/common/res_leanback/values-hu/strings.xml
new file mode 100644
index 00000000..cfd19a8d
--- /dev/null
+++ b/common/res_leanback/values-hu/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"KEZDŐ LÉPÉSEK"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Következő"</string>
+</resources>
diff --git a/common/res_leanback/values-hy-rAM/strings.xml b/common/res_leanback/values-hy-rAM/strings.xml
new file mode 100644
index 00000000..7b99acad
--- /dev/null
+++ b/common/res_leanback/values-hy-rAM/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ՍԿՍԵԼ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Հաջորդը"</string>
+</resources>
diff --git a/common/res_leanback/values-in/strings.xml b/common/res_leanback/values-in/strings.xml
new file mode 100644
index 00000000..940a5060
--- /dev/null
+++ b/common/res_leanback/values-in/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"MULAI"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Berikutnya"</string>
+</resources>
diff --git a/common/res_leanback/values-is-rIS/strings.xml b/common/res_leanback/values-is-rIS/strings.xml
new file mode 100644
index 00000000..0cbf8935
--- /dev/null
+++ b/common/res_leanback/values-is-rIS/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"HEFJAST HANDA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Áfram"</string>
+</resources>
diff --git a/common/res_leanback/values-it/strings.xml b/common/res_leanback/values-it/strings.xml
new file mode 100644
index 00000000..68681952
--- /dev/null
+++ b/common/res_leanback/values-it/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"INIZIA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Avanti"</string>
+</resources>
diff --git a/common/res_leanback/values-iw/strings.xml b/common/res_leanback/values-iw/strings.xml
new file mode 100644
index 00000000..1df4245e
--- /dev/null
+++ b/common/res_leanback/values-iw/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"התחל"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"הבא"</string>
+</resources>
diff --git a/common/res_leanback/values-ja/strings.xml b/common/res_leanback/values-ja/strings.xml
new file mode 100644
index 00000000..67183065
--- /dev/null
+++ b/common/res_leanback/values-ja/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"使ってみる"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"次へ"</string>
+</resources>
diff --git a/common/res_leanback/values-ka-rGE/strings.xml b/common/res_leanback/values-ka-rGE/strings.xml
new file mode 100644
index 00000000..d5238fc7
--- /dev/null
+++ b/common/res_leanback/values-ka-rGE/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"დაწყება"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"შემდეგი"</string>
+</resources>
diff --git a/common/res_leanback/values-kk-rKZ/strings.xml b/common/res_leanback/values-kk-rKZ/strings.xml
new file mode 100644
index 00000000..bf67ae09
--- /dev/null
+++ b/common/res_leanback/values-kk-rKZ/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ІСКЕ КІРІСУ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Келесі"</string>
+</resources>
diff --git a/common/res_leanback/values-km-rKH/strings.xml b/common/res_leanback/values-km-rKH/strings.xml
new file mode 100644
index 00000000..39b3a3c4
--- /dev/null
+++ b/common/res_leanback/values-km-rKH/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ចាប់ផ្ដើម"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"បន្ទាប់"</string>
+</resources>
diff --git a/common/res_leanback/values-kn-rIN/strings.xml b/common/res_leanback/values-kn-rIN/strings.xml
new file mode 100644
index 00000000..8113d1ac
--- /dev/null
+++ b/common/res_leanback/values-kn-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ಪ್ರಾರಂಭಿಸು"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ಮುಂದೆ"</string>
+</resources>
diff --git a/common/res_leanback/values-ko/strings.xml b/common/res_leanback/values-ko/strings.xml
new file mode 100644
index 00000000..b64e2d96
--- /dev/null
+++ b/common/res_leanback/values-ko/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"시작하기"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"다음"</string>
+</resources>
diff --git a/common/res_leanback/values-ky-rKG/strings.xml b/common/res_leanback/values-ky-rKG/strings.xml
new file mode 100644
index 00000000..d789e873
--- /dev/null
+++ b/common/res_leanback/values-ky-rKG/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"БАШТАДЫК"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Кийинки"</string>
+</resources>
diff --git a/common/res_leanback/values-lo-rLA/strings.xml b/common/res_leanback/values-lo-rLA/strings.xml
new file mode 100644
index 00000000..de4d7ead
--- /dev/null
+++ b/common/res_leanback/values-lo-rLA/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ເລີ່ມຕົ້ນນຳໃຊ້"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ຕໍ່​ໄປ"</string>
+</resources>
diff --git a/common/res_leanback/values-lt/strings.xml b/common/res_leanback/values-lt/strings.xml
new file mode 100644
index 00000000..2938c289
--- /dev/null
+++ b/common/res_leanback/values-lt/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"PRADĖTI"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Kitas"</string>
+</resources>
diff --git a/common/res_leanback/values-lv/strings.xml b/common/res_leanback/values-lv/strings.xml
new file mode 100644
index 00000000..a65b8919
--- /dev/null
+++ b/common/res_leanback/values-lv/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"SĀKT DARBU"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Tālāk"</string>
+</resources>
diff --git a/common/res_leanback/values-mk-rMK/strings.xml b/common/res_leanback/values-mk-rMK/strings.xml
new file mode 100644
index 00000000..a7df3e64
--- /dev/null
+++ b/common/res_leanback/values-mk-rMK/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ЗАПОЧНИ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Следно"</string>
+</resources>
diff --git a/common/res_leanback/values-ml-rIN/strings.xml b/common/res_leanback/values-ml-rIN/strings.xml
new file mode 100644
index 00000000..dc051da9
--- /dev/null
+++ b/common/res_leanback/values-ml-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ആരംഭിക്കുക"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"അടുത്തത്"</string>
+</resources>
diff --git a/common/res_leanback/values-mn-rMN/strings.xml b/common/res_leanback/values-mn-rMN/strings.xml
new file mode 100644
index 00000000..eb4b74bd
--- /dev/null
+++ b/common/res_leanback/values-mn-rMN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ЭХЭЛЦГЭЭЕ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Дараах"</string>
+</resources>
diff --git a/common/res_leanback/values-mr-rIN/strings.xml b/common/res_leanback/values-mr-rIN/strings.xml
new file mode 100644
index 00000000..293aa75b
--- /dev/null
+++ b/common/res_leanback/values-mr-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"प्रारंभ करा"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"पुढील"</string>
+</resources>
diff --git a/common/res_leanback/values-ms-rMY/strings.xml b/common/res_leanback/values-ms-rMY/strings.xml
new file mode 100644
index 00000000..08e6a0a6
--- /dev/null
+++ b/common/res_leanback/values-ms-rMY/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"MULAKAN"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Seterusnya"</string>
+</resources>
diff --git a/common/res_leanback/values-my-rMM/strings.xml b/common/res_leanback/values-my-rMM/strings.xml
new file mode 100644
index 00000000..37ca64e0
--- /dev/null
+++ b/common/res_leanback/values-my-rMM/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"စတင်ပါ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ရှေ့သို့"</string>
+</resources>
diff --git a/common/res_leanback/values-nb/strings.xml b/common/res_leanback/values-nb/strings.xml
new file mode 100644
index 00000000..f79a3fb5
--- /dev/null
+++ b/common/res_leanback/values-nb/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"KOM I GANG"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Neste"</string>
+</resources>
diff --git a/common/res_leanback/values-ne-rNP/strings.xml b/common/res_leanback/values-ne-rNP/strings.xml
new file mode 100644
index 00000000..0b479416
--- /dev/null
+++ b/common/res_leanback/values-ne-rNP/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"सुरू गरौँ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"अर्को"</string>
+</resources>
diff --git a/common/res_leanback/values-nl/strings.xml b/common/res_leanback/values-nl/strings.xml
new file mode 100644
index 00000000..98580f53
--- /dev/null
+++ b/common/res_leanback/values-nl/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"AAN DE SLAG"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Volgende"</string>
+</resources>
diff --git a/common/res_leanback/values-pl/strings.xml b/common/res_leanback/values-pl/strings.xml
new file mode 100644
index 00000000..59482365
--- /dev/null
+++ b/common/res_leanback/values-pl/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"WYPRÓBUJ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Dalej"</string>
+</resources>
diff --git a/common/res_leanback/values-pt-rPT/strings.xml b/common/res_leanback/values-pt-rPT/strings.xml
new file mode 100644
index 00000000..1529e3aa
--- /dev/null
+++ b/common/res_leanback/values-pt-rPT/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"INICIAR"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Seguinte"</string>
+</resources>
diff --git a/common/res_leanback/values-pt/strings.xml b/common/res_leanback/values-pt/strings.xml
new file mode 100644
index 00000000..596351c5
--- /dev/null
+++ b/common/res_leanback/values-pt/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"PRIMEIROS PASSOS"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Próxima"</string>
+</resources>
diff --git a/common/res_leanback/values-ro/strings.xml b/common/res_leanback/values-ro/strings.xml
new file mode 100644
index 00000000..0a993f46
--- /dev/null
+++ b/common/res_leanback/values-ro/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ÎNCEPEȚI"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Înainte"</string>
+</resources>
diff --git a/common/res_leanback/values-ru/strings.xml b/common/res_leanback/values-ru/strings.xml
new file mode 100644
index 00000000..1c07da67
--- /dev/null
+++ b/common/res_leanback/values-ru/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"НАЧАТЬ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Далее"</string>
+</resources>
diff --git a/common/res_leanback/values-si-rLK/strings.xml b/common/res_leanback/values-si-rLK/strings.xml
new file mode 100644
index 00000000..78dee7c6
--- /dev/null
+++ b/common/res_leanback/values-si-rLK/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ආරම්භ කරන්න"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ඊළඟ"</string>
+</resources>
diff --git a/common/res_leanback/values-sk/strings.xml b/common/res_leanback/values-sk/strings.xml
new file mode 100644
index 00000000..998585dc
--- /dev/null
+++ b/common/res_leanback/values-sk/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ZAČÍNAME"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Ďalej"</string>
+</resources>
diff --git a/common/res_leanback/values-sl/strings.xml b/common/res_leanback/values-sl/strings.xml
new file mode 100644
index 00000000..ec5e4719
--- /dev/null
+++ b/common/res_leanback/values-sl/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ZAČNITE"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Naprej"</string>
+</resources>
diff --git a/common/res_leanback/values-sr/strings.xml b/common/res_leanback/values-sr/strings.xml
new file mode 100644
index 00000000..e65e0e56
--- /dev/null
+++ b/common/res_leanback/values-sr/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ЗАПОЧНИТЕ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Следећа"</string>
+</resources>
diff --git a/common/res_leanback/values-sv/strings.xml b/common/res_leanback/values-sv/strings.xml
new file mode 100644
index 00000000..6866b1d2
--- /dev/null
+++ b/common/res_leanback/values-sv/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"KOM IGÅNG"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Nästa"</string>
+</resources>
diff --git a/common/res_leanback/values-sw/strings.xml b/common/res_leanback/values-sw/strings.xml
new file mode 100644
index 00000000..5f921c04
--- /dev/null
+++ b/common/res_leanback/values-sw/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ANZA KUTUMIA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Inayofuata"</string>
+</resources>
diff --git a/common/res_leanback/values-ta-rIN/strings.xml b/common/res_leanback/values-ta-rIN/strings.xml
new file mode 100644
index 00000000..5b3c2749
--- /dev/null
+++ b/common/res_leanback/values-ta-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"தொடங்குக"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"அடுத்து"</string>
+</resources>
diff --git a/common/res_leanback/values-te-rIN/strings.xml b/common/res_leanback/values-te-rIN/strings.xml
new file mode 100644
index 00000000..dc1954d5
--- /dev/null
+++ b/common/res_leanback/values-te-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ప్రారంభించు"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"తదుపరి"</string>
+</resources>
diff --git a/common/res_leanback/values-th/strings.xml b/common/res_leanback/values-th/strings.xml
new file mode 100644
index 00000000..00e40d11
--- /dev/null
+++ b/common/res_leanback/values-th/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"เริ่มต้นใช้งาน"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"ถัดไป"</string>
+</resources>
diff --git a/common/res_leanback/values-tl/strings.xml b/common/res_leanback/values-tl/strings.xml
new file mode 100644
index 00000000..f4a93e7f
--- /dev/null
+++ b/common/res_leanback/values-tl/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"MAGSIMULA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Susunod"</string>
+</resources>
diff --git a/common/res_leanback/values-tr/strings.xml b/common/res_leanback/values-tr/strings.xml
new file mode 100644
index 00000000..126fe3b5
--- /dev/null
+++ b/common/res_leanback/values-tr/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"BAŞLA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Sonraki"</string>
+</resources>
diff --git a/common/res_leanback/values-uk/strings.xml b/common/res_leanback/values-uk/strings.xml
new file mode 100644
index 00000000..61dd2034
--- /dev/null
+++ b/common/res_leanback/values-uk/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"ПОЧАТИ"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Далі"</string>
+</resources>
diff --git a/common/res_leanback/values-ur-rPK/strings.xml b/common/res_leanback/values-ur-rPK/strings.xml
new file mode 100644
index 00000000..2a3299ff
--- /dev/null
+++ b/common/res_leanback/values-ur-rPK/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"شروع کریں"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"اگلا"</string>
+</resources>
diff --git a/common/res_leanback/values-uz-rUZ/strings.xml b/common/res_leanback/values-uz-rUZ/strings.xml
new file mode 100644
index 00000000..923ea077
--- /dev/null
+++ b/common/res_leanback/values-uz-rUZ/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"BOSHLADIK"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Keyingi"</string>
+</resources>
diff --git a/common/res_leanback/values-vi/strings.xml b/common/res_leanback/values-vi/strings.xml
new file mode 100644
index 00000000..5e2c4c07
--- /dev/null
+++ b/common/res_leanback/values-vi/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"BẮT ĐẦU"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Tiếp theo"</string>
+</resources>
diff --git a/common/res_leanback/values-zh-rCN/strings.xml b/common/res_leanback/values-zh-rCN/strings.xml
new file mode 100644
index 00000000..7e032d76
--- /dev/null
+++ b/common/res_leanback/values-zh-rCN/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"开始使用"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"下一页"</string>
+</resources>
diff --git a/common/res_leanback/values-zh-rHK/strings.xml b/common/res_leanback/values-zh-rHK/strings.xml
new file mode 100644
index 00000000..4c054d96
--- /dev/null
+++ b/common/res_leanback/values-zh-rHK/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"開始使用"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"下一頁"</string>
+</resources>
diff --git a/common/res_leanback/values-zh-rTW/strings.xml b/common/res_leanback/values-zh-rTW/strings.xml
new file mode 100644
index 00000000..4c054d96
--- /dev/null
+++ b/common/res_leanback/values-zh-rTW/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"開始使用"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"下一頁"</string>
+</resources>
diff --git a/common/res_leanback/values-zu/strings.xml b/common/res_leanback/values-zu/strings.xml
new file mode 100644
index 00000000..fe862d14
--- /dev/null
+++ b/common/res_leanback/values-zu/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="lb_onboarding_get_started" msgid="1724006991213712878">"QALISA"</string>
+ <string name="lb_onboarding_accessibility_next" msgid="113416166336573484">"Okulandelayo"</string>
+</resources>
diff --git a/common/res_leanback/values/colors.xml b/common/res_leanback/values/colors.xml
new file mode 100644
index 00000000..5230dfb8
--- /dev/null
+++ b/common/res_leanback/values/colors.xml
@@ -0,0 +1,23 @@
+<?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.
+ -->
+
+<resources>
+ <!-- Onboarding screen -->
+ <color name="lb_page_indicator_dot">#014269</color>
+ <color name="lb_page_indicator_arrow_background">#EEEEEE</color>
+ <color name="lb_page_indicator_arrow_shadow">#4C000000</color>
+</resources>
diff --git a/common/res_leanback/values/dimens.xml b/common/res_leanback/values/dimens.xml
new file mode 100644
index 00000000..275d22ae
--- /dev/null
+++ b/common/res_leanback/values/dimens.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+
+<resources>
+ <!-- Onboarding screen -->
+ <dimen name="lb_onboarding_content_width">536dp</dimen>
+ <dimen name="lb_onboarding_header_height">100dp</dimen>
+ <dimen name="lb_onboarding_header_margin_top">64dp</dimen>
+ <dimen name="lb_onboarding_start_button_height">36dp</dimen>
+ <dimen name="lb_onboarding_start_button_margin_bottom">62dp</dimen>
+ <!-- This value should be lb_onboarding_header_margin_top + lb_onboarding_header_height -->
+ <dimen name="lb_onboarding_content_margin_top">164dp</dimen>
+ <!-- This value should be lb_onboarding_start_button_height + lb_onboarding_start_button_margin_bottom -->
+ <dimen name="lb_onboarding_content_margin_bottom">98dp</dimen>
+ <!-- This value should be lb_page_indicator_arrow_diameter + 2 * lb_page_indicator_arrow_shadow_radius -->
+ <dimen name="lb_onboarding_navigation_height">40dp</dimen>
+ <dimen name="lb_page_indicator_arrow_diameter">36dp</dimen>
+ <dimen name="lb_page_indicator_arrow_shadow_radius">2dp</dimen>
+ <dimen name="lb_page_indicator_arrow_shadow_offset">1dp</dimen>
+ <dimen name="lb_page_indicator_arrow_gap">32dp</dimen>
+ <!-- This value must be lb_twice page_indicator_dot_radius -->
+ <dimen name="lb_page_indicator_dot_diameter">10dp</dimen>
+ <dimen name="lb_page_indicator_dot_radius">5dp</dimen>
+ <dimen name="lb_page_indicator_dot_gap">16dp</dimen>
+</resources>
diff --git a/common/res_leanback/values/strings.xml b/common/res_leanback/values/strings.xml
new file mode 100644
index 00000000..2f585c0b
--- /dev/null
+++ b/common/res_leanback/values/strings.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<resources>
+ <!-- Onboarding screen.-->
+ <eat-comment />
+ <!-- Text for "GET STARTED" button. This text should be in ALL CAPS. -->
+ <string name="lb_onboarding_get_started">GET STARTED</string>
+ <!-- Content description for page navigator. -->
+ <string name="lb_onboarding_accessibility_next">Next</string>
+</resources>
diff --git a/common/src/com/android/tv/common/AutoCloseableUtils.java b/common/src/com/android/tv/common/AutoCloseableUtils.java
new file mode 100644
index 00000000..ad364cc4
--- /dev/null
+++ b/common/src/com/android/tv/common/AutoCloseableUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.android.tv.common;
+
+import android.util.Log;
+
+/**
+ * Static utilities for AutoCloseable.
+ */
+public class AutoCloseableUtils {
+ private static final String TAG = "AutoCloseableUtils";
+
+ private AutoCloseableUtils() { }
+
+ public static void closeQuietly(AutoCloseable closeable) {
+ try {
+ closeable.close();
+ } catch (Exception ex) {
+ Log.e(TAG, "Error closing " + closeable, ex);
+ }
+ }
+}
diff --git a/common/src/com/android/tv/common/CollectionUtils.java b/common/src/com/android/tv/common/CollectionUtils.java
new file mode 100644
index 00000000..4a7a81f2
--- /dev/null
+++ b/common/src/com/android/tv/common/CollectionUtils.java
@@ -0,0 +1,78 @@
+/*
+ * 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.android.tv.common;
+
+import android.os.Build;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Static utilities for collections
+ */
+public class CollectionUtils {
+ /**
+ * Returns a new Set suitable for small data sets.
+ *
+ * <p>In M and above this is a {@link ArraySet} otherwise it is a {@link HashSet}.
+ */
+ public static <T> Set<T> createSmallSet() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return new ArraySet<>();
+ } else {
+ return new HashSet<>();
+ }
+ }
+
+ /**
+ * Returns a new Map suitable for small data sets.
+ *
+ * <p>In M and above this is a {@link ArrayMap} otherwise it is a {@link HashMap}.
+ */
+ public static <K, V> Map<K, V> createSmallMap() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return new ArrayMap<>();
+ } else {
+ return new HashMap<>();
+ }
+ }
+
+ /**
+ * Returns an array with the arrays concatenated together.
+ *
+ * @see <a href="http://stackoverflow.com/a/784842/1122089">Stackoverflow answer</a> by
+ * <a href="http://stackoverflow.com/users/40342/joachim-sauer">Joachim Sauer</a>
+ */
+ public static <T> T[] concatAll(T[] first, T[]... rest) {
+ int totalLength = first.length;
+ for (T[] array : rest) {
+ totalLength += array.length;
+ }
+ T[] result = Arrays.copyOf(first, totalLength);
+ int offset = first.length;
+ for (T[] array : rest) {
+ System.arraycopy(array, 0, result, offset, array.length);
+ offset += array.length;
+ }
+ return result;
+ }
+}
diff --git a/common/src/com/android/tv/common/MemoryManageable.java b/common/src/com/android/tv/common/MemoryManageable.java
new file mode 100644
index 00000000..0cb36103
--- /dev/null
+++ b/common/src/com/android/tv/common/MemoryManageable.java
@@ -0,0 +1,29 @@
+/*
+ * 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.android.tv.common;
+
+/**
+ * Interface for the fine-grained memory management.
+ * The class which wants to release memory based on the system constraints should inherit
+ * this interface and implement {@link #performTrimMemory}.
+ */
+public interface MemoryManageable {
+ /**
+ * For more information, see {@link android.content.ComponentCallbacks2#onTrimMemory}.
+ */
+ void performTrimMemory(int level);
+}
diff --git a/common/src/com/android/tv/common/SharedPreferencesUtils.java b/common/src/com/android/tv/common/SharedPreferencesUtils.java
new file mode 100644
index 00000000..38daa963
--- /dev/null
+++ b/common/src/com/android/tv/common/SharedPreferencesUtils.java
@@ -0,0 +1,64 @@
+/*
+ * 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.android.tv.common;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
+
+/**
+ * Static utilities for {@link android.content.SharedPreferences}
+ */
+public final class SharedPreferencesUtils {
+ // Note that changing the preference name will reset the preference values.
+ public static final String SHARED_PREF_FEATURES = "sharePreferencesFeatures";
+ public static final String SHARED_PREF_BROWSABLE = "browsable_shared_preference";
+ public static final String SHARED_PREF_WATCHED_HISTORY = "watched_history_shared_preference";
+ public static final String SHARED_PREF_AUDIO_CAPABILITIES =
+ "com.android.tv.audio_capabilities";
+ public static final String SHARED_PREF_RECURRING_RUNNER = "sharedPreferencesRecurringRunner";
+
+ private static boolean sInitializeCalled;
+
+ /**
+ * {@link android.content.SharedPreferences} loads the preference file when
+ * {@link Context#getSharedPreferences(String, int)} is called for the first time.
+ * Call {@link Context#getSharedPreferences(String, int)} as early as possible to avoid the ANR
+ * due to the file loading.
+ */
+ public static synchronized void initialize(final Context context) {
+ if (!sInitializeCalled) {
+ sInitializeCalled = true;
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ PreferenceManager.getDefaultSharedPreferences(context);
+ context.getSharedPreferences(SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
+ context.getSharedPreferences(SHARED_PREF_BROWSABLE, Context.MODE_PRIVATE);
+ context.getSharedPreferences(SHARED_PREF_WATCHED_HISTORY, Context.MODE_PRIVATE);
+ context.getSharedPreferences(SHARED_PREF_AUDIO_CAPABILITIES,
+ Context.MODE_PRIVATE);
+ context.getSharedPreferences(SHARED_PREF_RECURRING_RUNNER,
+ Context.MODE_PRIVATE);
+ return null;
+ }
+ }.execute();
+ }
+ }
+
+ private SharedPreferencesUtils() { }
+}
diff --git a/common/src/com/android/tv/common/TvCommonConstants.java b/common/src/com/android/tv/common/TvCommonConstants.java
index a3c20d94..9824497e 100644
--- a/common/src/com/android/tv/common/TvCommonConstants.java
+++ b/common/src/com/android/tv/common/TvCommonConstants.java
@@ -29,11 +29,6 @@ public final class TvCommonConstants {
public static final String EXTRA_APP_LINK_CHANNEL_URI = "app_link_channel_uri";
/**
- * A flag whether this platform supports time shifting API or not.
- */
- public static final boolean HAS_TIME_SHIFT_API = Build.VERSION.SDK_INT >= 23;
-
- /**
* An intent action to launch setup activity of a TV input. The intent should include
* TV input ID in the value of {@link EXTRA_INPUT_ID}. Optionally, given the value of
* {@link EXTRA_ACTIVITY_AFTER_COMPLETION}, the activity will be launched after the setup
diff --git a/common/src/com/android/tv/common/TvContentRatingCache.java b/common/src/com/android/tv/common/TvContentRatingCache.java
new file mode 100644
index 00000000..5ca780e3
--- /dev/null
+++ b/common/src/com/android/tv/common/TvContentRatingCache.java
@@ -0,0 +1,145 @@
+/*
+ * 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.android.tv.common;
+
+import android.media.tv.TvContentRating;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * TvContentRating cache.
+ */
+public final class TvContentRatingCache implements MemoryManageable {
+ private final static String TAG = "TvContentRatings";
+
+ private final static TvContentRatingCache INSTANCE = new TvContentRatingCache();
+
+ public final static TvContentRatingCache getInstance() {
+ return INSTANCE;
+ }
+
+ private final Map<String, TvContentRating[]> mRatingsMultiMap = CollectionUtils
+ .createSmallMap();
+
+ /**
+ * Returns an array TvContentRatings from a string of comma separated set of rating strings
+ * creating each from {@link TvContentRating#unflattenFromString(String)} if needed.
+ * Returns {@code null} if the string is empty or contains no valid ratings.
+ */
+ @Nullable
+ public TvContentRating[] getRatings(String commaSeparatedRatings) {
+ if (TextUtils.isEmpty(commaSeparatedRatings)) {
+ return null;
+ }
+ TvContentRating[] tvContentRatings;
+ if (mRatingsMultiMap.containsKey(commaSeparatedRatings)) {
+ tvContentRatings = mRatingsMultiMap.get(commaSeparatedRatings);
+ } else {
+ String normalizedRatings = TextUtils
+ .join(",", getSortedSetFromCsv(commaSeparatedRatings));
+ if (mRatingsMultiMap.containsKey(normalizedRatings)) {
+ tvContentRatings = mRatingsMultiMap.get(normalizedRatings);
+ } else {
+ tvContentRatings = stringToContentRatings(commaSeparatedRatings);
+ mRatingsMultiMap.put(normalizedRatings, tvContentRatings);
+ }
+ if (!normalizedRatings.equals(commaSeparatedRatings)) {
+ // Add an entry so the non normalized entry points to the same result;
+ mRatingsMultiMap.put(commaSeparatedRatings, tvContentRatings);
+ }
+ }
+ return tvContentRatings;
+ }
+
+ /**
+ * Returns a sorted array of TvContentRatings from a comma separated string of ratings.
+ */
+ @VisibleForTesting
+ static TvContentRating[] stringToContentRatings(String commaSeparatedRatings) {
+ if (TextUtils.isEmpty(commaSeparatedRatings)) {
+ return null;
+ }
+ Set<String> ratingStrings = getSortedSetFromCsv(commaSeparatedRatings);
+ List<TvContentRating> contentRatings = new ArrayList<>();
+ for (String rating : ratingStrings) {
+ try {
+ contentRatings.add(TvContentRating.unflattenFromString(rating));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Can't parse the content rating: '" + rating + "'", e);
+ }
+ }
+ return contentRatings.size() == 0 ?
+ null : contentRatings.toArray(new TvContentRating[contentRatings.size()]);
+ }
+
+ private static Set<String> getSortedSetFromCsv(String commaSeparatedRatings) {
+ String[] ratingStrings = commaSeparatedRatings.split("\\s*,\\s*");
+ return toSortedSet(ratingStrings);
+ }
+
+ private static Set<String> toSortedSet(String[] ratingStrings) {
+ if (ratingStrings.length == 0) {
+ return Collections.EMPTY_SET;
+ } else if (ratingStrings.length == 1) {
+ return Collections.singleton(ratingStrings[0]);
+ } else {
+ // Using a TreeSet here is not very efficient, however it is good enough because:
+ // - the results are cached
+ // - in testing with multiple TISs, less than 50 entries are created
+ SortedSet<String> set = new TreeSet<>();
+ Collections.addAll(set, ratingStrings);
+ return set;
+ }
+ }
+
+ /**
+ * Returns a string of each flattened content rating, sorted and concatenated together
+ * with a comma.
+ */
+ public static String contentRatingsToString(TvContentRating[] contentRatings) {
+ if (contentRatings == null || contentRatings.length == 0) {
+ return null;
+ }
+ String[] ratingStrings = new String[contentRatings.length];
+ for (int i = 0; i < contentRatings.length; i++) {
+ ratingStrings[i] = contentRatings[i].flattenToString();
+ }
+ if (ratingStrings.length == 1) {
+ return ratingStrings[0];
+ } else {
+ return TextUtils.join(",", toSortedSet(ratingStrings));
+ }
+ }
+
+ @Override
+ public void performTrimMemory(int level) {
+ mRatingsMultiMap.clear();
+ }
+
+ private TvContentRatingCache() {
+ }
+}
diff --git a/common/src/com/android/tv/common/annotation/UsedByReflection.java b/common/src/com/android/tv/common/annotation/UsedByReflection.java
new file mode 100644
index 00000000..5a4517f7
--- /dev/null
+++ b/common/src/com/android/tv/common/annotation/UsedByReflection.java
@@ -0,0 +1,29 @@
+/*
+ * 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.android.tv.common.annotation;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Denotes that the method or field is used by reflection even though it is not ever called
+ * directly.
+ */
+@Retention(SOURCE)
+public @interface UsedByReflection {
+}
diff --git a/common/src/com/android/tv/common/dvr/DvrSessionClient.java b/common/src/com/android/tv/common/dvr/DvrSessionClient.java
deleted file mode 100644
index b7dde7ff..00000000
--- a/common/src/com/android/tv/common/dvr/DvrSessionClient.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.android.tv.common.dvr;
-
-import android.content.Context;
-import android.media.tv.TvContract;
-import android.media.tv.TvView;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A session used for recording.
- */
-public class DvrSessionClient {
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({RECORD_STOP_REASON_DISKFULL, RECORD_STOP_REASON_CONFLICT,
- RECORD_STOP_REASON_CONNECT_FAILED, RECORD_STOP_REASON_DISCONNECTED,
- RECORD_STOP_REASON_UNKNOWN})
- public @interface RecordStopReason {}
- public static final int RECORD_STOP_REASON_DISKFULL = 1;
- public static final int RECORD_STOP_REASON_CONFLICT = 2;
- public static final int RECORD_STOP_REASON_CONNECT_FAILED = 3;
- public static final int RECORD_STOP_REASON_DISCONNECTED = 4;
- public static final int RECORD_STOP_REASON_UNKNOWN = 10;
-
- private boolean mRecordStarted;
- private Callback mCallback;
- private TvView mTvView;
-
- public DvrSessionClient(Context context) {
- mTvView = new TvView(context);
- }
-
- /**
- * Connects the session to a specific input {@code inputId}.
- */
- public void connect(String inputId, Callback callback) {
- mCallback = callback;
- Bundle bundle = new Bundle();
- bundle.putBoolean(DvrUtils.BUNDLE_IS_DVR, true);
- mTvView.tune(inputId, TvContract.buildChannelUri(0), bundle);
- mTvView.sendAppPrivateCommand(DvrUtils.APP_PRIV_CREATE_DVR_SESSION, null);
- mTvView.setCallback(new TvView.TvInputCallback() {
- @Override
- public void onConnectionFailed(String inputId) {
- if (mCallback == null) {
- return;
- }
- mCallback.onDisconnected();
- }
-
- @Override
- public void onDisconnected(String inputId) {
- if (mCallback == null) {
- return;
- }
- mCallback.onDisconnected();
- }
-
- @Override
- public void onEvent(String inputId, String eventType, Bundle eventArgs) {
- if (mCallback == null) {
- return;
- }
- String mediaUriString = eventArgs == null ? null :
- eventArgs.getString(DvrUtils.BUNDLE_MEDIA_URI, null);
- Uri mediaUri = mediaUriString == null ? null : Uri.parse(mediaUriString);
- if (DvrUtils.EVENT_TYPE_CONNECTED.equals(eventType)) {
- mCallback.onConnected();
- } else if (DvrUtils.EVENT_TYPE_RECORD_STARTED.equals(eventType)) {
- mCallback.onRecordStarted(mediaUri);
- } else if (DvrUtils.EVENT_TYPE_RECORD_STOPPED.equals(eventType)) {
- int reason = eventArgs.getInt(DvrUtils.BUNDLE_STOPPED_REASON);
- mCallback.onRecordStopped(mediaUri, reason);
- } else if (DvrUtils.EVENT_TYPE_DELETED.equals(eventType)) {
- mCallback.onRecordDeleted(mediaUri);
- }
- }
-
- // TODO: handle track select.
- });
- }
-
- /**
- * Releases the session.
- */
- public void release() {
- mTvView.reset();
- mCallback = null;
- }
-
- /**
- * Starts recording.
- */
- public void startRecord(Uri channelUri, Uri mediaUri) {
- if (mRecordStarted) {
- throw new IllegalStateException("Don't reuse the session for simple implementation");
- }
- mRecordStarted = true;
- Bundle params = DvrUtils.buildMediaUri(mediaUri);
- params.putString(DvrUtils.BUNDLE_CHANNEL_URI, channelUri.toString());
- mTvView.sendAppPrivateCommand(DvrUtils.APP_PRIV_START_RECORD, params);
- }
-
- /**
- * Stops recording.
- */
- public void stopRecord() {
- if (!mRecordStarted) {
- return;
- }
- mRecordStarted = false;
- mTvView.sendAppPrivateCommand(DvrUtils.APP_PRIV_STOP_RECORD, null);
- }
-
- /**
- * Deletes a recorded media.
- */
- public void delete(Uri mediaUri) {
- mTvView.sendAppPrivateCommand(DvrUtils.APP_PRIV_DELETE, DvrUtils.buildMediaUri(mediaUri));
- }
-
- public abstract static class Callback {
- public void onConnected() { }
- public void onDisconnected() { }
- public void onRecordStarted(Uri mediaUri) { }
- public void onRecordStopped(Uri mediaUri, @RecordStopReason int reason) { }
- public void onRecordDeleted(Uri mediaUri) { }
- public void onRecordDeleteFailed(Uri mediaUri, int reason) { }
- }
-}
diff --git a/common/src/com/android/tv/common/dvr/DvrTvView.java b/common/src/com/android/tv/common/dvr/DvrTvView.java
deleted file mode 100644
index 247db191..00000000
--- a/common/src/com/android/tv/common/dvr/DvrTvView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.android.tv.common.dvr;
-
-import android.content.Context;
-import android.media.tv.TvContract;
-import android.media.tv.TvView;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.AttributeSet;
-
-/**
- * Extend {@link TvView} to support recording playback.
- */
-public class DvrTvView extends TvView {
-
- public DvrTvView(Context context) {
- this(context, null, 0);
- }
-
- public DvrTvView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DvrTvView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- /**
- * Start playback of recording. Once TvInput is ready to play, onVideoAvailable will be called.
- * Playback control will be done with timeshift method for seek, play, pause.
- */
- public void playMedia(String inputId, Uri mediaUri) {
- tune(inputId, TvContract.buildChannelUri(0), DvrUtils.buildMediaUri(mediaUri));
- }
-
- @Override
- public void tune(String inputId, Uri channelUri, Bundle params) {
- super.tune(inputId, channelUri, params);
- sendAppPrivateCommand(DvrUtils.APP_PRIV_CREATE_PLAYBACK_SESSION, null);
- }
-
- public void setTimeShiftPositionCallback(TimeShiftPositionCallback2 callback) {
- // TODO: implement
- }
-
- /**
- * We need end position for recording playback.
- */
- public abstract static class TimeShiftPositionCallback2 extends TimeShiftPositionCallback {
- public void onTimeShiftEndPositionChanged(String inputId, long timeMs) { }
- }
-}
diff --git a/common/src/com/android/tv/common/feature/CommonFeatures.java b/common/src/com/android/tv/common/feature/CommonFeatures.java
new file mode 100644
index 00000000..bfef19a6
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/CommonFeatures.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.android.tv.common.feature;
+
+import static com.android.tv.common.feature.EngOnlyFeature.ENG_ONLY_FEATURE;
+import static com.android.tv.common.feature.FeatureUtils.AND;
+import static com.android.tv.common.feature.TestableFeature.createTestableFeature;
+
+/**
+ * List of {@link Feature} that affect more than just the Live TV app.
+ *
+ * <p>Remove the {@code Feature} once it is launched.
+ */
+public class CommonFeatures {
+ /**
+ * DVR
+ *
+ * <p>See <a href="https://goto.google.com/atv-dvr-onepager">go/atv-dvr-onepager</a>
+ */
+ public static TestableFeature DVR = createTestableFeature(
+ AND(
+ ENG_ONLY_FEATURE,
+ new PropertyFeature("dvr_enabled", false),
+ Sdk.M_FEATURE // TODO(dvr): Sdk.N_PREVIEW_FEATURE
+ ));
+}
diff --git a/common/src/com/android/tv/common/feature/EngOnlyFeature.java b/common/src/com/android/tv/common/feature/EngOnlyFeature.java
new file mode 100644
index 00000000..14d2b49b
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/EngOnlyFeature.java
@@ -0,0 +1,40 @@
+/*
+ * 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.android.tv.common.feature;
+
+import android.content.Context;
+
+import com.android.tv.common.BuildConfig;
+
+/**
+ * A feature that is only available on {@link BuildConfig#ENG} builds.
+ */
+public final class EngOnlyFeature implements Feature {
+ public static Feature ENG_ONLY_FEATURE = new EngOnlyFeature();
+
+ private EngOnlyFeature() { }
+
+ @Override
+ public boolean isEnabled(Context context) {
+ return BuildConfig.ENG;
+ }
+
+ @Override
+ public String toString() {
+ return "EngOnlyFeature(" + BuildConfig.ENG + ")";
+ }
+}
diff --git a/common/src/com/android/tv/common/feature/PackageVersionFeature.java b/common/src/com/android/tv/common/feature/PackageVersionFeature.java
new file mode 100644
index 00000000..7f615d31
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/PackageVersionFeature.java
@@ -0,0 +1,55 @@
+/*
+ * 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.android.tv.common.feature;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+/*
+ * A feature controlled by package version.
+ */
+public class PackageVersionFeature implements Feature {
+ private static final String TAG = "PackageVersionFeature";
+ private static final boolean DEBUG = false;
+
+ private final String mPackageName;
+ private final int mRequiredVersionCode;
+
+ public PackageVersionFeature(String packageName, int requiredVersionCode) {
+ mPackageName = packageName;
+ mRequiredVersionCode = requiredVersionCode;
+ }
+
+ @Override
+ public boolean isEnabled(Context context) {
+ try {
+ PackageInfo pInfo = context.getPackageManager().getPackageInfo(mPackageName, 0);
+ return pInfo != null && pInfo.versionCode >= mRequiredVersionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Can't find package '" + mPackageName + "'.", e);
+ return false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PackageVersionFeature[packageName=" + mPackageName + ",requiredVersion="
+ + mRequiredVersionCode + "]";
+ }
+}
diff --git a/common/src/com/android/tv/common/feature/Sdk.java b/common/src/com/android/tv/common/feature/Sdk.java
new file mode 100644
index 00000000..1efefd89
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/Sdk.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.android.tv.common.feature;
+
+import android.content.Context;
+import android.os.Build;
+
+/**
+ * Holder for SDK version features
+ */
+public class Sdk {
+ public static Feature M_FEATURE = new SdkVersionFeature(Build.VERSION_CODES.M);
+
+ private static class SdkVersionFeature implements Feature {
+ private final int mVersionCode;
+
+ private SdkVersionFeature(int versionCode) {
+ mVersionCode = versionCode;
+ }
+
+ @Override
+ public boolean isEnabled(Context context) {
+ return Build.VERSION.SDK_INT >= mVersionCode;
+ }
+ }
+
+ private Sdk() {}
+}
diff --git a/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java b/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
index eb5c805f..4d3a70a8 100644
--- a/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
+++ b/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
@@ -20,14 +20,15 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
+import com.android.tv.common.SharedPreferencesUtils;
+
/**
* Feature controlled by shared preferences.
*/
public final class SharedPreferencesFeature implements Feature {
- private static final String TAG = "SharedPreferencesFeature";
+ private static final String TAG = "SharedPrefFeature";
private static final boolean DEBUG = false;
- private static final String SHARED_PREFERENCE = "sharePreferencesFeatures";
private String mKey;
private boolean mEnabled;
private boolean mDefaultValue;
@@ -54,7 +55,7 @@ public final class SharedPreferencesFeature implements Feature {
}
if (mSharedPreferences == null) {
mSharedPreferences = context.getSharedPreferences(
- SHARED_PREFERENCE, Context.MODE_PRIVATE);
+ SharedPreferencesUtils.SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
mEnabled = mSharedPreferences.getBoolean(mKey, mDefaultValue);
}
if (DEBUG) Log.d(TAG, mKey + " is " + mEnabled);
@@ -70,7 +71,7 @@ public final class SharedPreferencesFeature implements Feature {
if (DEBUG) Log.d(TAG, mKey + " is set to " + enable);
if (mSharedPreferences == null) {
mSharedPreferences = context.getSharedPreferences(
- SHARED_PREFERENCE, Context.MODE_PRIVATE);
+ SharedPreferencesUtils.SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
mEnabled = enable;
mSharedPreferences.edit().putBoolean(mKey, enable).apply();
} else if (mEnabled != enable) {
diff --git a/common/src/com/android/tv/common/feature/TestableFeature.java b/common/src/com/android/tv/common/feature/TestableFeature.java
index db546ec9..a02877ec 100644
--- a/common/src/com/android/tv/common/feature/TestableFeature.java
+++ b/common/src/com/android/tv/common/feature/TestableFeature.java
@@ -16,7 +16,6 @@
package com.android.tv.common.feature;
-import android.app.ActivityManager;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
@@ -31,6 +30,9 @@ import com.android.tv.common.TvCommonUtils;
*/
public class TestableFeature implements Feature {
private final static String TAG = "TestableFeature";
+ private final static String DETAIL_MESSAGE
+ = "TestableFeatures should only be changed in tests.";
+
private final Feature mDelegate;
private Boolean mTestValue = null;
@@ -44,24 +46,29 @@ public class TestableFeature implements Feature {
@VisibleForTesting
public void enableForTest() {
- if (TvCommonUtils.isRunningInTest()) {
- Log.e(TAG, "TestableFeatures should only be changed in tests. Ignoring");
+ if (!TvCommonUtils.isRunningInTest()) {
+ Log.e(TAG, "Not enabling for test:" + this,
+ new IllegalStateException(DETAIL_MESSAGE));
+ } else {
mTestValue = true;
}
}
@VisibleForTesting
public void disableForTests() {
- if (TvCommonUtils.isRunningInTest()) {
- Log.e(TAG, "TestableFeatures should only be changed in tests. Ignoring");
+ if (!TvCommonUtils.isRunningInTest()) {
+ Log.e(TAG, "Not disabling for test: " + this,
+ new IllegalStateException(DETAIL_MESSAGE));
+ } else {
mTestValue = false;
}
}
@VisibleForTesting
public void resetForTests() {
- if (TvCommonUtils.isRunningInTest()) {
- Log.e(TAG, "TestableFeatures should only be changed in tests. Ignoring");
+ if (!TvCommonUtils.isRunningInTest()) {
+ Log.e(TAG, "Not resetting feature: " + this, new IllegalStateException(DETAIL_MESSAGE));
+ } else {
mTestValue = null;
}
}
diff --git a/common/src/com/android/tv/common/recording/PlaybackTvView.java b/common/src/com/android/tv/common/recording/PlaybackTvView.java
new file mode 100644
index 00000000..e62ee06f
--- /dev/null
+++ b/common/src/com/android/tv/common/recording/PlaybackTvView.java
@@ -0,0 +1,191 @@
+/*
+ * 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.android.tv.common.recording;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvContract;
+import android.media.tv.TvTrackInfo;
+import android.media.tv.TvView;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.AttributeSet;
+
+import com.android.tv.common.feature.CommonFeatures;
+
+import java.util.List;
+
+/**
+ * Extend {@link TvView} to support recording playback.
+ */
+@TargetApi(Build.VERSION_CODES.M) // TODO(DVR): set to N
+public class PlaybackTvView extends TvView {
+
+ final TvInputCallback mInternalCallback = new TvInputCallback() {
+ @Override
+ public void onChannelRetuned(String inputId, Uri channelUri) {
+ if (mCallback != null) {
+ mCallback.onChannelRetuned(inputId, channelUri);
+ }
+ }
+
+ @Override
+ public void onConnectionFailed(String inputId) {
+ if (mCallback != null) {
+ mCallback.onConnectionFailed(inputId);
+ }
+ }
+
+ @Override
+ public void onContentAllowed(String inputId) {
+ if (mCallback != null) {
+ mCallback.onContentAllowed(inputId);
+ }
+ }
+
+ @Override
+ public void onContentBlocked(String inputId, TvContentRating rating) {
+ if (mCallback != null) {
+ mCallback.onContentBlocked(inputId, rating);
+ }
+ }
+
+ @Override
+ public void onDisconnected(String inputId) {
+ if (mCallback != null) {
+ mCallback.onDisconnected(inputId);
+ }
+ }
+
+ @Override
+ public void onEvent(String inputId, String eventType, Bundle eventArgs) {
+ if (mCallback != null) {
+ if (eventType.equals(RecordingUtils.EVENT_TYPE_TIMESHIFT_END_POSITION)) {
+ if (mTimeshiftCallback != null) {
+ mTimeshiftCallback.onTimeShiftEndPositionChanged(inputId,
+ eventArgs.getLong(RecordingUtils.BUNDLE_TIMESHIFT_END_POSITION));
+ }
+ return;
+ }
+ mCallback.onEvent(inputId, eventType, eventArgs);
+ }
+ }
+
+ @Override
+ public void onTimeShiftStatusChanged(String inputId, int status) {
+ if (mCallback != null) {
+ mCallback.onTimeShiftStatusChanged(inputId, status);
+ }
+ }
+
+ @Override
+ public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) {
+ if (mCallback != null) {
+ mCallback.onTracksChanged(inputId, tracks);
+ }
+ }
+
+ @Override
+ public void onTrackSelected(String inputId, int type, String trackId) {
+ if (mCallback != null) {
+ mCallback.onTrackSelected(inputId, type, trackId);
+ }
+ }
+
+ @Override
+ public void onVideoAvailable(String inputId) {
+ if (mCallback != null) {
+ mCallback.onVideoAvailable(inputId);
+ }
+ }
+
+ @Override
+ public void onVideoSizeChanged(String inputId, int width, int height) {
+ if (mCallback != null) {
+ mCallback.onVideoSizeChanged(inputId, width, height);
+ }
+ }
+
+ @Override
+ public void onVideoUnavailable(String inputId, int reason) {
+ if (mCallback != null) {
+ mCallback.onVideoUnavailable(inputId, reason);
+ }
+ }
+ };
+
+ private TvInputCallback mCallback;
+ private TimeShiftPositionCallback2 mTimeshiftCallback;
+
+ public PlaybackTvView(Context context) {
+ this(context, null, 0);
+ }
+
+ public PlaybackTvView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PlaybackTvView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Start playback of recording. Once TvInput is ready to play, onVideoAvailable will be called.
+ * Playback control will be done with timeshift method for seek, play, pause.
+ */
+ public void playMedia(String inputId, Uri mediaUri) {
+ tune(inputId, TvContract.buildChannelUri(0), RecordingUtils.buildMediaUri(mediaUri));
+ }
+
+ @Override
+ public void tune(String inputId, Uri channelUri, Bundle params) {
+ super.tune(inputId, channelUri, params);
+ if (CommonFeatures.DVR.isEnabled(getContext())) {
+ sendAppPrivateCommand(RecordingUtils.APP_PRIV_CREATE_PLAYBACK_SESSION, null);
+ }
+ }
+
+ public void setTimeShiftPositionCallback(TimeShiftPositionCallback2 callback) {
+ if (CommonFeatures.DVR.isEnabled(getContext())) {
+ mTimeshiftCallback = callback;
+ }
+ super.setTimeShiftPositionCallback(callback);
+ }
+
+ @Override
+ public void setCallback(TvInputCallback callback) {
+ if (CommonFeatures.DVR.isEnabled(getContext())) {
+ mCallback = callback;
+ if (callback == null) {
+ super.setCallback(null);
+ } else {
+ super.setCallback(mInternalCallback);
+ }
+ } else {
+ super.setCallback(callback);
+ }
+ }
+
+ /**
+ * We need end position for recording playback.
+ */
+ public abstract static class TimeShiftPositionCallback2 extends TimeShiftPositionCallback {
+ public void onTimeShiftEndPositionChanged(String inputId, long timeMs) { }
+ }
+}
diff --git a/common/src/com/android/tv/common/recording/RecordingCapability.java b/common/src/com/android/tv/common/recording/RecordingCapability.java
new file mode 100644
index 00000000..266fd271
--- /dev/null
+++ b/common/src/com/android/tv/common/recording/RecordingCapability.java
@@ -0,0 +1,181 @@
+/*
+ * 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.android.tv.common.recording;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Static representation of the recording capability of a TvInputService.
+ */
+public final class RecordingCapability implements Parcelable{
+ /**
+ * The inputId this capability represents.
+ */
+ public final String inputId;
+
+ /**
+ * The max number of concurrent sessions that require a tuner.
+ *
+ * <p>Both recording and playing live TV requires a Tuner.
+ */
+ public final int maxConcurrentTunedSessions;
+
+ /**
+ * The max number concurrent session that play a stream.
+ *
+ *<p>This is often limited by the number of decoders available.
+ * The count includes both playing live TV and playing a recorded stream.
+ */
+ public final int maxConcurrentPlayingSessions;
+
+ /**
+ * Max number of concurrent sessions all types.
+ *
+ * <p>This may be limited by bandwidth or CPU or other factors.
+ */
+ public final int maxConcurrentSessionsOfAllTypes;
+
+ /**
+ * True if a tuned session can support recording and playback from the same resource.
+ */
+ public final boolean playbackWhileRecording;
+
+ private RecordingCapability(String inputId, int maxConcurrentTunedSessions,
+ int maxConcurrentPlayingSessions, int maxConcurrentSessionsOfAllTypes,
+ boolean playbackWhileRecording) {
+ this.inputId = inputId;
+ this.maxConcurrentTunedSessions = maxConcurrentTunedSessions;
+ this.maxConcurrentPlayingSessions = maxConcurrentPlayingSessions;
+ this.maxConcurrentSessionsOfAllTypes = maxConcurrentSessionsOfAllTypes;
+ this.playbackWhileRecording = playbackWhileRecording;
+ }
+
+ protected RecordingCapability(Parcel in) {
+ inputId = in.readString();
+ maxConcurrentTunedSessions = in.readInt();
+ maxConcurrentPlayingSessions = in.readInt();
+ maxConcurrentSessionsOfAllTypes = in.readInt();
+ playbackWhileRecording = in.readByte() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(inputId);
+ parcel.writeInt(maxConcurrentTunedSessions);
+ parcel.writeInt(maxConcurrentPlayingSessions);
+ parcel.writeInt(maxConcurrentSessionsOfAllTypes);
+ parcel.writeByte((byte) (playbackWhileRecording ? 1 : 0));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof RecordingCapability)) {
+ return false;
+ }
+ RecordingCapability that = (RecordingCapability) o;
+ return Objects.equals(maxConcurrentTunedSessions, that.maxConcurrentTunedSessions) &&
+ Objects.equals(maxConcurrentPlayingSessions, that.maxConcurrentPlayingSessions) &&
+ Objects.equals(maxConcurrentSessionsOfAllTypes,
+ that.maxConcurrentSessionsOfAllTypes) &&
+ Objects.equals(playbackWhileRecording, that.playbackWhileRecording) &&
+ Objects.equals(inputId, that.inputId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(inputId);
+ }
+
+ @Override
+ public String toString() {
+ return "RecordingCapability{" +
+ "inputId='" + inputId + '\'' +
+ ", maxConcurrentTunedSessions=" + maxConcurrentTunedSessions +
+ ", maxConcurrentPlayingSessions=" + maxConcurrentPlayingSessions +
+ ", maxConcurrentSessionsOfAllTypes=" + maxConcurrentSessionsOfAllTypes +
+ ", playbackWhileRecording=" + playbackWhileRecording +
+ '}';
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<RecordingCapability> CREATOR = new Creator<RecordingCapability>() {
+ @Override
+ public RecordingCapability createFromParcel(Parcel in) {
+ return new RecordingCapability(in);
+ }
+
+ @Override
+ public RecordingCapability[] newArray(int size) {
+ return new RecordingCapability[size];
+ }
+ };
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private String mInputId;
+ private int mMaxConcurrentTunedSessions;
+ private int mMaxConcurrentPlayingSessions;
+ private int mMaxConcurrentSessionsOfAllTypes;
+ private boolean mPlaybackWhileRecording;
+
+ public Builder setInputId(String inputId) {
+ mInputId = inputId;
+ return this;
+ }
+
+ public Builder setMaxConcurrentTunedSessions(int maxConcurrentTunedSessions) {
+ mMaxConcurrentTunedSessions = maxConcurrentTunedSessions;
+ return this;
+ }
+
+ public Builder setMaxConcurrentPlayingSessions(int maxConcurrentPlayingSessions) {
+ mMaxConcurrentPlayingSessions = maxConcurrentPlayingSessions;
+ return this;
+ }
+
+ public Builder setMaxConcurrentSessionsOfAllTypes(int maxConcurrentSessionsOfAllTypes) {
+ mMaxConcurrentSessionsOfAllTypes = maxConcurrentSessionsOfAllTypes;
+ return this;
+ }
+
+ public Builder setPlaybackWhileRecording(boolean playbackWhileRecording) {
+ mPlaybackWhileRecording = playbackWhileRecording;
+ return this;
+ }
+
+ public RecordingCapability build() {
+ return new RecordingCapability(mInputId, mMaxConcurrentTunedSessions,
+ mMaxConcurrentPlayingSessions, mMaxConcurrentSessionsOfAllTypes,
+ mPlaybackWhileRecording);
+ }
+ }
+}
+
+
diff --git a/common/src/com/android/tv/common/dvr/DvrTvInputService.java b/common/src/com/android/tv/common/recording/RecordingTvInputService.java
index ecf90656..6eea6ae7 100644
--- a/common/src/com/android/tv/common/dvr/DvrTvInputService.java
+++ b/common/src/com/android/tv/common/recording/RecordingTvInputService.java
@@ -14,33 +14,35 @@
* limitations under the License.
*/
-package com.android.tv.common.dvr;
+package com.android.tv.common.recording;
+import android.annotation.TargetApi;
import android.content.Context;
import android.media.PlaybackParams;
import android.media.tv.TvContentRating;
import android.media.tv.TvInputService;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
+import com.android.tv.common.feature.CommonFeatures;
+
import java.util.List;
/**
- * {@link TvInputService} class supporting DVR feature.
+ * {@link TvInputService} class that supports recording and playback.
*/
-public abstract class DvrTvInputService extends TvInputService {
+@TargetApi(Build.VERSION_CODES.M) // TODO(DVR): set to N
+public abstract class RecordingTvInputService extends TvInputService {
private static final String TAG = "DvrTvInputService";
- private static final boolean DEBUG = false;
- // TODO: use Features.DVR.
- private static final boolean FEATURE_DVR = false;
+ private static final boolean DEBUG = true;
@Override
public final Session onCreateSession(String inputId) {
- if (FEATURE_DVR) {
+ if (CommonFeatures.DVR.isEnabled(this)) {
return new InternalSession(this, inputId);
} else {
return onCreatePlaybackSession(inputId);
@@ -48,9 +50,9 @@ public abstract class DvrTvInputService extends TvInputService {
}
/**
- * Called when {@link com.android.tv.common.dvr.DvrSession#connect} is called.
+ * Called when {@link com.android.tv.common.recording.DvrSession#connect} is called.
*/
- protected DvrSession onCreateDvrSession(String inputId) {
+ protected TvRecording.RecordingSession onCreateDvrSession(String inputId) {
return null;
}
@@ -89,15 +91,15 @@ public abstract class DvrTvInputService extends TvInputService {
@Override
public void onAppPrivateCommand(String action, Bundle data) {
- if (action.equals(DvrUtils.APP_PRIV_CREATE_DVR_SESSION)) {
+ if (action.equals(RecordingUtils.APP_PRIV_CREATE_DVR_SESSION)) {
if (mSessionImpl == null) {
mSessionImpl = onCreateDvrSession(mInputId);
if (mSessionImpl != null) {
mSessionImpl.setPassthroughSession(this);
- notifySessionEvent(DvrUtils.EVENT_TYPE_CONNECTED, null);
+ notifySessionEvent(RecordingUtils.EVENT_TYPE_CONNECTED, null);
}
}
- } else if (action.equals(DvrUtils.APP_PRIV_CREATE_PLAYBACK_SESSION)) {
+ } else if (action.equals(RecordingUtils.APP_PRIV_CREATE_PLAYBACK_SESSION)) {
if (mSessionImpl == null) {
mSessionImpl = onCreatePlaybackSession(mInputId);
if (mSessionImpl != null) {
@@ -219,7 +221,7 @@ public abstract class DvrTvInputService extends TvInputService {
}
/**
- * Base class for {@link PlaybackSession} and {@link DvrSession}. Do not use it directly
+ * Base class for {@link PlaybackSession} and {@link TvRecording.RecordingSession}. Do not use it directly
* outside of this class.
*/
public static abstract class BaseSession extends TvInputService.Session {
@@ -325,121 +327,50 @@ public abstract class DvrTvInputService extends TvInputService {
}
/**
- * Session linked to {@link com.android.tv.common.dvr.DvrSession} to record contents.
+ * Session linked to {@link android.media.tv.TvView} to tune to a channel or play an recording.
*/
- public static abstract class DvrSession extends BaseSession {
- public DvrSession(Context context) {
- super(context);
- }
-
- @Override
- public final boolean onTune(Uri channelUri) {
- // no-op
- return false;
- }
-
- @Override
- public final boolean onSetSurface(Surface surface) {
- // no-op
- return false;
- }
-
- @Override
- public final void onSetStreamVolume(float volume) {
- // no-op
- }
-
- @Override
- public final void onSetCaptionEnabled(boolean enabled) {
- // no-op
- }
-
- /**
- * Called when it starts to record {@code channelUri}. {@link #notifyRecordStarted()}
- * should be called as soon as starting recording.
- */
- public abstract void onStartRecord(Uri channelUri, Uri mediaUri);
-
- /**
- * Called when it stops to record.
- */
- public abstract void onStopRecord();
-
- /**
- * Called when it is requested to delete {@code mediaUri}.
- */
- public abstract void onDelete(Uri mediaUri);
+ public static abstract class PlaybackSession extends BaseSession {
+ private boolean mIsRecordingPlayback;
- /**
- * Notifies when recording starts. It is an response of {@link #onStartRecord}.
- */
- public void notifyRecordStarted(Uri mediaUri) {
- notifySessionEvent(DvrUtils.EVENT_TYPE_RECORD_STARTED,
- DvrUtils.buildMediaUri(mediaUri));
+ public PlaybackSession(Context context) {
+ super(context);
}
/**
- * Notifies when recording is unexpectedly stopped.
+ * Returns {@code true}, if the current playback is for a recording.
*/
- public void notifyRecordUnexpectedlyStopped(Uri mediaUri, int reason) {
- Bundle params = DvrUtils.buildMediaUri(mediaUri);
- params.putInt(DvrUtils.BUNDLE_STOPPED_REASON, reason);
- notifySessionEvent(DvrUtils.EVENT_TYPE_RECORD_STOPPED, params);
+ public boolean isRecordingPlayback() {
+ return mIsRecordingPlayback;
}
/**
- * Notifies when the recording {@code mediaUri} is deleted.
+ * Called when it is requested to play an recording {@code mediaUri}. When playback and
+ * rendering starts, {@link #notifyVideoAvailable} should be called.
*/
- public void notifyDeleted(Uri mediaUri) {
- notifySessionEvent(DvrUtils.EVENT_TYPE_DELETED, DvrUtils.buildMediaUri(mediaUri));
- }
+ public void onPlayMedia(Uri mediaUri) { }
/**
- * Notifies when the deletion of the recording {@code mediaUri} is requested through
- * {@link #onDelete} but failed.
+ * Notifies TimeShift end position. It should have the form like onTimeShiftEndPosition.
+ * But, it's not trivial to add that in the prototyping. The method is recommended to be
+ * called inside {@link #onTimeShiftGetStartPosition()}, when a recording is played.
*/
- public void notifyDeleteFailed(Uri mediaUri, int reason) {
- Bundle params = DvrUtils.buildMediaUri(mediaUri);
- params.putInt(DvrUtils.BUNDLE_DELETE_FAILED_REASON, reason);
- notifySessionEvent(DvrUtils.EVENT_TYPE_DELETE_FAILED, params);
+ public void notifyTimeShiftEndPosition(long endPosition) {
+ Bundle params = new Bundle();
+ params.putLong(RecordingUtils.BUNDLE_TIMESHIFT_END_POSITION, endPosition);
+ notifySessionEvent(RecordingUtils.EVENT_TYPE_TIMESHIFT_END_POSITION, params);
}
@Override
- public void onAppPrivateCommand(String action, Bundle data) {
- if (DvrUtils.APP_PRIV_START_RECORD.equals(action)) {
- onStartRecord(Uri.parse(data.getString(DvrUtils.BUNDLE_CHANNEL_URI)),
- Uri.parse(data.getString(DvrUtils.BUNDLE_CHANNEL_URI)));
- } else if (DvrUtils.APP_PRIV_STOP_RECORD.equals(action)) {
- onStopRecord();
- } else if (DvrUtils.APP_PRIV_DELETE.equals(action)) {
- onDelete(Uri.parse(data.getString(DvrUtils.BUNDLE_CHANNEL_URI)));
- }
- }
- }
-
- /**
- * Session linked to {@link android.media.tv.TvView} to tune to a channel or play an recording.
- */
- public static abstract class PlaybackSession extends BaseSession {
- public PlaybackSession(Context context) {
- super(context);
- }
-
- /**
- * Called when it is requested to play an recording {@code mediaUri}. When playback and
- * rendering starts, {@link #notifyVideoAvailable} should be called.
- */
- public void onPlayMedia(Uri mediaUri) { }
-
- @Override
public final boolean onTune(Uri channelUri, Bundle params) {
- if (params != null && params.getBoolean(DvrUtils.BUNDLE_IS_DVR, false)) {
- notifySessionEvent(DvrUtils.EVENT_TYPE_CONNECTED, null);
+ if (params != null && params.getBoolean(RecordingUtils.BUNDLE_IS_DVR, false)) {
+ notifySessionEvent(RecordingUtils.EVENT_TYPE_CONNECTED, null);
return true;
- } else if (params != null && params.containsKey(DvrUtils.BUNDLE_MEDIA_URI)) {
- onPlayMedia(Uri.parse(params.getString(DvrUtils.BUNDLE_CHANNEL_URI)));
+ } else if (params != null && params.containsKey(RecordingUtils.BUNDLE_MEDIA_URI)) {
+ mIsRecordingPlayback = true;
+ onPlayMedia(Uri.parse(params.getString(RecordingUtils.BUNDLE_MEDIA_URI)));
return true;
} else {
+ mIsRecordingPlayback = false;
return onTune(channelUri);
}
}
diff --git a/common/src/com/android/tv/common/dvr/DvrUtils.java b/common/src/com/android/tv/common/recording/RecordingUtils.java
index 0a3e536b..ae91659f 100644
--- a/common/src/com/android/tv/common/dvr/DvrUtils.java
+++ b/common/src/com/android/tv/common/recording/RecordingUtils.java
@@ -14,40 +14,37 @@
* limitations under the License.
*/
-package com.android.tv.common.dvr;
+package com.android.tv.common.recording;
import android.net.Uri;
import android.os.Bundle;
-public class DvrUtils {
+public class RecordingUtils {
static final int ACTION_START_RECORD = 10055;
static final int ACTION_STOP_RECORD = 10056;
static final String EVENT_TYPE_CONNECTED = "event_type_connected";
- static final String EVENT_TYPE_RECORD_STARTED = "event_type_record_started";
- static final String EVENT_TYPE_RECORD_STOPPED = "event_type_record_stopped";
- static final String EVENT_TYPE_DELETED = "event_type_deleted";
- static final String EVENT_TYPE_DELETE_FAILED = "event_type_delete_failed";
+ static final String EVENT_TYPE_TIMESHIFT_END_POSITION = "event_type_timeshift_end_position";
static final String APP_PRIV_CREATE_PLAYBACK_SESSION = "app_priv_create_playback_session";
static final String APP_PRIV_CREATE_DVR_SESSION = "app_priv_create_dvr_session";
- static final String APP_PRIV_START_RECORD = "app_priv_start_record";
- static final String APP_PRIV_STOP_RECORD = "app_priv_stop_record";
- static final String APP_PRIV_DELETE = "app_priv_delete";
+
// Type: boolean
static final String BUNDLE_IS_DVR = "bundle_is_dvr";
// Type: String (Uri)
static final String BUNDLE_MEDIA_URI = "bundle_media_uri";
// Type: String
static final String BUNDLE_CHANNEL_URI = "bundle_channel_uri";
- // Type: int
- static final String BUNDLE_STOPPED_REASON = "stopped_reason";
- // Type: int
- static final String BUNDLE_DELETE_FAILED_REASON = "delete_failed_reason";
+ // Type: long
+ static final String BUNDLE_TIMESHIFT_END_POSITION = "timeshift_end_position";
- static Bundle buildMediaUri(Uri mediaUri) {
+ /**
+ * Builds a {@link Bundle} with {@code mediaUri}. If the bundle is sent with tune command,
+ * the {@code mediaUri} will be played.
+ */
+ public static Bundle buildMediaUri(Uri mediaUri) {
Bundle params = new Bundle();
- params.putString(DvrUtils.BUNDLE_MEDIA_URI, mediaUri.toString());
+ params.putString(RecordingUtils.BUNDLE_MEDIA_URI, mediaUri.toString());
return params;
}
}
diff --git a/common/src/com/android/tv/common/recording/TvRecording.java b/common/src/com/android/tv/common/recording/TvRecording.java
new file mode 100644
index 00000000..28a611a0
--- /dev/null
+++ b/common/src/com/android/tv/common/recording/TvRecording.java
@@ -0,0 +1,384 @@
+/*
+ * 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.android.tv.common.recording;
+
+import android.content.Context;
+import android.media.tv.TvContract;
+import android.media.tv.TvView;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.IntDef;
+import android.util.Log;
+import android.view.Surface;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * API for making TV Recordings.
+ * This class holds both the API under development and the session app private command magic needed
+ * to simulate the API.
+ */
+public final class TvRecording {
+ private static final String TAG = "TvRecording";
+ private static final boolean DEBUG = true; // STOPSHIP(DVR)
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RECORD_STOP_REASON_DISKFULL, RECORD_STOP_REASON_CONFLICT,
+ RECORD_STOP_REASON_CONNECT_FAILED, RECORD_STOP_REASON_DISCONNECTED,
+ RECORD_STOP_REASON_UNKNOWN})
+ public @interface RecordStopReason {
+ }
+
+ private static final int FIRST_REASON = 1;
+ public static final int RECORD_STOP_REASON_DISKFULL = 1;
+ public static final int RECORD_STOP_REASON_CONFLICT = 2;
+ public static final int RECORD_STOP_REASON_CONNECT_FAILED = 3;
+ public static final int RECORD_STOP_REASON_DISCONNECTED = 4;
+ public static final int RECORD_STOP_REASON_UNKNOWN = 5;
+ private static final int LAST_REASON = 5;
+
+ public abstract static class ClientCallback {
+ public void onConnected() { }
+
+ public void onDisconnected() { }
+
+ public void onRecordStarted(Uri mediaUri) { }
+
+ public void onRecordStopped(Uri mediaUri, @RecordStopReason int reason) { }
+
+ public void onRecordDeleted(Uri mediaUri) { }
+
+ public void onRecordDeleteFailed(Uri mediaUri, int reason) { }
+
+ public void onCapabilityReceived(RecordingCapability capability) { }
+ }
+
+ public interface RecordingClientApi {
+ void release();
+
+ void startRecord(Uri channelUri, Uri mediaUri);
+
+ void stopRecord();
+
+ void delete(Uri mediaUri);
+
+ void getCapability();
+ }
+
+ public interface RecordingSessionApi {
+ /**
+ * Start recording on {@code channelUri}.
+ * <p>{@link RecordingSession#notifyRecordStarted(Uri)} should be called as soon as the
+ * recording is started.
+ */
+ void onStartRecord(Uri channelUri, Uri mediaUri);
+
+ /**
+ * Called when it stops to record.
+ */
+ void onStopRecord();
+
+ /**
+ * Called when it is requested to delete {@code mediaUri}.
+ */
+ void onDelete(Uri mediaUri);
+
+ /**
+ * Called when the client request {@link RecordingCapability}.
+ */
+ RecordingCapability onGetCapability();
+ }
+
+ ///////////
+ // BELOW IS IMPLEMENTATION DETAILS OFTEN SPECIFIC TO USING APP PRIVATE COMMANDS
+ //////////
+
+ private static final String PREFIX = "record_";
+
+ private static final String APP_PRIV_DELETE = PREFIX + "app_priv_delete";
+ private static final String APP_PRIV_GET_CAPABILITY = PREFIX + "app_priv_get_capability";
+ private static final String APP_PRIV_START_RECORD = PREFIX + "app_priv_start_record";
+ private static final String APP_PRIV_STOP_RECORD = PREFIX + "app_priv_stop_record";
+
+ private static final String EVENT_TYPE_DELETED = PREFIX + "event_type_deleted";
+ private static final String EVENT_TYPE_DELETE_FAILED = PREFIX + "event_type_delete_failed";
+ private static final String EVENT_TYPE_CAPABILITY_RECEIVED = PREFIX
+ + "event_type_capability_received";
+ private static final String EVENT_TYPE_RECORD_STARTED = PREFIX + "event_type_record_started";
+ private static final String EVENT_TYPE_RECORD_STOPPED = PREFIX + "event_type_record_stopped";
+
+ // Type: int
+ private static final String BUNDLE_STOPPED_REASON = PREFIX + "stopped_reason";
+ // Type: int
+ private static final String BUNDLE_DELETE_FAILED_REASON = PREFIX + "delete_failed_reason";
+ // Type: RecordingCapability
+ private static final String BUNDLE_CAPABILITY = PREFIX + "capability";
+
+
+ /**
+ * Session linked to {@link TvRecordingClient} to record contents.
+ */
+ public static abstract class RecordingSession extends RecordingTvInputService.BaseSession
+ implements RecordingSessionApi {
+ private final static String TAG = "RecordingSession";
+
+ public RecordingSession(Context context) {
+ super(context);
+ }
+
+ @Override
+ public final boolean onTune(Uri channelUri) {
+ // no-op
+ return false;
+ }
+
+ @Override
+ public final boolean onSetSurface(Surface surface) {
+ // no-op
+ return false;
+ }
+
+ @Override
+ public final void onSetStreamVolume(float volume) {
+ // no-op
+ }
+
+ @Override
+ public final void onSetCaptionEnabled(boolean enabled) {
+ // no-op
+ }
+
+ /**
+ * Notifies when recording starts. It is an response of {@link #onStartRecord}.
+ */
+ public final void notifyRecordStarted(Uri mediaUri) {
+ notifySessionEvent(EVENT_TYPE_RECORD_STARTED, RecordingUtils.buildMediaUri(mediaUri));
+ }
+
+ /**
+ * Notifies when recording is unexpectedly stopped.
+ */
+ public final void notifyRecordUnexpectedlyStopped(Uri mediaUri, int reason) {
+ Bundle params = RecordingUtils.buildMediaUri(mediaUri);
+ params.putInt(BUNDLE_STOPPED_REASON, reason);
+ notifySessionEvent(EVENT_TYPE_RECORD_STOPPED, params);
+ }
+
+ /**
+ * Notifies when the recording {@code mediaUri} is deleted.
+ */
+ public final void notifyDeleted(Uri mediaUri) {
+ notifySessionEvent(EVENT_TYPE_DELETED, RecordingUtils.buildMediaUri(mediaUri));
+ }
+
+ /**
+ * Notifies when the deletion of the recording {@code mediaUri} is requested through
+ * {@link #onDelete} but failed.
+ */
+ public final void notifyDeleteFailed(Uri mediaUri, int reason) {
+ Bundle params = RecordingUtils.buildMediaUri(mediaUri);
+ params.putInt(BUNDLE_DELETE_FAILED_REASON, reason);
+ notifySessionEvent(EVENT_TYPE_DELETE_FAILED, params);
+ }
+
+ @Override
+ public final void onAppPrivateCommand(String action, Bundle data) {
+ if (DEBUG) Log.d(TAG, "onAppPrivateCommand(" + action + ", " + data + ")");
+ switch (action) {
+ case APP_PRIV_GET_CAPABILITY:
+ RecordingCapability capability = onGetCapability();
+ Bundle params = new Bundle();
+ params.putParcelable(BUNDLE_CAPABILITY, capability);
+ notifySessionEvent(EVENT_TYPE_CAPABILITY_RECEIVED, params);
+ break;
+ case APP_PRIV_DELETE:
+ onDelete(Uri.parse(data.getString(RecordingUtils.BUNDLE_CHANNEL_URI)));
+ break;
+ case APP_PRIV_START_RECORD:
+ onStartRecord(Uri.parse(data.getString(RecordingUtils.BUNDLE_CHANNEL_URI)),
+ Uri.parse(data.getString(RecordingUtils.BUNDLE_MEDIA_URI)));
+ break;
+ case APP_PRIV_STOP_RECORD:
+ onStopRecord();
+ break;
+ }
+ }
+ }
+
+ /**
+ * A session used for recording.
+ */
+ public static class TvRecordingClient implements RecordingClientApi {
+ private static final String TAG = "DvrSessionClient";
+
+ private ClientCallback mCallback;
+ private TvView mTvView;
+
+ public TvRecordingClient(Context context) {
+ if (DEBUG) {
+ Log.d(TAG, "creating client");
+ }
+ mTvView = new TvView(context);
+ }
+
+ /**
+ * Connects the session to a specific input {@code inputId}.
+ */
+ public void connect(String inputId, ClientCallback callback) {
+ if (DEBUG) {
+ Log.d(TAG, "connect " + inputId + " with " + callback);
+ }
+ mCallback = callback;
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(RecordingUtils.BUNDLE_IS_DVR, true);
+ mTvView.tune(inputId, TvContract.buildChannelUri(0), bundle);
+ mTvView.sendAppPrivateCommand(RecordingUtils.APP_PRIV_CREATE_DVR_SESSION, null);
+ mTvView.setCallback(new TvView.TvInputCallback() {
+ @Override
+ public void onConnectionFailed(String inputId) {
+ if (mCallback == null) {
+ return;
+ }
+ mCallback.onDisconnected();
+ }
+
+ @Override
+ public void onDisconnected(String inputId) {
+ if (mCallback == null) {
+ return;
+ }
+ mCallback.onDisconnected();
+ }
+
+ @Override
+ public void onEvent(String inputId, String eventType, Bundle eventArgs) {
+ if (mCallback == null) {
+ return;
+ }
+ String mediaUriString = eventArgs == null ? null
+ : eventArgs.getString(RecordingUtils.BUNDLE_MEDIA_URI, null);
+ Uri mediaUri = mediaUriString == null ? null : Uri.parse(mediaUriString);
+ switch (eventType) {
+ case RecordingUtils.EVENT_TYPE_CONNECTED:
+ mCallback.onConnected();
+ break;
+ case EVENT_TYPE_DELETED:
+ mCallback.onRecordDeleted(mediaUri);
+ break;
+ case EVENT_TYPE_DELETE_FAILED: {
+ // TODO(DVR) use reasons from API
+ int reason = eventArgs == null ? 0
+ : eventArgs.getInt(BUNDLE_DELETE_FAILED_REASON);
+ mCallback.onRecordDeleteFailed(mediaUri, reason);
+ break;
+ }
+ case EVENT_TYPE_CAPABILITY_RECEIVED: {
+ RecordingCapability capability = eventArgs
+ .getParcelable(BUNDLE_CAPABILITY);
+ mCallback.onCapabilityReceived(capability);
+ break;
+ }
+ case EVENT_TYPE_RECORD_STARTED:
+ mCallback.onRecordStarted(mediaUri);
+ break;
+ case EVENT_TYPE_RECORD_STOPPED: {
+ int reason = getRecordStopReason(eventArgs);
+ mCallback.onRecordStopped(mediaUri, reason);
+ break;
+ }
+ }
+ }
+
+ // TODO: handle track select.
+ });
+ }
+
+ /**
+ * Releases the session.
+ */
+ @Override
+ public void release() {
+ if (DEBUG) {
+ Log.d(TAG, "release " + this);
+ }
+ mTvView.reset();
+ mCallback = null;
+ }
+
+ /**
+ * Starts recording.
+ */
+ @Override
+ public void startRecord(Uri channelUri, Uri mediaUri) {
+ if (DEBUG) {
+ Log.d(TAG, "startRecord " + channelUri + ", " + mediaUri);
+ }
+ Bundle params = RecordingUtils.buildMediaUri(mediaUri);
+ params.putString(RecordingUtils.BUNDLE_CHANNEL_URI, channelUri.toString());
+ mTvView.sendAppPrivateCommand(APP_PRIV_START_RECORD, params);
+ }
+
+ /**
+ * Stops recording.
+ */
+ @Override
+ public void stopRecord() {
+ if (DEBUG) {
+ Log.d(TAG, "stopRecord " + this);
+ }
+ mTvView.sendAppPrivateCommand(APP_PRIV_STOP_RECORD, null);
+ }
+
+ /**
+ * Deletes a recorded media.
+ */
+ @Override
+ public void delete(Uri mediaUri) {
+ mTvView.sendAppPrivateCommand(APP_PRIV_DELETE,
+ RecordingUtils.buildMediaUri(mediaUri));
+ }
+
+ @Override
+ public void getCapability() {
+ mTvView.sendAppPrivateCommand(APP_PRIV_GET_CAPABILITY, null);
+ }
+
+ @Override
+ public String toString() {
+ return TvRecordingClient.class.getName() + "{" + "callBack=" + mCallback + "}";
+ }
+ }
+
+ @SuppressWarnings("ResourceType")
+ @RecordStopReason
+ private static int getRecordStopReason(Bundle eventArgs) {
+ if(eventArgs == null) {
+ if (DEBUG) Log.d(TAG, "Null stop reason");
+ return RECORD_STOP_REASON_UNKNOWN;
+ }
+ int reason = eventArgs.getInt(BUNDLE_STOPPED_REASON);
+ if (reason < FIRST_REASON || reason > LAST_REASON) {
+ if (DEBUG) Log.d(TAG, "Unknown stop reason " + reason);
+ reason = RECORD_STOP_REASON_UNKNOWN;
+ }
+ return reason;
+ }
+
+ private TvRecording() {
+ }
+}
diff --git a/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java b/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java
index 39af2d83..15b38f02 100644
--- a/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java
+++ b/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java
@@ -23,7 +23,8 @@ public interface OnActionClickListener {
/**
* Called when the action is clicked.
*
+ * @param category action category.
* @param id action id.
*/
- void onActionClick(int id);
+ void onActionClick(String category, int id);
}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java b/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java
index ed999990..0f44ce06 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java
@@ -17,6 +17,8 @@
package com.android.tv.common.ui.setup;
import android.app.Fragment;
+import android.view.View;
+import android.view.View.OnClickListener;
/**
* Helper class for the execution in the fragment.
@@ -25,9 +27,46 @@ public class SetupActionHelper {
/**
* Executes the action of the given {@code actionId}.
*/
- public static void onActionClick(Fragment fragment, int actionId) {
- if (fragment.getActivity() instanceof OnActionClickListener) {
- ((OnActionClickListener) fragment.getActivity()).onActionClick(actionId);
+ public static void onActionClick(Fragment fragment, String category, int actionId) {
+ OnActionClickListener listener = null;
+ if (fragment instanceof SetupFragment) {
+ listener = ((SetupFragment) fragment).getOnActionClickListener();
+ }
+ if (listener == null && fragment.getActivity() instanceof OnActionClickListener) {
+ listener = (OnActionClickListener) fragment.getActivity();
+ }
+ if (listener != null) {
+ listener.onActionClick(category, actionId);
}
}
+
+ /**
+ * Creates an {@link OnClickListener} to handle the action.
+ */
+ public static OnClickListener createOnClickListenerForAction(OnActionClickListener listener,
+ String category, int actionId) {
+ return new OnActionClickListenerForAction(listener, category, actionId);
+ }
+
+ private static class OnActionClickListenerForAction implements OnClickListener {
+ private final OnActionClickListener mListener;
+ private final String mCategory;
+ private final int mActionId;
+
+ OnActionClickListenerForAction(OnActionClickListener listener, String category,
+ int actionId) {
+ mListener = listener;
+ mCategory = category;
+ mActionId = actionId;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mListener != null) {
+ mListener.onActionClick(mCategory, mActionId);
+ }
+ }
+ }
+
+ private SetupActionHelper() { }
}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupActivity.java b/common/src/com/android/tv/common/ui/setup/SetupActivity.java
new file mode 100644
index 00000000..8c7b1b8e
--- /dev/null
+++ b/common/src/com/android/tv/common/ui/setup/SetupActivity.java
@@ -0,0 +1,168 @@
+/*
+ * 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.android.tv.common.ui.setup;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.support.annotation.NonNull;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.view.View;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+
+import com.android.tv.common.R;
+import com.android.tv.common.WeakHandler;
+import com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
+
+/**
+ * Setup activity for onboarding screens or TIS.
+ *
+ * <p>The inherited class should add theme {@code Theme.Setup.GuidedStep} to its definition in
+ * AndroidManifest.xml.
+ */
+public abstract class SetupActivity extends Activity implements OnActionClickListener {
+ private static final int MSG_EXECUTE_ACTION = 1;
+
+ private boolean mShowInitialFragment = true;
+ private long mFragmentTransitionDuration;
+ private final Handler mHandler = new SetupActivityHandler(this);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_setup);
+ mFragmentTransitionDuration = getResources().getInteger(
+ R.integer.setup_fragment_transition_duration);
+ // Show initial fragment only when the saved state is not restored, because the last
+ // fragment is restored if savesInstanceState is not null.
+ if (savedInstanceState == null) {
+ // This is the workaround to show the first fragment with delay to show the fragment
+ // enter transition. See http://b/26255145
+ getWindow().getDecorView().getViewTreeObserver().addOnPreDrawListener(
+ new OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ getWindow().getDecorView().getViewTreeObserver()
+ .removeOnPreDrawListener(this);
+ showInitialFragment();
+ return true;
+ }
+ });
+ } else {
+ mShowInitialFragment = false;
+ }
+ }
+
+ /**
+ * The inherited class should provide the initial fragment to show.
+ *
+ * <p>If this method returns {@code null} during {@link #onCreate}, then call
+ * {@link #showInitialFragment} explicitly later with non null initial fragment.
+ */
+ protected abstract Fragment onCreateInitialFragment();
+
+ /**
+ * Shows the initial fragment.
+ *
+ * <p>The inherited class can call this method later explicitly if it doesn't want the initial
+ * fragment to be shown in onCreate().
+ */
+ protected void showInitialFragment() {
+ if (!mShowInitialFragment) {
+ return;
+ }
+ Fragment fragment = onCreateInitialFragment();
+ if (fragment != null) {
+ showFragment(fragment, false);
+ mShowInitialFragment = false;
+ }
+ }
+
+ /**
+ * Shows the given fragment.
+ */
+ protected FragmentTransaction showFragment(Fragment fragment, boolean addToBackStack) {
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ if (fragment instanceof SetupFragment) {
+ int[] sharedElements = ((SetupFragment) fragment).getSharedElementIds();
+ if (sharedElements != null && sharedElements.length > 0) {
+ Transition sharedTransition = TransitionInflater.from(this)
+ .inflateTransition(R.transition.transition_action_background);
+ sharedTransition.setDuration(getSharedElementTransitionDuration());
+ SetupAnimationHelper.applyAnimationTimeScale(sharedTransition);
+ fragment.setSharedElementEnterTransition(sharedTransition);
+ fragment.setSharedElementReturnTransition(sharedTransition);
+ for (int id : sharedElements) {
+ View sharedView = findViewById(id);
+ if (sharedView != null) {
+ ft.addSharedElement(sharedView, sharedView.getTransitionName());
+ }
+ }
+ }
+ }
+ String tag = fragment.getClass().getCanonicalName();
+ if (addToBackStack) {
+ ft.addToBackStack(tag);
+ }
+ ft.replace(R.id.fragment_container, fragment, tag).commit();
+
+ return ft;
+ }
+
+ @Override
+ public void onActionClick(String category, int actionId) {
+ if (mHandler.hasMessages(MSG_EXECUTE_ACTION)) {
+ return;
+ }
+ executeAction(category, actionId);
+ }
+
+ protected void executeActionWithDelay(Runnable action, int delayMs) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_EXECUTE_ACTION, action), delayMs);
+ }
+
+ // Override this method if the inherited class wants to handle the action.
+ protected void executeAction(String category, int actionId) { }
+
+ /**
+ * Returns the duration of the shared element transition.
+ *
+ * <p>It's (exit transition) + (delayed animation) + (enter transition).
+ */
+ private long getSharedElementTransitionDuration() {
+ return (mFragmentTransitionDuration + SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS) * 2;
+ }
+
+ private static class SetupActivityHandler extends WeakHandler<SetupActivity> {
+ SetupActivityHandler(SetupActivity activity) {
+ // Should run on main thread because onAc3SupportChanged will be called on main thread.
+ super(Looper.getMainLooper(), activity);
+ }
+
+ @Override
+ protected void handleMessage(Message msg, @NonNull SetupActivity activity) {
+ if (msg.what == MSG_EXECUTE_ACTION) {
+ ((Runnable) msg.obj).run();
+ }
+ }
+ }
+}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupFragment.java b/common/src/com/android/tv/common/ui/setup/SetupFragment.java
index 0ae96d63..df7256d3 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupFragment.java
@@ -20,6 +20,7 @@ import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,14 +42,54 @@ public abstract class SetupFragment extends Fragment {
value = {FRAGMENT_ENTER_TRANSITION, FRAGMENT_EXIT_TRANSITION,
FRAGMENT_REENTER_TRANSITION, FRAGMENT_RETURN_TRANSITION})
public @interface FragmentTransitionType {}
- protected static final int FRAGMENT_ENTER_TRANSITION = 0x01;
- protected static final int FRAGMENT_EXIT_TRANSITION = FRAGMENT_ENTER_TRANSITION << 1;
- protected static final int FRAGMENT_REENTER_TRANSITION = FRAGMENT_ENTER_TRANSITION << 2;
- protected static final int FRAGMENT_RETURN_TRANSITION = FRAGMENT_ENTER_TRANSITION << 3;
+ public static final int FRAGMENT_ENTER_TRANSITION = 0x01;
+ public static final int FRAGMENT_EXIT_TRANSITION = FRAGMENT_ENTER_TRANSITION << 1;
+ public static final int FRAGMENT_REENTER_TRANSITION = FRAGMENT_ENTER_TRANSITION << 2;
+ public static final int FRAGMENT_RETURN_TRANSITION = FRAGMENT_ENTER_TRANSITION << 3;
+
+ private OnActionClickListener mOnActionClickListener;
+
+ private boolean mEnterTransitionRunning;
+
+ private TransitionListener mTransitionListener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ mEnterTransitionRunning = true;
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mEnterTransitionRunning = false;
+ onEnterTransitionEnd();
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) { }
+
+ @Override
+ public void onTransitionPause(Transition transition) { }
+
+ @Override
+ public void onTransitionResume(Transition transition) { }
+ };
+
+ /**
+ * Returns {@code true} if the enter/reenter transition is running.
+ */
+ protected boolean isEnterTransitionRunning() {
+ return mEnterTransitionRunning;
+ }
+
+ /**
+ * Called when the enter/reenter transition ends.
+ */
+ protected void onEnterTransitionEnd() { }
public SetupFragment() {
setAllowEnterTransitionOverlap(false);
setAllowReturnTransitionOverlap(false);
+ enableFragmentTransition(FRAGMENT_ENTER_TRANSITION | FRAGMENT_EXIT_TRANSITION
+ | FRAGMENT_REENTER_TRANSITION | FRAGMENT_RETURN_TRANSITION);
}
@Override
@@ -62,21 +103,51 @@ public abstract class SetupFragment extends Fragment {
}
/**
+ * Returns action click listener.
+ */
+ public OnActionClickListener getOnActionClickListener() {
+ return mOnActionClickListener;
+ }
+
+ /**
+ * Sets action click listener.
+ */
+ public void setOnActionClickListener(OnActionClickListener onActionClickListener) {
+ mOnActionClickListener = onActionClickListener;
+ }
+
+ /**
* Returns the layout resource ID for this fragment.
*/
- protected abstract int getLayoutResourceId();
+ abstract protected int getLayoutResourceId();
- protected void setOnClickAction(View view, final int actionId) {
+ protected void setOnClickAction(View view, final String category, final int actionId) {
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- onActionClick(actionId);
+ onActionClick(category, actionId);
}
});
}
- protected void onActionClick(int actionId) {
- SetupActionHelper.onActionClick(this, actionId);
+ protected void onActionClick(String category, int actionId) {
+ SetupActionHelper.onActionClick(this, category, actionId);
+ }
+
+ @Override
+ public void setEnterTransition(Transition transition) {
+ super.setEnterTransition(transition);
+ if (transition != null) {
+ transition.addListener(mTransitionListener);
+ }
+ }
+
+ @Override
+ public void setReenterTransition(Transition transition) {
+ super.setReenterTransition(transition);
+ if (transition != null) {
+ transition.addListener(mTransitionListener);
+ }
}
/**
@@ -100,8 +171,7 @@ public abstract class SetupFragment extends Fragment {
/**
* Sets the transition with the given {@code slidEdge}.
*/
- protected void setFragmentTransition(@FragmentTransitionType int transitionType,
- int slideEdge) {
+ public void setFragmentTransition(@FragmentTransitionType int transitionType, int slideEdge) {
switch (transitionType) {
case FRAGMENT_ENTER_TRANSITION:
setEnterTransition(createTransition(slideEdge));
@@ -127,46 +197,32 @@ public abstract class SetupFragment extends Fragment {
}
/**
- * Sets the distance of the fragment transition.
+ * Changes the move distance of the transitions to short distance.
*/
- public void setTransitionDistance(int distance) {
- Transition transition = getEnterTransition();
- if (transition instanceof FadeAndShortSlide) {
- ((FadeAndShortSlide) transition).setDistance(distance);
- }
- transition = getExitTransition();
- if (transition instanceof FadeAndShortSlide) {
- ((FadeAndShortSlide) transition).setDistance(distance);
- }
- transition = getReenterTransition();
- if (transition instanceof FadeAndShortSlide) {
- ((FadeAndShortSlide) transition).setDistance(distance);
- }
- transition = getReturnTransition();
- if (transition instanceof FadeAndShortSlide) {
- ((FadeAndShortSlide) transition).setDistance(distance);
- }
- }
-
- /**
- * Sets the duration of the fragment transition.
- */
- public void setTransitionDuration(long duration) {
- Transition transition = getEnterTransition();
- if (transition != null) {
- transition.setDuration(duration);
+ public void setShortDistance(@FragmentTransitionType int mask) {
+ if ((mask & FRAGMENT_ENTER_TRANSITION) != 0) {
+ Transition transition = getEnterTransition();
+ if (transition instanceof FadeAndShortSlide) {
+ SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
+ }
}
- transition = getExitTransition();
- if (transition != null) {
- transition.setDuration(duration);
+ if ((mask & FRAGMENT_EXIT_TRANSITION) != 0) {
+ Transition transition = getExitTransition();
+ if (transition instanceof FadeAndShortSlide) {
+ SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
+ }
}
- transition = getReenterTransition();
- if (transition != null) {
- transition.setDuration(duration);
+ if ((mask & FRAGMENT_REENTER_TRANSITION) != 0) {
+ Transition transition = getReenterTransition();
+ if (transition instanceof FadeAndShortSlide) {
+ SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
+ }
}
- transition = getReturnTransition();
- if (transition != null) {
- transition.setDuration(duration);
+ if ((mask & FRAGMENT_RETURN_TRANSITION) != 0) {
+ Transition transition = getReturnTransition();
+ if (transition instanceof FadeAndShortSlide) {
+ SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
+ }
}
}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
index 65575adc..aa912a97 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
@@ -24,8 +24,8 @@ import android.support.v17.leanback.widget.VerticalGridView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.LinearLayout;
import com.android.tv.common.R;
@@ -45,37 +45,31 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment {
Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
Bundle arguments = getArguments();
- view.findViewById(R.id.action_fragment).setPadding(0, 0, 0, 0);
+ view.findViewById(R.id.action_fragment_root).setPadding(0, 0, 0, 0);
+ LinearLayout.LayoutParams guidanceLayoutParams = (LinearLayout.LayoutParams)
+ view.findViewById(R.id.content_fragment).getLayoutParams();
+ guidanceLayoutParams.weight = 0;
if (arguments != null && arguments.getBoolean(KEY_THREE_PANE, false)) {
- boolean isRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
// Content fragment.
- LayoutParams layoutParams = view.findViewById(R.id.content_fragment).getLayoutParams();
- layoutParams.width = getResources().getDimensionPixelOffset(
- R.dimen.setup_guidedstep_guidance_section_width_3pane);
+ guidanceLayoutParams.width = getResources().getDimensionPixelOffset(
+ R.dimen.setup_guidedstep_guidance_section_width_3pane);
int doneButtonWidth = getResources().getDimensionPixelOffset(
R.dimen.setup_done_button_container_width);
- // Guided actions selector.
- int endMargin = getResources().getDimensionPixelOffset(
- R.dimen.setup_guidedactions_selector_margin_end);
+ // Guided actions list
+ View list = view.findViewById(R.id.guidedactions_list);
+ View list2 = view.findViewById(R.id.guidedactions_list2);
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) view.findViewById(
- R.id.guidedactions_selector).getLayoutParams();
- if (isRtl) {
- marginLayoutParams.leftMargin = endMargin + doneButtonWidth;
+ R.id.guidedactions_list).getLayoutParams();
+ // Use content view to check layout direction while view is being created.
+ if (getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR) {
+ marginLayoutParams.rightMargin = doneButtonWidth;
} else {
- marginLayoutParams.rightMargin = endMargin + doneButtonWidth;
- }
- // Guided actions list
- marginLayoutParams = (MarginLayoutParams) view.findViewById(R.id.guidedactions_list)
- .getLayoutParams();
- if (isRtl) {
marginLayoutParams.leftMargin = doneButtonWidth;
- } else {
- marginLayoutParams.rightMargin = doneButtonWidth;
}
} else {
// Content fragment.
- LayoutParams layoutParams = view.findViewById(R.id.content_fragment).getLayoutParams();
- layoutParams.width = getResources().getDimensionPixelOffset(
+ guidanceLayoutParams.width = getResources().getDimensionPixelOffset(
R.dimen.setup_guidedstep_guidance_section_width_2pane);
}
// gridView Alignment
@@ -91,6 +85,8 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment {
ViewGroup group = (ViewGroup) view.findViewById(R.id.content_frame);
group.setClipChildren(false);
group.setClipToPadding(false);
+ // Workaround b/26205201
+ view.findViewById(R.id.guidedactions_list2).setFocusable(false);
return view;
}
@@ -110,13 +106,20 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment {
};
}
+ abstract protected String getActionCategory();
+
@Override
public void onGuidedActionClicked(GuidedAction action) {
- SetupActionHelper.onActionClick(this, (int) action.getId());
+ SetupActionHelper.onActionClick(this, getActionCategory(), (int) action.getId());
}
@Override
protected void onProvideFragmentTransitions() {
// Don't use the fragment transition defined in GuidedStepFragment.
}
+
+ @Override
+ public boolean isFocusOutEndAllowed() {
+ return true;
+ }
}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
index fa946ae3..fea9bf4a 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
@@ -28,12 +28,7 @@ import com.android.tv.common.R;
* A fragment for channel source info/setup.
*/
public abstract class SetupMultiPaneFragment extends SetupFragment {
- public static final int ACTION_DONE = 1;
-
- public SetupMultiPaneFragment() {
- enableFragmentTransition(FRAGMENT_ENTER_TRANSITION | FRAGMENT_EXIT_TRANSITION
- | FRAGMENT_REENTER_TRANSITION | FRAGMENT_RETURN_TRANSITION);
- }
+ public static final int ACTION_DONE = Integer.MAX_VALUE;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -43,10 +38,12 @@ public abstract class SetupMultiPaneFragment extends SetupFragment {
getChildFragmentManager().beginTransaction()
.replace(R.id.guided_step_fragment_container, contentFragment).commit();
if (needsDoneButton()) {
- setOnClickAction(view.findViewById(R.id.button_done), ACTION_DONE);
+ setOnClickAction(view.findViewById(R.id.button_done), getActionCategory(), ACTION_DONE);
} else {
View doneButtonContainer = view.findViewById(R.id.done_button_container);
- if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+ // Use content view to check layout direction while view is being created.
+ if (getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR) {
((MarginLayoutParams) doneButtonContainer.getLayoutParams()).rightMargin =
-getResources().getDimensionPixelOffset(
R.dimen.setup_done_button_container_width);
@@ -67,6 +64,8 @@ public abstract class SetupMultiPaneFragment extends SetupFragment {
abstract protected SetupGuidedStepFragment onCreateContentFragment();
+ abstract protected String getActionCategory();
+
protected boolean needsDoneButton() {
return true;
}
@@ -78,6 +77,6 @@ public abstract class SetupMultiPaneFragment extends SetupFragment {
@Override
public int[] getSharedElementIds() {
- return new int[] {R.id.guidedactions_background, R.id.done_button_container};
+ return new int[] {R.id.action_fragment_background, R.id.done_button_container};
}
}
diff --git a/common/src/com/android/tv/common/ui/setup/SetupStep.java b/common/src/com/android/tv/common/ui/setup/SetupStep.java
deleted file mode 100644
index 7545906d..00000000
--- a/common/src/com/android/tv/common/ui/setup/SetupStep.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.android.tv.common.ui.setup;
-
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.support.annotation.Nullable;
-
-/**
- * An interface for the setup step.
- */
-public abstract class SetupStep {
- private final SetupStep mPreviousStep;
- private final int mPreviousBackStackRecordCount;
- private Fragment mFragment;
-
- public SetupStep(FragmentManager fragmentManager, @Nullable SetupStep previousStep) {
- mPreviousStep = previousStep;
- mPreviousBackStackRecordCount = fragmentManager.getBackStackEntryCount();
- }
-
- /**
- * Creates and Returns a fragment for this step.
- */
- public Fragment createFragment() {
- mFragment = onCreateFragment();
- return mFragment;
- }
-
- /**
- * Returns fragment to represent this step.
- */
- protected abstract Fragment onCreateFragment();
-
- /**
- * Executes the given action.
- */
- public abstract void executeAction(int actionId);
-
- /**
- * Returns the back stack record count at the moment when this step starts.
- */
- public int getPreviousBackStackRecordCount() {
- return mPreviousBackStackRecordCount;
- }
-
- /**
- * Returns the previous step.
- */
- @Nullable
- public SetupStep getPreviousStep() {
- return mPreviousStep;
- }
-
- /**
- * Returns the fragment which represents this step.
- */
- public Fragment getFragment() {
- return mFragment;
- }
-}
diff --git a/common/src/com/android/tv/common/ui/setup/SteppedSetupActivity.java b/common/src/com/android/tv/common/ui/setup/SteppedSetupActivity.java
deleted file mode 100644
index 984c6c7f..00000000
--- a/common/src/com/android/tv/common/ui/setup/SteppedSetupActivity.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.android.tv.common.ui.setup;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager.OnBackStackChangedListener;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.transition.Transition;
-import android.transition.TransitionInflater;
-import android.view.View;
-
-import com.android.tv.common.R;
-import com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
-
-/**
- * Stepped setup activity for onboarding screens or setup activity for TIS.
- *
- * <p>The inherited class should add theme {@code Theme.Setup.GuidedStep} to its definition in
- * AndroidManifest.xml.
- */
-public abstract class SteppedSetupActivity extends Activity implements OnActionClickListener {
- private boolean mStartedInitialStep = false;
- private SetupStep mStep;
- private long mFragmentTransitionDuration;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_stepped_setup);
- startInitialStep();
- getFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {
- @Override
- public void onBackStackChanged() {
- if (mStep != null) {
- // Need to change step to the previous one if the current step is popped from
- // the back stack.
- if (getFragmentManager().getBackStackEntryCount()
- <= mStep.getPreviousBackStackRecordCount()) {
- mStep = mStep.getPreviousStep();
- }
- }
- }
- });
- mFragmentTransitionDuration = getResources().getInteger(
- R.integer.setup_fragment_transition_duration);
- SetupAnimationHelper.setFragmentTransitionDuration(mFragmentTransitionDuration);
- SetupAnimationHelper.setFragmentTransitionDistance(getResources().getDimensionPixelOffset(
- R.dimen.setup_fragment_transition_distance));
- }
-
- /**
- * Returns the current step.
- */
- public SetupStep getCurrentStep() {
- return mStep;
- }
-
- /**
- * The inherited class should provide the initial step.
- *
- * <p>If this method returns {@code null} during {@link #onCreate}, then call
- * {@link #startInitialStep} explicitly later with non null initial setup step.
- *
- * @see SetupStep
- */
- protected abstract SetupStep onCreateInitialStep();
-
- /**
- * Starts the initial step.
- *
- * <p>The inherited class can call this method later explicitly if it doesn't want the initial
- * step to be started in onCreate().
- *
- * @see SetupStep
- */
- protected void startInitialStep() {
- if (mStartedInitialStep) {
- return;
- }
- SetupStep step = onCreateInitialStep();
- if (step != null) {
- startStep(step, false);
- mStartedInitialStep = true;
- }
- }
-
- /**
- * Starts next step.
- */
- protected FragmentTransaction startStep(SetupStep step, boolean addToBackStack) {
- mStep = step;
- Fragment fragment = step.createFragment();
- FragmentTransaction ft = getFragmentManager().beginTransaction();
- if (fragment instanceof SetupFragment) {
- int[] sharedElements = ((SetupFragment) fragment).getSharedElementIds();
- if (sharedElements != null && sharedElements.length > 0) {
- Transition sharedTransition = TransitionInflater.from(this)
- .inflateTransition(R.transition.transition_action_background);
- sharedTransition.setDuration(getSharedElementTransitionDuration());
- SetupAnimationHelper.applyAnimationTimeScale(sharedTransition);
- fragment.setSharedElementEnterTransition(sharedTransition);
- fragment.setSharedElementReturnTransition(sharedTransition);
- for (int id : sharedElements) {
- View sharedView = findViewById(id);
- if (sharedView != null) {
- ft.addSharedElement(sharedView, sharedView.getTransitionName());
- }
- }
- }
- }
- if (addToBackStack) {
- ft.addToBackStack(null);
- }
- ft.replace(R.id.fragment_container, fragment).commit();
-
- return ft;
- }
-
- @Override
- public void onActionClick(int actionId) {
- mStep.executeAction(actionId);
- }
-
- /**
- * Returns the duration of the shared element transition.
- *
- * <p>It's (exit transition) + (delayed animation) + (enter transition).
- */
- private long getSharedElementTransitionDuration() {
- return (mFragmentTransitionDuration + SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS) * 2;
- }
-}
diff --git a/common/src/com/android/tv/common/ui/setup/animation/CustomTransition.java b/common/src/com/android/tv/common/ui/setup/animation/CustomTransition.java
deleted file mode 100644
index 58d9b695..00000000
--- a/common/src/com/android/tv/common/ui/setup/animation/CustomTransition.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.android.tv.common.ui.setup.animation;
-
-import android.animation.Animator;
-import android.transition.Transition;
-import android.transition.TransitionValues;
-import android.view.ViewGroup;
-
-/**
- * Simple custom transition.
- */
-public class CustomTransition extends Transition {
- private CustomTransitionProvider mTransitionProvider;
-
- public CustomTransition(CustomTransitionProvider transitionProvider) {
- mTransitionProvider = transitionProvider;
- }
-
- @Override
- public void captureStartValues(TransitionValues transitionValues) {
- }
-
- @Override
- public void captureEndValues(TransitionValues transitionValues) {
- }
-
- @Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- Animator animator;
- if (startValues != null) {
- animator = mTransitionProvider.onDisappear(sceneRoot, startValues.view, startValues,
- endValues);
- } else {
- animator = mTransitionProvider.onAppear(sceneRoot, endValues.view, startValues,
- endValues);
- }
- return animator == null ? null : SetupAnimationHelper.applyAnimationTimeScale(animator);
- }
-}
diff --git a/common/src/com/android/tv/common/ui/setup/animation/CustomTransitionProvider.java b/common/src/com/android/tv/common/ui/setup/animation/CustomTransitionProvider.java
deleted file mode 100644
index 5f492503..00000000
--- a/common/src/com/android/tv/common/ui/setup/animation/CustomTransitionProvider.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.android.tv.common.ui.setup.animation;
-
-import android.animation.Animator;
-import android.transition.TransitionValues;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Provides custom fragment transition animation.
- */
-public interface CustomTransitionProvider {
- /**
- * Create appearing animator.
- *
- * @see android.transition.Visibility#onAppear
- */
- Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
- TransitionValues endValues);
-
- /**
- * Create disappearing animator.
- *
- * @see android.transition.Visibility#onDisappear
- */
- Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
- TransitionValues endValues);
-}
-
diff --git a/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java b/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java
index 0bd9f7b2..28ab97de 100644
--- a/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java
+++ b/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java
@@ -26,9 +26,15 @@ import android.transition.Visibility;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
/**
* Execute horizontal slide of 1/4 width and fade (to workaround bug 23718734)
*/
@@ -76,12 +82,15 @@ public class FadeAndShortSlide extends Visibility {
}
};
+ private static final ViewPositionComparator sViewPositionComparator =
+ new ViewPositionComparator();
+
+ private int mSlideEdge;
private CalculateSlide mSlideCalculator = sCalculateEnd;
private Visibility mFade = new Fade();
// TODO: Consider using TransitionPropagation.
private int[] mParentIdsForDelay;
- private boolean mDelayChildFound;
private int mDistance = DEFAULT_DISTANCE;
public FadeAndShortSlide() {
@@ -110,16 +119,23 @@ public class FadeAndShortSlide extends Visibility {
transitionValues.values.put(PROPNAME_SCREEN_POSITION, position);
}
- private int getDelayOrder(View view) {
+ private int getDelayOrder(View view, boolean appear) {
if (mParentIdsForDelay == null) {
return -1;
}
- View parentForDelay = findParentForDelay(view);
+ final View parentForDelay = findParentForDelay(view);
if (parentForDelay == null || !(parentForDelay instanceof ViewGroup)) {
return -1;
}
- mDelayChildFound = false;
- return getTransitionTargetIndex((ViewGroup) parentForDelay, view, 0);
+ List<View> transitionTargets = new ArrayList<>();
+ getTransitionTargets((ViewGroup) parentForDelay, transitionTargets);
+ sViewPositionComparator.mParentForDelay = parentForDelay;
+ sViewPositionComparator.mIsLtr = view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
+ sViewPositionComparator.mToLeft = sViewPositionComparator.mIsLtr
+ ? mSlideEdge == (appear ? Gravity.END : Gravity.START)
+ : mSlideEdge == (appear ? Gravity.START : Gravity.END);
+ Collections.sort(transitionTargets, sViewPositionComparator);
+ return transitionTargets.indexOf(view);
}
private View findParentForDelay(View view) {
@@ -145,28 +161,16 @@ public class FadeAndShortSlide extends Visibility {
return false;
}
- private int getTransitionTargetIndex(ViewGroup parent, View view, int delayIndex) {
- int checked = 0;
+ private void getTransitionTargets(ViewGroup parent, List<View> transitionTargets) {
int count = parent.getChildCount();
for (int i = 0; i < count; ++i) {
View child = parent.getChildAt(i);
if (child instanceof ViewGroup && !((ViewGroup) child).isTransitionGroup()) {
- int result = getTransitionTargetIndex((ViewGroup) child, view, delayIndex);
- if (mDelayChildFound) {
- return delayIndex + result;
- }
- delayIndex += result;
- checked += result;
+ getTransitionTargets((ViewGroup) child, transitionTargets);
} else {
- if (child == view) {
- mDelayChildFound = true;
- return delayIndex;
- }
- ++delayIndex;
- ++checked;
+ transitionTargets.add(child);
}
}
- return checked;
}
@Override
@@ -174,7 +178,7 @@ public class FadeAndShortSlide extends Visibility {
super.captureStartValues(transitionValues);
mFade.captureStartValues(transitionValues);
captureValues(transitionValues);
- int delayIndex = getDelayOrder(transitionValues.view);
+ int delayIndex = getDelayOrder(transitionValues.view, false);
if (delayIndex > 0) {
transitionValues.values.put(PROPNAME_DELAY,
delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS);
@@ -186,7 +190,7 @@ public class FadeAndShortSlide extends Visibility {
super.captureEndValues(transitionValues);
mFade.captureEndValues(transitionValues);
captureValues(transitionValues);
- int delayIndex = getDelayOrder(transitionValues.view);
+ int delayIndex = getDelayOrder(transitionValues.view, true);
if (delayIndex > 0) {
transitionValues.values.put(PROPNAME_DELAY,
delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS);
@@ -194,6 +198,7 @@ public class FadeAndShortSlide extends Visibility {
}
public void setSlideEdge(int slideEdge) {
+ mSlideEdge = slideEdge;
switch (slideEdge) {
case Gravity.START:
mSlideCalculator = sCalculateStart;
@@ -272,8 +277,7 @@ public class FadeAndShortSlide extends Visibility {
@Override
public Transition clone() {
- FadeAndShortSlide clone = null;
- clone = (FadeAndShortSlide) super.clone();
+ FadeAndShortSlide clone = (FadeAndShortSlide) super.clone();
clone.mFade = (Visibility) mFade.clone();
return clone;
}
@@ -291,4 +295,78 @@ public class FadeAndShortSlide extends Visibility {
public void setDistance(int distance) {
mDistance = distance;
}
+
+ private static class ViewPositionComparator implements Comparator<View> {
+ View mParentForDelay;
+ boolean mIsLtr;
+ boolean mToLeft;
+
+ @Override
+ public int compare(View lhs, View rhs) {
+ int start1;
+ int start2;
+ if (mIsLtr) {
+ start1 = getRelativeLeft(lhs, mParentForDelay);
+ start2 = getRelativeLeft(rhs, mParentForDelay);
+ } else {
+ start1 = getRelativeRight(lhs, mParentForDelay);
+ start2 = getRelativeRight(rhs, mParentForDelay);
+ }
+ if (mToLeft) {
+ if (start1 > start2) {
+ return 1;
+ } else if (start1 < start2) {
+ return -1;
+ }
+ } else {
+ if (start1 > start2) {
+ return -1;
+ } else if (start1 < start2) {
+ return 1;
+ }
+ }
+ int top1 = getRelativeTop(lhs, mParentForDelay);
+ int top2 = getRelativeTop(rhs, mParentForDelay);
+ return Integer.compare(top1, top2);
+ }
+
+ private int getRelativeLeft(View child, View ancestor) {
+ ViewParent parent = child.getParent();
+ int left = child.getLeft();
+ while (parent instanceof View) {
+ if (parent == ancestor) {
+ break;
+ }
+ left += ((View) parent).getLeft();
+ parent = parent.getParent();
+ }
+ return left;
+ }
+
+ private int getRelativeRight(View child, View ancestor) {
+ ViewParent parent = child.getParent();
+ int right = child.getRight();
+ while (parent instanceof View) {
+ if (parent == ancestor) {
+ break;
+ }
+ right += ((View) parent).getLeft();
+ parent = parent.getParent();
+ }
+ return right;
+ }
+
+ private int getRelativeTop(View child, View ancestor) {
+ ViewParent parent = child.getParent();
+ int top = child.getTop();
+ while (parent instanceof View) {
+ if (parent == ancestor) {
+ break;
+ }
+ top += ((View) parent).getTop();
+ parent = parent.getParent();
+ }
+ return top;
+ }
+ }
}
diff --git a/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java b/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java
index 9d2efcd0..0c5849ea 100644
--- a/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java
+++ b/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java
@@ -21,46 +21,60 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
+import android.content.Context;
import android.transition.Transition;
import android.transition.TransitionSet;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
+import com.android.tv.common.R;
+
/**
* A helper class for setup animation.
*/
public final class SetupAnimationHelper {
public static final long DELAY_BETWEEN_SIBLINGS_MS = applyAnimationTimeScale(33);
- private static final float ANIMATION_SCALE = 1.0f;
+ private static final float ANIMATION_TIME_SCALE = 1.0f;
+ private static boolean sInitialized;
private static long sFragmentTransitionDuration;
- private static int sFragmentTransitionDistance;
+ private static int sFragmentTransitionLongDistance;
+ private static int sFragmentTransitionShortDistance;
private SetupAnimationHelper() { }
/**
- * Sets the duration of the fragment transition.
+ * Load initial parameters. This method should be called before using this class.
*/
- public static void setFragmentTransitionDuration(long duration) {
- sFragmentTransitionDuration = duration;
+ public static void initialize(Context context) {
+ sFragmentTransitionDuration = context.getResources()
+ .getInteger(R.integer.setup_fragment_transition_duration);
+ sFragmentTransitionLongDistance = context.getResources()
+ .getDimensionPixelOffset(R.dimen.setup_fragment_transition_long_distance);
+ sFragmentTransitionShortDistance = context.getResources()
+ .getDimensionPixelOffset(R.dimen.setup_fragment_transition_short_distance);
+ sInitialized = true;
}
- /**
- * Sets the distance of the fragment transition.
- */
- public static void setFragmentTransitionDistance(int distance) {
- sFragmentTransitionDistance = distance;
+ private static void checkInitialized() {
+ if (!sInitialized) {
+ throw new IllegalStateException("SetupAnimationHelper not initialized");
+ }
}
public static class TransitionBuilder {
private int mSlideEdge = Gravity.START;
- private int mDistance = sFragmentTransitionDistance;
+ private int mDistance = sFragmentTransitionLongDistance;
private long mDuration = sFragmentTransitionDuration;
private int[] mParentIdForDelay;
private int[] mExcludeIds;
+ public TransitionBuilder() {
+ checkInitialized();
+ }
+
/**
* Sets the edge of the slide transition.
*
@@ -114,6 +128,22 @@ public final class SetupAnimationHelper {
}
/**
+ * Changes the move distance of the {@code transition} to long distance.
+ */
+ public static void setLongDistance(FadeAndShortSlide transition) {
+ checkInitialized();
+ transition.setDistance(sFragmentTransitionLongDistance);
+ }
+
+ /**
+ * Changes the move distance of the {@code transition} to short distance.
+ */
+ public static void setShortDistance(FadeAndShortSlide transition) {
+ checkInitialized();
+ transition.setDistance(sFragmentTransitionShortDistance);
+ }
+
+ /**
* Applies the animation scale to the given {@code animator}.
*/
public static Animator applyAnimationTimeScale(Animator animator) {
@@ -123,9 +153,9 @@ public final class SetupAnimationHelper {
}
}
if (animator.getDuration() > 0) {
- animator.setDuration((long) (animator.getDuration() * ANIMATION_SCALE));
+ animator.setDuration((long) (animator.getDuration() * ANIMATION_TIME_SCALE));
}
- animator.setStartDelay((long) (animator.getStartDelay() * ANIMATION_SCALE));
+ animator.setStartDelay((long) (animator.getStartDelay() * ANIMATION_TIME_SCALE));
return animator;
}
@@ -141,9 +171,9 @@ public final class SetupAnimationHelper {
}
}
if (transition.getDuration() > 0) {
- transition.setDuration((long) (transition.getDuration() * ANIMATION_SCALE));
+ transition.setDuration((long) (transition.getDuration() * ANIMATION_TIME_SCALE));
}
- transition.setStartDelay((long) (transition.getStartDelay() * ANIMATION_SCALE));
+ transition.setStartDelay((long) (transition.getStartDelay() * ANIMATION_TIME_SCALE));
return transition;
}
@@ -151,11 +181,11 @@ public final class SetupAnimationHelper {
* Applies the animation scale to the given {@code time}.
*/
public static long applyAnimationTimeScale(long time) {
- return (long) (time * ANIMATION_SCALE);
+ return (long) (time * ANIMATION_TIME_SCALE);
}
/**
- * Returns an animator which animate the source image of the {@link ImageView}.
+ * Returns an animator which animates the source image of the {@link ImageView}.
*
* <p>The frame rate is 60 fps.
*/
@@ -164,7 +194,7 @@ public final class SetupAnimationHelper {
}
/**
- * Returns an animator which animate the source image of the {@link ImageView} with start delay.
+ * Returns an animator which animates the source image of the {@link ImageView} with start delay.
*
* <p>The frame rate is 60 fps.
*/
@@ -192,9 +222,10 @@ public final class SetupAnimationHelper {
* @param makeVisibleAfterAnimation If {@code true}, the view will become visible after the
* animation ends.
*/
- public static Animator createFadeOutAnimator(final View view, int duration,
+ public static Animator createFadeOutAnimator(final View view, long duration,
boolean makeVisibleAfterAnimation) {
- ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f);
+ ObjectAnimator animator =
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f).setDuration(duration);
if (makeVisibleAfterAnimation) {
animator.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/common/src/com/android/tv/common/ui/setup/leanback/OnboardingFragment.java b/common/src/com/android/tv/common/ui/setup/leanback/OnboardingFragment.java
new file mode 100644
index 00000000..adbd98c2
--- /dev/null
+++ b/common/src/com/android/tv/common/ui/setup/leanback/OnboardingFragment.java
@@ -0,0 +1,531 @@
+/*
+ * 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.android.tv.common.ui.setup.leanback;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnKeyListener;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.tv.common.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An OnboardingFragment provides a common and simple way to build onboarding screen for
+ * applications.
+ * <p>
+ * <h3>Building the screen</h3>
+ * The view structure of onboarding screen is composed of the common parts and custom parts. The
+ * common parts are composed of title, description and page navigator and the custom parts are
+ * composed of background, contents and foreground.
+ * <p>
+ * To build the screen views, the inherited class should override:
+ * <ul>
+ * <li>{@link #onCreateBackgroundView} to provide the background view. Background view has the same
+ * size as the screen and the lowest z-order.</li>
+ * <li>{@link #onCreateContentView} to provide the contents view. The content view is located in
+ * the content area at the center of the screen.</li>
+ * <li>{@link #onCreateForegroundView} to provide the foreground view. Foreground view has the same
+ * size as the screen and the highest z-order</li>
+ * </ul>
+ * <p>
+ * Each of these methods can return {@code null} if the application doesn't want to provide it.
+ * <p>
+ * <h3>Page information</h3>
+ * The onboarding screen may have several pages which explain the functionality of the application.
+ * The inherited class should provide the page information by overriding the methods:
+ * <p>
+ * <ul>
+ * <li>{@link #getPageCount} to provide the number of pages.</li>
+ * <li>{@link #getPageTitle} to provide the title of the page.</li>
+ * <li>{@link #getPageDescription} to provide the description of the page.</li>
+ * </ul>
+ * <p>
+ * <h3><a name="logoAnimation">Logo Splash Animation</a></h3>
+ * When onboarding screen appears, the logo splash animation is played by default. The animation
+ * fades in the logo image, pauses in a few seconds and fades it out. To support this animation with
+ * its own logo image, the inherited class should override the following method.
+ * <p>
+ * <ul>
+ * <li>{@link #getLogoResourceId()}</li>
+ * </ul>
+ * <p>
+ * <h3>Animation</h3>
+ * This page has three kinds of animations:
+ * <p>
+ * <ul>
+ * <li><b>Logo splash animation</b> which starts as soon as onboarding screen is shown as described
+ * in <a href="#logoAnimation">Logo Splash Animation</a>.</li>
+ * <li><b>Page enter animation</b> which runs just after the logo animation finishes. The
+ * application can run the animations of their custom views by overriding
+ * {@link #onStartEnterAnimation}.</li>
+ * <li><b>Page change animation</b> which runs when the page changes. The pages can move backward or
+ * forward direction and the application can start the page change animations by overriding
+ * {@link #onStartPageChangeAnimation}.</li>
+ * </ul>
+ * <p>
+ * <h3>Finishing the screen</h3>
+ * <p>
+ * If the user finishes the onboarding screen after navigating all the pages,
+ * {@link #onFinishFragment} is called. The inherited class can override this method to show another
+ * fragment or activity, or just remove this fragment.
+ *
+ * @hide
+ */
+abstract public class OnboardingFragment extends Fragment {
+ private static final long LOGO_SPLASH_PAUSE_DURATION_MS = 1333;
+ private static final long START_DELAY_TITLE_MS = 33;
+ private static final long START_DELAY_DESCRIPTION_MS = 33;
+
+ private static final long HEADER_ANIMATION_DURATION_MS = 417;
+ private static final long DESCRIPTION_START_DELAY_MS = 33;
+ private static final long HEADER_APPEAR_DELAY_MS = 500;
+ private static final int SLIDE_DISTANCE = 60;
+
+ private static int sSlideDistance;
+
+ private static final TimeInterpolator HEADER_APPEAR_INTERPOLATOR = new DecelerateInterpolator();
+ private static final TimeInterpolator HEADER_DISAPPEAR_INTERPOLATOR
+ = new AccelerateInterpolator();
+
+ private PagingIndicator mPageIndicator;
+ private View mStartButton;
+ private ImageView mLogoView;
+ private TextView mTitleView;
+ private TextView mDescriptionView;
+
+ private boolean mEnterTransitionFinished;
+ private int mCurrentPageIndex;
+
+ private AnimatorSet mAnimator;
+
+ /**
+ * Called to have the inherited class create its own start animation. The start animation runs
+ * after logo splash animation ends.
+ */
+ abstract protected void onStartEnterAnimation();
+
+ private final OnClickListener mOnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (!mEnterTransitionFinished) {
+ // Do not change page until the enter transition finishes.
+ return;
+ }
+ if (mCurrentPageIndex == getPageCount() - 1) {
+ onFinishFragment();
+ } else {
+ ++mCurrentPageIndex;
+ onPageChanged(mCurrentPageIndex - 1);
+ }
+ }
+ };
+
+ private final OnKeyListener mOnKeyListener = new OnKeyListener() {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (!mEnterTransitionFinished) {
+ // Ignore key event until the enter transition finishes.
+ return keyCode != KeyEvent.KEYCODE_BACK;
+ }
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ return false;
+ }
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ if (mCurrentPageIndex == 0) {
+ return false;
+ }
+ // pass through
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (mCurrentPageIndex > 0) {
+ --mCurrentPageIndex;
+ onPageChanged(mCurrentPageIndex + 1);
+ }
+ return true;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (mCurrentPageIndex < getPageCount() - 1) {
+ ++mCurrentPageIndex;
+ onPageChanged(mCurrentPageIndex - 1);
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, final ViewGroup container,
+ Bundle savedInstanceState) {
+ ViewGroup view = (ViewGroup) inflater.inflate(R.layout.lb_onboarding_fragment, container,
+ false);
+ mPageIndicator = (PagingIndicator) view.findViewById(R.id.page_indicator);
+ mPageIndicator.setPageCount(getPageCount());
+ mPageIndicator.setOnClickListener(mOnClickListener);
+ mPageIndicator.setOnKeyListener(mOnKeyListener);
+ mStartButton = view.findViewById(R.id.button_start);
+ mStartButton.setOnClickListener(mOnClickListener);
+ mStartButton.setOnKeyListener(mOnKeyListener);
+ mLogoView = (ImageView) view.findViewById(R.id.logo);
+ mLogoView.setImageResource(getLogoResourceId());
+ mTitleView = (TextView) view.findViewById(R.id.title);
+ mTitleView.setText(getPageTitle(0));
+ mDescriptionView = (TextView) view.findViewById(R.id.description);
+ mDescriptionView.setText(getPageDescription(0));
+ if (sSlideDistance == 0) {
+ sSlideDistance = (int) (SLIDE_DISTANCE * getActivity().getResources()
+ .getDisplayMetrics().scaledDensity);
+ }
+ mCurrentPageIndex = 0;
+ mPageIndicator.onPageSelected(0, false);
+ view.requestFocus();
+ if (getLogoResourceId() != 0) {
+ container.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ container.getViewTreeObserver().removeOnPreDrawListener(this);
+ startLogoAnimation();
+ return true;
+ }
+ });
+ } else {
+ onLogoAnimationFinished();
+ }
+ return view;
+ }
+
+ private void startLogoAnimation() {
+ mLogoView.setVisibility(View.VISIBLE);
+ Animator inAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_logo_enter);
+ Animator outAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_logo_exit);
+ outAnimator.setStartDelay(LOGO_SPLASH_PAUSE_DURATION_MS);
+ AnimatorSet animator = new AnimatorSet();
+ animator.playSequentially(inAnimator, outAnimator);
+ animator.setTarget(mLogoView);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mEnterTransitionFinished = true;
+ if (getActivity() != null) {
+ onLogoAnimationFinished();
+ onStartEnterAnimation();
+ }
+ }
+ });
+ animator.start();
+ }
+
+ private void onLogoAnimationFinished() {
+ mLogoView.setVisibility(View.GONE);
+ // Create custom views.
+ LayoutInflater inflater = LayoutInflater.from(getActivity());
+ ViewGroup backgroundContainer = (ViewGroup) getView().findViewById(
+ R.id.background_container);
+ View background = onCreateBackgroundView(inflater, backgroundContainer);
+ if (background != null) {
+ backgroundContainer.setVisibility(View.VISIBLE);
+ backgroundContainer.addView(background);
+ }
+ ViewGroup contentContainer = (ViewGroup) getView().findViewById(R.id.content_container);
+ View content = onCreateContentView(inflater, contentContainer);
+ if (content != null) {
+ contentContainer.setVisibility(View.VISIBLE);
+ contentContainer.addView(content);
+ }
+ ViewGroup foregroundContainer = (ViewGroup) getView().findViewById(
+ R.id.foreground_container);
+ View foreground = onCreateForegroundView(inflater, foregroundContainer);
+ if (foreground != null) {
+ foregroundContainer.setVisibility(View.VISIBLE);
+ foregroundContainer.addView(foreground);
+ }
+ // Make views visible which were invisible while logo animation is running.
+ getView().findViewById(R.id.page_container).setVisibility(View.VISIBLE);
+ getView().findViewById(R.id.content_container).setVisibility(View.VISIBLE);
+
+ List<Animator> animators = new ArrayList<>();
+ Animator animator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_page_indicator_enter);
+ if (getPageCount() <= 1) {
+ // Start button
+ mStartButton.setVisibility(View.VISIBLE);
+ animator.setTarget(mStartButton);
+ } else {
+ // Page indicator
+ mPageIndicator.setVisibility(View.VISIBLE);
+ animator.setTarget(mPageIndicator);
+ }
+ animators.add(animator);
+ // Header title
+ View view = getActivity().findViewById(R.id.title);
+ view.setAlpha(0);
+ animator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_title_enter);
+ animator.setStartDelay(START_DELAY_TITLE_MS);
+ animator.setTarget(view);
+ animators.add(animator);
+ // Header description
+ view = getActivity().findViewById(R.id.description);
+ view.setAlpha(0);
+ animator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_description_enter);
+ animator.setStartDelay(START_DELAY_DESCRIPTION_MS);
+ animator.setTarget(view);
+ animators.add(animator);
+ mAnimator = new AnimatorSet();
+ mAnimator.playTogether(animators);
+ mAnimator.start();
+ onStartEnterAnimation();
+ // Search focus and give the focus to the appropriate child which has become visible.
+ getView().requestFocus();
+ }
+
+ /**
+ * Returns the page count.
+ *
+ * @return The page count.
+ */
+ abstract protected int getPageCount();
+
+ /**
+ * Returns the title of the given page.
+ *
+ * @param pageIndex The page index.
+ *
+ * @return The title of the page.
+ */
+ abstract protected String getPageTitle(int pageIndex);
+
+ /**
+ * Returns the description of the given page.
+ *
+ * @param pageIndex The page index.
+ *
+ * @return The description of the page.
+ */
+ abstract protected String getPageDescription(int pageIndex);
+
+ /**
+ * Returns the index of the current page.
+ *
+ * @return The index of the current page.
+ */
+ protected final int getCurrentPageIndex() {
+ return mCurrentPageIndex;
+ }
+
+ /**
+ * Returns the resource ID of the splash logo image.
+ *
+ * @return The resource ID of the splash logo image.
+ */
+ abstract protected int getLogoResourceId();
+
+ /**
+ * Called to have the inherited class create background view. This is optional and the fragment
+ * which doesn't have the background view can return {@code null}. This is called inside
+ * {@link #onCreateView}.
+ *
+ * @param inflater The LayoutInflater object that can be used to inflate the views,
+ * @param container The parent view that the additional views are attached to.The fragment
+ * should not add the view by itself.
+ *
+ * @return The background view for the onboarding screen, or {@code null}.
+ */
+ @Nullable
+ abstract protected View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container);
+
+ /**
+ * Called to have the inherited class create content view. This is optional and the fragment
+ * which doesn't have the content view can return {@code null}. This is called inside
+ * {@link #onCreateView}.
+ *
+ * <p>The content view would be located at the center of the screen.
+ *
+ * @param inflater The LayoutInflater object that can be used to inflate the views,
+ * @param container The parent view that the additional views are attached to.The fragment
+ * should not add the view by itself.
+ *
+ * @return The content view for the onboarding screen, or {@code null}.
+ */
+ @Nullable
+ abstract protected View onCreateContentView(LayoutInflater inflater, ViewGroup container);
+
+ /**
+ * Called to have the inherited class create foreground view. This is optional and the fragment
+ * which doesn't need the foreground view can return {@code null}. This is called inside
+ * {@link #onCreateView}.
+ *
+ * <p>This foreground view would have the highest z-order.
+ *
+ * @param inflater The LayoutInflater object that can be used to inflate the views,
+ * @param container The parent view that the additional views are attached to.The fragment
+ * should not add the view by itself.
+ *
+ * @return The foreground view for the onboarding screen, or {@code null}.
+ */
+ @Nullable
+ abstract protected View onCreateForegroundView(LayoutInflater inflater, ViewGroup container);
+
+ /**
+ * Called when the onboarding flow finishes.
+ */
+ protected void onFinishFragment() { }
+
+ /**
+ * Called when the page changes.
+ */
+ private void onPageChanged(int previousPage) {
+ if (mAnimator != null) {
+ mAnimator.end();
+ }
+ mPageIndicator.onPageSelected(mCurrentPageIndex, true);
+
+ List<Animator> animators = new ArrayList<>();
+ // Header animation
+ Animator fadeAnimator = null;
+ if (previousPage < getCurrentPageIndex()) {
+ // sliding to left
+ animators.add(createAnimator(mTitleView, false, Gravity.START, 0));
+ animators.add(fadeAnimator = createAnimator(mDescriptionView, false, Gravity.START,
+ DESCRIPTION_START_DELAY_MS));
+ animators.add(createAnimator(mTitleView, true, Gravity.END,
+ HEADER_APPEAR_DELAY_MS));
+ animators.add(createAnimator(mDescriptionView, true, Gravity.END,
+ HEADER_APPEAR_DELAY_MS + DESCRIPTION_START_DELAY_MS));
+ } else {
+ // sliding to right
+ animators.add(createAnimator(mTitleView, false, Gravity.END, 0));
+ animators.add(fadeAnimator = createAnimator(mDescriptionView, false, Gravity.END,
+ DESCRIPTION_START_DELAY_MS));
+ animators.add(createAnimator(mTitleView, true, Gravity.START,
+ HEADER_APPEAR_DELAY_MS));
+ animators.add(createAnimator(mDescriptionView, true, Gravity.START,
+ HEADER_APPEAR_DELAY_MS + DESCRIPTION_START_DELAY_MS));
+ }
+ final int currentPageIndex = getCurrentPageIndex();
+ fadeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mTitleView.setText(getPageTitle(currentPageIndex));
+ mDescriptionView.setText(getPageDescription(currentPageIndex));
+ }
+ });
+
+ // Animator for switching between page indicator and button.
+ if (getCurrentPageIndex() == getPageCount() - 1) {
+ mStartButton.setVisibility(View.VISIBLE);
+ Animator navigatorFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_page_indicator_fade_out);
+ navigatorFadeOutAnimator.setTarget(mPageIndicator);
+ Animator buttonFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_start_button_fade_in);
+ buttonFadeInAnimator.setTarget(mStartButton);
+ animators.add(navigatorFadeOutAnimator);
+ navigatorFadeOutAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mPageIndicator.setVisibility(View.GONE);
+ }
+ });
+ animators.add(buttonFadeInAnimator);
+ } else if (previousPage == getPageCount() - 1) {
+ mPageIndicator.setVisibility(View.VISIBLE);
+ Animator navigatorFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_page_indicator_fade_in);
+ navigatorFadeInAnimator.setTarget(mPageIndicator);
+ Animator buttonFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_start_button_fade_out);
+ buttonFadeOutAnimator.setTarget(mStartButton);
+ buttonFadeOutAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mStartButton.setVisibility(View.GONE);
+ }
+ });
+ mAnimator = new AnimatorSet();
+ mAnimator.playTogether(navigatorFadeInAnimator, buttonFadeOutAnimator);
+ mAnimator.start();
+ }
+ mAnimator = new AnimatorSet();
+ mAnimator.playTogether(animators);
+ mAnimator.start();
+ onStartPageChangeAnimation(previousPage);
+ }
+
+ private Animator createAnimator(View view, boolean fadeIn, int slideDirection,
+ long startDelay) {
+ boolean isLtr = getView().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
+ boolean slideRight = (isLtr && slideDirection == Gravity.END)
+ || (!isLtr && slideDirection == Gravity.START)
+ || slideDirection == Gravity.RIGHT;
+ Animator fadeAnimator;
+ Animator slideAnimator;
+ if (fadeIn) {
+ fadeAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 0.0f, 1.0f);
+ slideAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
+ slideRight ? sSlideDistance : -sSlideDistance, 0);
+ fadeAnimator.setInterpolator(HEADER_APPEAR_INTERPOLATOR);
+ slideAnimator.setInterpolator(HEADER_APPEAR_INTERPOLATOR);
+ } else {
+ fadeAnimator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f);
+ slideAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 0,
+ slideRight ? sSlideDistance : -sSlideDistance);
+ fadeAnimator.setInterpolator(HEADER_DISAPPEAR_INTERPOLATOR);
+ slideAnimator.setInterpolator(HEADER_DISAPPEAR_INTERPOLATOR);
+ }
+ fadeAnimator.setDuration(HEADER_ANIMATION_DURATION_MS);
+ fadeAnimator.setTarget(view);
+ slideAnimator.setDuration(HEADER_ANIMATION_DURATION_MS);
+ slideAnimator.setTarget(view);
+ AnimatorSet animator = new AnimatorSet();
+ animator.playTogether(fadeAnimator, slideAnimator);
+ if (startDelay > 0) {
+ animator.setStartDelay(startDelay);
+ }
+ return animator;
+ }
+
+ /**
+ * Called to have the inherited class run its own page change animation
+ *
+ * @param previousPage The previous page.
+ */
+ abstract protected void onStartPageChangeAnimation(int previousPage);
+}
diff --git a/common/src/com/android/tv/common/ui/setup/leanback/PagingIndicator.java b/common/src/com/android/tv/common/ui/setup/leanback/PagingIndicator.java
new file mode 100644
index 00000000..e2c9be72
--- /dev/null
+++ b/common/src/com/android/tv/common/ui/setup/leanback/PagingIndicator.java
@@ -0,0 +1,377 @@
+/*
+ * 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.android.tv.common.ui.setup.leanback;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorSet;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Build;
+import android.support.annotation.ColorInt;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.tv.common.R;
+import com.android.tv.common.annotation.UsedByReflection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A page indicator with dots.
+ * @hide
+ */
+public class PagingIndicator extends View {
+ // attribute
+ private final int mDotDiameter;
+ private final int mDotRadius;
+ private final int mDotGap;
+ private final int mArrowDiameter;
+ private final int mArrowRadius;
+ private final int mArrowGap;
+ private final int mShadowRadius;
+ private Dot[] mDots;
+ // X position when the dot is selected.
+ private int[] mDotSelectedX;
+ // X position when the dot is located to the left of the selected dot.
+ private int[] mDotSelectedLeftX;
+ // X position when the dot is located to the right of the selected dot.
+ private int[] mDotSelectedRightX;
+ private int mDotCenterY;
+
+ // state
+ private int mPageCount;
+ private int mCurrentPage;
+ private int mPreviousPage;
+
+ // drawing
+ @ColorInt
+ private final int mDotFgSelectColor;
+ private final Paint mBgPaint;
+ private final Paint mFgPaint;
+ private final Animator mShowAnimator;
+ private final Animator mHideAnimator;
+ private final AnimatorSet mAnimator = new AnimatorSet();
+ private final Bitmap mArrow;
+ private final Rect mArrowRect;
+ private final float mArrowToBgRatio;
+
+ public PagingIndicator(Context context) {
+ this(context, null, 0);
+ }
+
+ public PagingIndicator(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PagingIndicator(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ Resources res = getResources();
+ mDotRadius = res.getDimensionPixelSize(R.dimen.lb_page_indicator_dot_radius);
+ mDotDiameter = mDotRadius * 2;
+ mDotGap = res.getDimensionPixelSize(R.dimen.lb_page_indicator_dot_gap);
+ mArrowGap = res.getDimensionPixelSize(R.dimen.lb_page_indicator_arrow_gap);
+ mArrowDiameter = res.getDimensionPixelSize(R.dimen.lb_page_indicator_arrow_diameter);
+ mArrowRadius = mArrowDiameter / 2;
+ mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mDotFgSelectColor = res.getColor(R.color.lb_page_indicator_arrow_background);
+ int bgColor = res.getColor(R.color.lb_page_indicator_dot);
+ int shadowColor = res.getColor(R.color.lb_page_indicator_arrow_shadow);
+ mBgPaint.setColor(bgColor);
+ mShadowRadius = res.getDimensionPixelSize(R.dimen.lb_page_indicator_arrow_shadow_radius);
+ mFgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ int shadowOffset = res.getDimensionPixelSize(R.dimen.lb_page_indicator_arrow_shadow_offset);
+ mFgPaint.setShadowLayer(mShadowRadius, shadowOffset, shadowOffset, shadowColor);
+ mArrow = BitmapFactory.decodeResource(res, R.drawable.lb_ic_nav_arrow);
+ mArrowRect = new Rect(0, 0, mArrow.getWidth(), mArrow.getHeight());
+ mArrowToBgRatio = (float) mArrow.getWidth() / (float) mArrowDiameter;
+ // Initialize animations.
+ List<Animator> animators = new ArrayList<>();
+ mShowAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.animator.lb_page_indicator_dot_show);
+ mHideAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.animator.lb_page_indicator_dot_hide);
+ animators.add(mShowAnimator);
+ animators.add(mHideAnimator);
+ mAnimator.playTogether(animators);
+ // Use software layer to show shadows.
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
+ /**
+ * Sets the page count.
+ */
+ public void setPageCount(int pages) {
+ if (pages <= 0) {
+ throw new IllegalArgumentException("The page count should be a positive integer");
+ }
+ mPageCount = pages;
+ mDots = new Dot[mPageCount];
+ for (int i = 0; i < mPageCount; ++i) {
+ mDots[i] = new Dot();
+ }
+ calculateDotPositions();
+ setSelectedPage(0);
+ }
+
+ /**
+ * Called when the page has been selected.
+ */
+ public void onPageSelected(int pageIndex, boolean withAnimation) {
+ if (mCurrentPage == pageIndex) {
+ return;
+ }
+ if (mAnimator.isStarted()) {
+ mAnimator.end();
+ }
+ mPreviousPage = mCurrentPage;
+ if (withAnimation) {
+ mHideAnimator.setTarget(mDots[mPreviousPage]);
+ mShowAnimator.setTarget(mDots[pageIndex]);
+ mAnimator.start();
+ }
+ setSelectedPage(pageIndex);
+ }
+
+ private void calculateDotPositions() {
+ int left = getPaddingLeft();
+ int top = getPaddingTop();
+ int right = getWidth() - getPaddingRight();
+ int requiredWidth = getRequiredWidth();
+ int mid = (left + right) / 2;
+ int startLeft = mid - requiredWidth / 2;
+ mDotSelectedX = new int[mPageCount];
+ mDotSelectedLeftX = new int[mPageCount];
+ mDotSelectedRightX = new int[mPageCount];
+ // mDotSelectedX[0] should be mDotSelectedLeftX[-1] + mArrowGap
+ mDotSelectedX[0] = startLeft + mDotRadius - mDotGap + mArrowGap;
+ mDotSelectedLeftX[0] = startLeft + mDotRadius;
+ mDotSelectedRightX[0] = 0;
+ for (int i = 1; i < mPageCount; i++) {
+ mDotSelectedX[i] = mDotSelectedLeftX[i - 1] + mArrowGap;
+ mDotSelectedLeftX[i] = mDotSelectedLeftX[i - 1] + mDotGap;
+ mDotSelectedRightX[i] = mDotSelectedX[i - 1] + mArrowGap;
+ }
+ mDotCenterY = top + mArrowRadius;
+ adjustDotPosition();
+ }
+
+ @VisibleForTesting
+ int getPageCount() {
+ return mPageCount;
+ }
+
+ @VisibleForTesting
+ int[] getDotSelectedX() {
+ return mDotSelectedX;
+ }
+
+ @VisibleForTesting
+ int[] getDotSelectedLeftX() {
+ return mDotSelectedLeftX;
+ }
+
+ @VisibleForTesting
+ int[] getDotSelectedRightX() {
+ return mDotSelectedRightX;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int desiredHeight = getDesiredHeight();
+ int height;
+ switch (MeasureSpec.getMode(heightMeasureSpec)) {
+ case MeasureSpec.EXACTLY:
+ height = MeasureSpec.getSize(heightMeasureSpec);
+ break;
+ case MeasureSpec.AT_MOST:
+ height = Math.min(desiredHeight, MeasureSpec.getSize(heightMeasureSpec));
+ break;
+ case MeasureSpec.UNSPECIFIED:
+ default:
+ height = desiredHeight;
+ break;
+ }
+ int desiredWidth = getDesiredWidth();
+ int width;
+ switch (MeasureSpec.getMode(widthMeasureSpec)) {
+ case MeasureSpec.EXACTLY:
+ width = MeasureSpec.getSize(widthMeasureSpec);
+ break;
+ case MeasureSpec.AT_MOST:
+ width = Math.min(desiredWidth, MeasureSpec.getSize(widthMeasureSpec));
+ break;
+ case MeasureSpec.UNSPECIFIED:
+ default:
+ width = desiredWidth;
+ break;
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
+ setMeasuredDimension(width, height);
+ calculateDotPositions();
+ }
+
+ private int getDesiredHeight() {
+ return getPaddingTop() + mArrowDiameter + getPaddingBottom() + mShadowRadius;
+ }
+
+ private int getRequiredWidth() {
+ return 2 * mDotRadius + 2 * mArrowGap + (mPageCount - 3) * mDotGap;
+ }
+
+ private int getDesiredWidth() {
+ return getPaddingLeft() + getRequiredWidth() + getPaddingRight();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ for (int i = 0; i < mPageCount; ++i) {
+ mDots[i].draw(canvas);
+ }
+ }
+
+ private void setSelectedPage(int now) {
+ if (now == mCurrentPage) {
+ return;
+ }
+
+ mCurrentPage = now;
+ adjustDotPosition();
+ }
+
+ private void adjustDotPosition() {
+ for (int i = 0; i < mCurrentPage; ++i) {
+ mDots[i].deselect();
+ mDots[i].mDirection = i == mPreviousPage ? Dot.LEFT : Dot.RIGHT;
+ mDots[i].mCenterX = mDotSelectedLeftX[i];
+ }
+ mDots[mCurrentPage].select();
+ mDots[mCurrentPage].mDirection = mPreviousPage < mCurrentPage ? Dot.LEFT : Dot.RIGHT;
+ mDots[mCurrentPage].mCenterX = mDotSelectedX[mCurrentPage];
+ for (int i = mCurrentPage + 1; i < mPageCount; ++i) {
+ mDots[i].deselect();
+ mDots[i].mDirection = Dot.RIGHT;
+ mDots[i].mCenterX = mDotSelectedRightX[i];
+ }
+ }
+
+ public class Dot {
+ static final float LEFT = -1;
+ static final float RIGHT = 1;
+
+ float mAlpha;
+ @ColorInt
+ int mBgColor;
+ @ColorInt
+ int mFgColor;
+ float mTranslationX;
+ float mCenterX;
+ float mDiameter;
+ float mRadius;
+ float mArrowImageRadius;
+ float mDirection = RIGHT;
+
+ void select() {
+ mTranslationX = 0.0f;
+ mCenterX = 0.0f;
+ mDiameter = mArrowDiameter;
+ mRadius = mArrowRadius;
+ mArrowImageRadius = mRadius * mArrowToBgRatio;
+ mAlpha = 1.0f;
+ adjustAlpha();
+ }
+
+ void deselect() {
+ mTranslationX = 0.0f;
+ mCenterX = 0.0f;
+ mDiameter = mDotDiameter;
+ mRadius = mDotRadius;
+ mArrowImageRadius = mRadius * mArrowToBgRatio;
+ mAlpha = 0.0f;
+ adjustAlpha();
+ }
+
+ public void adjustAlpha() {
+ int alpha = Math.round(0xFF * mAlpha);
+ int red = Color.red(mDotFgSelectColor);
+ int green = Color.green(mDotFgSelectColor);
+ int blue = Color.blue(mDotFgSelectColor);
+ mFgColor = Color.argb(alpha, red, green, blue);
+ }
+
+ @UsedByReflection
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ @UsedByReflection
+ public void setAlpha(float alpha) {
+ this.mAlpha = alpha;
+ adjustAlpha();
+ invalidate();
+ }
+
+ @UsedByReflection
+ public float getTranslationX() {
+ return mTranslationX;
+ }
+
+ @UsedByReflection
+ public void setTranslationX(float translationX) {
+ this.mTranslationX = translationX * mDirection;
+ invalidate();
+ }
+
+ @UsedByReflection
+ public float getDiameter() {
+ return mDiameter;
+ }
+
+ @UsedByReflection
+ public void setDiameter(float diameter) {
+ this.mDiameter = diameter;
+ this.mRadius = diameter / 2;
+ this.mArrowImageRadius = diameter / 2 * mArrowToBgRatio;
+ invalidate();
+ }
+
+ void draw(Canvas canvas) {
+ float centerX = mCenterX + mTranslationX;
+ canvas.drawCircle(centerX, mDotCenterY, mRadius, mBgPaint);
+ if (mAlpha > 0) {
+ mFgPaint.setColor(mFgColor);
+ canvas.drawCircle(centerX, mDotCenterY, mRadius, mFgPaint);
+ canvas.drawBitmap(mArrow, mArrowRect, new Rect((int) (centerX - mArrowImageRadius),
+ (int) (mDotCenterY - mArrowImageRadius),
+ (int) (centerX + mArrowImageRadius),
+ (int) (mDotCenterY + mArrowImageRadius)), null);
+ }
+ }
+ }
+}