summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml14
-rw-r--r--res/layout-land/radio_playback_card.xml12
-rw-r--r--res/layout-land/tuner_fragment.xml1
-rw-r--r--res/layout/browse_fragment.xml2
-rw-r--r--res/layout/radio_activity.xml17
-rw-r--r--res/layout/radio_browse_item.xml7
-rw-r--r--res/layout/radio_playback_card.xml12
-rw-r--r--res/layout/radio_playback_controls.xml99
-rw-r--r--res/layout/tuner_dialpad.xml153
-rw-r--r--res/layout/tuner_fragment.xml4
-rw-r--r--res/values/dimens.xml4
-rw-r--r--res/values/styles.xml8
-rw-r--r--res/values/themes.xml2
-rw-r--r--src/com/android/car/radio/BrowseAdapter.java4
-rw-r--r--src/com/android/car/radio/BrowseFragment.java24
-rw-r--r--src/com/android/car/radio/FavoritesFragment.java24
-rw-r--r--src/com/android/car/radio/ManualTunerFragment.java21
-rw-r--r--src/com/android/car/radio/RadioActivity.java28
-rw-r--r--src/com/android/car/radio/service/RadioAppServiceWrapper.java4
19 files changed, 278 insertions, 162 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 01b2412..eccbf94 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,9 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.car.radio">
- <uses-sdk
- android:minSdkVersion="25"
- android:targetSdkVersion="25" />
<!-- This permission is required to allow the radio to be muted. -->
<uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS" />
@@ -30,9 +27,18 @@
<!-- Media Center permission to fetch and update the currently selected media source -->
<uses-permission android:name="com.android.car.media.provider.READ_WRITE"/>
+ <!-- To connect to media browser services in other apps, media browser clients
+ that target Android 11 need to add the following in their manifest -->
+ <queries>
+ <intent>
+ <action android:name="android.media.browse.MediaBrowserService" />
+ </intent>
+ </queries>
+
<application android:label="@string/app_name"
android:icon="@drawable/logo_fm_radio"
- android:theme="@style/Theme.Radio">
+ android:theme="@style/Theme.Radio"
+ android:supportsRtl="true">
<activity
android:name=".RadioActivity"
diff --git a/res/layout-land/radio_playback_card.xml b/res/layout-land/radio_playback_card.xml
index 622011d..39a3c22 100644
--- a/res/layout-land/radio_playback_card.xml
+++ b/res/layout-land/radio_playback_card.xml
@@ -19,8 +19,8 @@ limitations under the License.
android:id="@+id/main_radio_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/playback_card_margin_horizontal"
- android:layout_marginRight="@dimen/playback_card_margin_horizontal"
+ android:layout_marginStart="@dimen/playback_card_margin_horizontal"
+ android:layout_marginEnd="@dimen/playback_card_margin_horizontal"
android:layout_marginBottom="@dimen/playback_card_margin_bottom"
android:background="@drawable/playback_background">
@@ -40,8 +40,8 @@ limitations under the License.
android:ellipsize="end"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/playback_card_interior_padding"
- android:layout_marginRight="@dimen/playback_card_interior_padding"
+ android:layout_marginStart="@dimen/playback_card_interior_padding"
+ android:layout_marginEnd="@dimen/playback_card_interior_padding"
android:maxLines="1"
android:textAppearance="?android:attr/textAppearanceLarge"
app:layout_constraintVertical_chainStyle="packed"
@@ -56,8 +56,8 @@ limitations under the License.
android:ellipsize="end"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/playback_card_interior_padding"
- android:layout_marginRight="@dimen/playback_card_interior_padding"
+ android:layout_marginStart="@dimen/playback_card_interior_padding"
+ android:layout_marginEnd="@dimen/playback_card_interior_padding"
android:paddingTop="@dimen/playback_card_text_spacing"
android:maxLines="1"
android:fontFamily="sans-serif-medium"
diff --git a/res/layout-land/tuner_fragment.xml b/res/layout-land/tuner_fragment.xml
index d90c928..65c8f29 100644
--- a/res/layout-land/tuner_fragment.xml
+++ b/res/layout-land/tuner_fragment.xml
@@ -46,6 +46,7 @@ limitations under the License.
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large"
android:textColor="@color/manual_tuner_button_text_color"
+ android:textDirection="ltr"
app:layout_constraintBottom_toTopOf="@+id/manual_tuner_done_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dialpad_layout"
diff --git a/res/layout/browse_fragment.xml b/res/layout/browse_fragment.xml
index 7c174b8..0cdb636 100644
--- a/res/layout/browse_fragment.xml
+++ b/res/layout/browse_fragment.xml
@@ -23,6 +23,6 @@ limitations under the License.
android:background="@color/browse_fragment_list_color"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginLeft="@dimen/tab_margin_left"
+ android:layout_marginStart="@dimen/tab_margin_start"
/>
</LinearLayout>
diff --git a/res/layout/radio_activity.xml b/res/layout/radio_activity.xml
index 45c022b..bd92a9a 100644
--- a/res/layout/radio_activity.xml
+++ b/res/layout/radio_activity.xml
@@ -26,15 +26,6 @@ limitations under the License.
android:orientation="horizontal"
app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height" />
- <com.android.car.ui.toolbar.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:title="@string/app_name"
- app:layout_constraintTop_toTopOf="parent"
- app:logo="@drawable/logo_fm_radio"
- app:state="home"/>
-
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="@dimen/radio_activity_pager_size"
@@ -43,14 +34,14 @@ limitations under the License.
android:layout_weight="@integer/radio_activity_view_weight"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/toolbar"
+ app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/main_radio_display" />
<TextView
android:id="@+id/status_message"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/toolbar"
+ app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/main_radio_display"
android:visibility="gone"
style="@style/RadioStatusMessage" />
@@ -60,8 +51,8 @@ limitations under the License.
android:layout_width="@dimen/radio_activity_playback_width"
android:layout_height="@dimen/playback_card_height"
android:layout_marginBottom="@dimen/playback_card_margin_bottom"
- android:layout_marginLeft="@dimen/playback_card_margin_horizontal"
- android:layout_marginRight="@dimen/playback_card_margin_horizontal"
+ android:layout_marginStart="@dimen/playback_card_margin_horizontal"
+ android:layout_marginEnd="@dimen/playback_card_margin_horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
diff --git a/res/layout/radio_browse_item.xml b/res/layout/radio_browse_item.xml
index c1a256f..9bbd54b 100644
--- a/res/layout/radio_browse_item.xml
+++ b/res/layout/radio_browse_item.xml
@@ -50,15 +50,16 @@ limitations under the License.
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/browse_item_spacing"
android:textColor="@color/browse_item_text_color"
- android:textAppearance="?android:attr/textAppearanceLarge" />
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textAlignment="viewStart"/>
<ImageButton
android:id="@+id/browse_button"
android:layout_marginEnd="@dimen/browse_item_spacing"
- android:layout_gravity="center_vertical|right"
+ android:layout_gravity="center_vertical|end"
android:layout_width="@dimen/control_button_size"
android:layout_height="@dimen/control_button_size"
- android:gravity="right"
+ android:gravity="end"
android:src="@drawable/ic_star_filled"
style="@style/RadioButton" />
diff --git a/res/layout/radio_playback_card.xml b/res/layout/radio_playback_card.xml
index 2e19fdc..f1aa4d4 100644
--- a/res/layout/radio_playback_card.xml
+++ b/res/layout/radio_playback_card.xml
@@ -19,8 +19,8 @@ limitations under the License.
android:id="@+id/main_radio_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/playback_card_margin_horizontal"
- android:layout_marginRight="@dimen/playback_card_margin_horizontal"
+ android:layout_marginStart="@dimen/playback_card_margin_horizontal"
+ android:layout_marginEnd="@dimen/playback_card_margin_horizontal"
android:layout_marginBottom="@dimen/playback_card_margin_bottom"
android:paddingTop="@dimen/playback_card_interior_padding"
android:background="@drawable/playback_background">
@@ -41,8 +41,8 @@ limitations under the License.
android:layout_gravity="center"
android:layout_width="@dimen/playback_card_station_name_width"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/playback_card_interior_padding"
- android:layout_marginRight="@dimen/playback_card_interior_padding"
+ android:layout_marginStart="@dimen/playback_card_interior_padding"
+ android:layout_marginEnd="@dimen/playback_card_interior_padding"
android:maxLines="@integer/playback_card_station_name_max_lines"
android:textAppearance="?android:attr/textAppearanceLarge"
app:layout_constraintVertical_chainStyle="packed"
@@ -59,8 +59,8 @@ limitations under the License.
android:layout_width="@dimen/playback_card_station_details_width"
android:layout_height="wrap_content"
android:paddingTop="@dimen/playback_card_text_spacing"
- android:layout_marginLeft="@dimen/playback_card_interior_padding"
- android:layout_marginRight="@dimen/playback_card_interior_padding"
+ android:layout_marginStart="@dimen/playback_card_interior_padding"
+ android:layout_marginEnd="@dimen/playback_card_interior_padding"
android:maxLines="@integer/playback_card_station_details_max_lines"
android:textAppearance="?android:attr/textAppearanceMedium"
app:layout_constraintTop_toBottomOf="@+id/station_name"
diff --git a/res/layout/radio_playback_controls.xml b/res/layout/radio_playback_controls.xml
index baac1cc..e3ff718 100644
--- a/res/layout/radio_playback_controls.xml
+++ b/res/layout/radio_playback_controls.xml
@@ -13,52 +13,65 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
+<!-- A dummy wrapper layout so we can set the layout direction of the LinearLayout
+ without impacting its positioning in a parent view group with a potentially different
+ layout direction.
+ Please note that even though most layouts mirror in RTL, playback controls should not be
+ mirrored as they do not refer to the direction of time.
+ For more details see
+ https://material.io/design/usability/bidirectionality.html#mirroring-elements -->
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/buttons_container"
android:layout_width="match_parent"
- android:layout_height="@dimen/control_bar_height"
- android:orientation="horizontal">
+ android:layout_height="@dimen/control_bar_height">
- <ImageButton
- android:id="@+id/back_button"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/control_button_size"
- android:layout_height="@dimen/control_button_size"
- android:layout_weight="@integer/playback_controls_back_button_weight"
- android:src="@drawable/ic_skip_previous"
- android:background="@drawable/playback_button_background"
- style="@style/RadioButton" />
+ <LinearLayout
+ android:id="@+id/buttons_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:layoutDirection="ltr">
- <com.android.car.radio.widget.PlayPauseButton
- android:id="@+id/play_button"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/control_button_size"
- android:layout_height="@dimen/control_button_size"
- android:layout_weight="@integer/playback_controls_play_button_weight"
- android:stateListAnimator="@anim/fab_state_list_animator"
- android:src="@drawable/ic_play_pause_stop"
- android:scaleType="center"
- android:background="@drawable/playback_button_background"
- android:tint="@color/playback_controls_play_button_color"/>
+ <ImageButton
+ android:id="@+id/back_button"
+ android:layout_gravity="center_vertical"
+ android:layout_width="@dimen/control_button_size"
+ android:layout_height="@dimen/control_button_size"
+ android:layout_weight="@integer/playback_controls_back_button_weight"
+ android:src="@drawable/ic_skip_previous"
+ android:background="@drawable/playback_button_background"
+ style="@style/RadioButton" />
- <ImageButton
- android:id="@+id/forward_button"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/control_button_size"
- android:layout_height="@dimen/control_button_size"
- android:layout_weight="@integer/playback_controls_forward_button_weight"
- android:src="@drawable/ic_skip_next"
- android:background="@drawable/playback_button_background"
- style="@style/RadioButton" />
+ <com.android.car.radio.widget.PlayPauseButton
+ android:id="@+id/play_button"
+ android:layout_gravity="center_vertical"
+ android:layout_width="@dimen/control_button_size"
+ android:layout_height="@dimen/control_button_size"
+ android:layout_weight="@integer/playback_controls_play_button_weight"
+ android:stateListAnimator="@anim/fab_state_list_animator"
+ android:src="@drawable/ic_play_pause_stop"
+ android:scaleType="center"
+ android:background="@drawable/playback_button_background"
+ android:tint="@color/playback_controls_play_button_color"/>
- <ImageButton
- android:id="@+id/add_presets_button"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/control_button_size"
- android:layout_height="@dimen/control_button_size"
- android:layout_weight="@integer/playback_controls_presets_button_weight"
- android:src="@drawable/ic_star_empty"
- android:background="@drawable/playback_button_background"
- style="@style/RadioButton" />
-</LinearLayout> \ No newline at end of file
+ <ImageButton
+ android:id="@+id/forward_button"
+ android:layout_gravity="center_vertical"
+ android:layout_width="@dimen/control_button_size"
+ android:layout_height="@dimen/control_button_size"
+ android:layout_weight="@integer/playback_controls_forward_button_weight"
+ android:src="@drawable/ic_skip_next"
+ android:background="@drawable/playback_button_background"
+ style="@style/RadioButton" />
+
+ <ImageButton
+ android:id="@+id/add_presets_button"
+ android:layout_gravity="center_vertical"
+ android:layout_width="@dimen/control_button_size"
+ android:layout_height="@dimen/control_button_size"
+ android:layout_weight="@integer/playback_controls_presets_button_weight"
+ android:src="@drawable/ic_star_empty"
+ android:background="@drawable/playback_button_background"
+ style="@style/RadioButton" />
+ </LinearLayout>
+</FrameLayout>
diff --git a/res/layout/tuner_dialpad.xml b/res/layout/tuner_dialpad.xml
index 57a572a..506940b 100644
--- a/res/layout/tuner_dialpad.xml
+++ b/res/layout/tuner_dialpad.xml
@@ -13,79 +13,88 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:columnCount="@integer/tuner_dialpad_column_count">
+<!-- A dummy wrapper layout so we can set the layout direction of the GridLayout
+ without impacting its positioning in a parent view group with a potentially different
+ layout direction. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <!-- Dialpad should always have LTR layout regardless of the locale. -->
+ <GridLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:columnCount="@integer/tuner_dialpad_column_count"
+ android:layoutDirection="ltr">
- <!-- Row 1 -->
- <Button
- android:id="@+id/manual_tuner_1"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_1"
- android:tag="1"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_2"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_2"
- android:tag="2"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_3"
- android:text="@string/manual_tuner_3"
- android:tag="3"
- style="@style/DialpadKeyButtonStyle" />
+ <!-- Row 1 -->
+ <Button
+ android:id="@+id/manual_tuner_1"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="1"
+ android:tag="1"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_2"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_2"
+ android:tag="2"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_3"
+ android:text="@string/manual_tuner_3"
+ android:tag="3"
+ style="@style/DialpadKeyButtonStyle" />
- <!-- Row 2 -->
- <Button
- android:id="@+id/manual_tuner_4"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_4"
- android:tag="4"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_5"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_5"
- android:tag="5"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_6"
- android:text="@string/manual_tuner_6"
- android:tag="6"
- style="@style/DialpadKeyButtonStyle" />
+ <!-- Row 2 -->
+ <Button
+ android:id="@+id/manual_tuner_4"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_4"
+ android:tag="4"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_5"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_5"
+ android:tag="5"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_6"
+ android:text="@string/manual_tuner_6"
+ android:tag="6"
+ style="@style/DialpadKeyButtonStyle" />
- <!-- Row 3 -->
- <Button
- android:id="@+id/manual_tuner_7"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_7"
- android:tag="7"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_8"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_8"
- android:tag="8"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_9"
- android:text="@string/manual_tuner_9"
- android:tag="9"
- style="@style/DialpadKeyButtonStyle" />
+ <!-- Row 3 -->
+ <Button
+ android:id="@+id/manual_tuner_7"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_7"
+ android:tag="7"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_8"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_8"
+ android:tag="8"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_9"
+ android:text="@string/manual_tuner_9"
+ android:tag="9"
+ style="@style/DialpadKeyButtonStyle"/>
- <!-- Row 4 -->
- <ImageView
- android:id="@+id/manual_tuner_backspace"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:scaleType="center"
- android:src="@drawable/ic_backspace"
- style="@style/DialpadKeyButtonStyle" />
- <Button
- android:id="@+id/manual_tuner_0"
- android:layout_marginRight="@dimen/dialpad_space_horizontal"
- android:text="@string/manual_tuner_0"
- android:tag="0"
- style="@style/DialpadKeyButtonStyle" />
-</GridLayout> \ No newline at end of file
+ <!-- Row 4 -->
+ <ImageView
+ android:id="@+id/manual_tuner_backspace"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:scaleType="center"
+ android:src="@drawable/ic_backspace"
+ style="@style/DialpadKeyButtonStyle" />
+ <Button
+ android:id="@+id/manual_tuner_0"
+ android:layout_marginRight="@dimen/dialpad_space_horizontal"
+ android:text="@string/manual_tuner_0"
+ android:tag="0"
+ style="@style/DialpadKeyButtonStyle" />
+ </GridLayout>
+</FrameLayout> \ No newline at end of file
diff --git a/res/layout/tuner_fragment.xml b/res/layout/tuner_fragment.xml
index 3bdb097..458dd22 100644
--- a/res/layout/tuner_fragment.xml
+++ b/res/layout/tuner_fragment.xml
@@ -20,6 +20,9 @@ limitations under the License.
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <!-- Using LTR text direction since this textView displays bidi strings that should always have
+ LTR direction. Otherwise, the period character in "123." would be interpreted as end of
+ the sentence. This results in ".123" in RTL text direction which is not what we want. -->
<TextView
android:id="@+id/manual_tuner_channel"
android:layout_width="wrap_content"
@@ -27,6 +30,7 @@ limitations under the License.
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large"
android:textColor="@color/manual_tuner_button_text_color"
+ android:textDirection="ltr"
app:layout_constraintBottom_toTopOf="@+id/dialpad_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8edd032..3d60272 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -103,8 +103,8 @@ limitations under the License.
<dimen name="tab_icon_margin">@*android:dimen/car_padding_1</dimen>
<dimen name="tab_elevation">8dp</dimen>
<dimen name="tab_padding">@*android:dimen/car_padding_4</dimen>
- <dimen name="tab_margin_left">@*android:dimen/car_padding_4</dimen>
- <dimen name="tab_margin_right">@dimen/radio_margin</dimen>
+ <dimen name="tab_margin_start">@*android:dimen/car_padding_4</dimen>
+ <dimen name="tab_margin_end">@dimen/radio_margin</dimen>
<dimen name="band_selector_size">@dimen/tab_height</dimen>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 635a19f..20001dc 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,6 +18,10 @@ limitations under the License.
<style name="RadioButton">
<item name="android:background">?android:attr/selectableItemBackground</item>
<item name="android:padding">@dimen/radio_controls_button_padding</item>
+ <!-- Added paddingStart/End explicitly since padding does not override paddingStart/End
+ when RTL support is enabled -->
+ <item name="android:paddingStart">@dimen/radio_controls_button_padding</item>
+ <item name="android:paddingEnd">@dimen/radio_controls_button_padding</item>
<item name="android:scaleType">center</item>
</style>
@@ -27,6 +31,10 @@ limitations under the License.
<item name="android:layout_height">@dimen/dialpad_button_size</item>
<item name="android:layout_marginBottom">@dimen/dialpad_space_vertical</item>
<item name="android:padding">@dimen/dialpad_button_padding</item>
+ <!-- Added paddingStart/End explicitly since padding does not override paddingStart/End
+ when RTL support is enabled -->
+ <item name="android:paddingStart">@dimen/dialpad_button_padding</item>
+ <item name="android:paddingEnd">@dimen/dialpad_button_padding</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:background">?android:attr/selectableItemBackground</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 1c88003..90fdf5d 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -15,7 +15,7 @@ limitations under the License.
-->
<resources>
<!--Theme for the app. -->
- <style name="Theme.Radio" parent="android:Theme.DeviceDefault.NoActionBar">
+ <style name="Theme.Radio" parent="Theme.CarUi.WithToolbar">
<item name="textAppearanceGridItem">@android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="textAppearanceGridItemSecondary">@android:style/TextAppearance.DeviceDefault.Small</item>
</style>
diff --git a/src/com/android/car/radio/BrowseAdapter.java b/src/com/android/car/radio/BrowseAdapter.java
index b894b55..2ca2376 100644
--- a/src/com/android/car/radio/BrowseAdapter.java
+++ b/src/com/android/car/radio/BrowseAdapter.java
@@ -238,7 +238,7 @@ public class BrowseAdapter extends RecyclerView.Adapter<ProgramViewHolder> {
private void handlePresetClicked(int position) {
synchronized (mLock) {
if (mItemClickListener == null) return;
- if (position >= getItemCount()) return;
+ if (position < 0 || position >= getItemCount()) return;
mItemClickListener.onItemClicked(getEntryLocked(position).program.getSelector());
}
@@ -247,7 +247,7 @@ public class BrowseAdapter extends RecyclerView.Adapter<ProgramViewHolder> {
private void handlePresetFavoriteChanged(int position, boolean saveAsFavorite) {
synchronized (mLock) {
if (mItemFavoriteListener == null) return;
- if (position >= getItemCount()) return;
+ if (position < 0 || position >= getItemCount()) return;
mItemFavoriteListener.onItemFavoriteChanged(
getEntryLocked(position).program, saveAsFavorite);
diff --git a/src/com/android/car/radio/BrowseFragment.java b/src/com/android/car/radio/BrowseFragment.java
index 4661df3..f81fc1d 100644
--- a/src/com/android/car/radio/BrowseFragment.java
+++ b/src/com/android/car/radio/BrowseFragment.java
@@ -16,6 +16,8 @@
package com.android.car.radio;
+import static com.android.car.ui.core.CarUi.requireInsets;
+
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -28,11 +30,13 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.car.broadcastradio.support.Program;
import com.android.car.radio.storage.RadioStorage;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
/**
* Fragment that shows all browseable radio stations from background scan
*/
-public class BrowseFragment extends Fragment {
+public class BrowseFragment extends Fragment implements InsetsChangedListener {
private RadioController mRadioController;
private BrowseAdapter mBrowseAdapter;
@@ -76,6 +80,24 @@ public class BrowseFragment extends Fragment {
}
}
+ @Override
+ public void onCarUiInsetsChanged(Insets insets) {
+ View view = requireView();
+ View recyclerView = view.findViewById(R.id.browse_list);
+ recyclerView.setPadding(insets.getLeft(),
+ insets.getTop(),
+ insets.getRight(),
+ insets.getBottom());
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ // This is needed to apply the inset changes that happened before this fragment was visible
+ onCarUiInsetsChanged(requireInsets(getActivity()));
+ }
+
private void handlePresetItemFavoriteChanged(Program program, boolean saveAsFavorite) {
if (saveAsFavorite) {
mRadioStorage.addFavorite(program);
diff --git a/src/com/android/car/radio/FavoritesFragment.java b/src/com/android/car/radio/FavoritesFragment.java
index 3154dba..218a318 100644
--- a/src/com/android/car/radio/FavoritesFragment.java
+++ b/src/com/android/car/radio/FavoritesFragment.java
@@ -16,6 +16,8 @@
package com.android.car.radio;
+import static com.android.car.ui.core.CarUi.requireInsets;
+
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -28,11 +30,13 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.car.broadcastradio.support.Program;
import com.android.car.radio.storage.RadioStorage;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
/**
* Fragment that shows a list of all the current favorite radio stations
*/
-public class FavoritesFragment extends Fragment {
+public class FavoritesFragment extends Fragment implements InsetsChangedListener {
private RadioController mRadioController;
private BrowseAdapter mBrowseAdapter;
@@ -76,6 +80,24 @@ public class FavoritesFragment extends Fragment {
}
}
+ @Override
+ public void onCarUiInsetsChanged(Insets insets) {
+ View view = requireView();
+ View recyclerView = view.findViewById(R.id.browse_list);
+ recyclerView.setPadding(insets.getLeft(),
+ insets.getTop(),
+ insets.getRight(),
+ insets.getBottom());
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ // This is needed to apply the inset changes that happened before this fragment was visible
+ onCarUiInsetsChanged(requireInsets(getActivity()));
+ }
+
private void handlePresetItemFavoriteChanged(Program program, boolean saveAsFavorite) {
if (saveAsFavorite) {
mRadioStorage.addFavorite(program);
diff --git a/src/com/android/car/radio/ManualTunerFragment.java b/src/com/android/car/radio/ManualTunerFragment.java
index 737edb9..9fe6bcc 100644
--- a/src/com/android/car/radio/ManualTunerFragment.java
+++ b/src/com/android/car/radio/ManualTunerFragment.java
@@ -16,6 +16,8 @@
package com.android.car.radio;
+import static com.android.car.ui.core.CarUi.requireInsets;
+
import android.hardware.radio.RadioManager.ProgramInfo;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -25,11 +27,13 @@ import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.android.car.radio.bands.ProgramType;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
/**
* Fragment that allows tuning to a specific frequency using a keypad
*/
-public class ManualTunerFragment extends Fragment {
+public class ManualTunerFragment extends Fragment implements InsetsChangedListener {
private ManualTunerController mController;
private RadioController mRadioController;
@@ -57,6 +61,21 @@ public class ManualTunerFragment extends Fragment {
}
}
+ @Override
+ public void onCarUiInsetsChanged(Insets insets) {
+ View view = requireView();
+ view.setPadding(insets.getLeft(), insets.getTop(),
+ insets.getRight(), insets.getBottom());
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ // This is needed to apply the inset changes that happened before this fragment was visible
+ onCarUiInsetsChanged(requireInsets(getActivity()));
+ }
+
static ManualTunerFragment newInstance(RadioController radioController) {
ManualTunerFragment fragment = new ManualTunerFragment();
fragment.mRadioController = radioController;
diff --git a/src/com/android/car/radio/RadioActivity.java b/src/com/android/car/radio/RadioActivity.java
index a9a956a..73582b5 100644
--- a/src/com/android/car/radio/RadioActivity.java
+++ b/src/com/android/car/radio/RadioActivity.java
@@ -16,6 +16,11 @@
package com.android.car.radio;
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_BROWSE;
+
+import static com.android.car.ui.core.CarUi.requireToolbar;
+import static com.android.car.ui.toolbar.Toolbar.State.HOME;
+
import android.car.Car;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -30,9 +35,11 @@ import com.android.car.media.common.source.MediaSource;
import com.android.car.media.common.source.MediaSourceViewModel;
import com.android.car.radio.bands.ProgramType;
import com.android.car.radio.util.Log;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.TabLayout;
-import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
import java.util.Arrays;
import java.util.List;
@@ -40,7 +47,7 @@ import java.util.List;
/**
* The main activity for the radio app.
*/
-public class RadioActivity extends FragmentActivity {
+public class RadioActivity extends FragmentActivity implements InsetsChangedListener {
private static final String TAG = "BcRadioApp.activity";
/**
@@ -57,10 +64,17 @@ public class RadioActivity extends FragmentActivity {
private RadioController mRadioController;
private BandController mBandController = new BandController();
- private Toolbar mToolbar;
+ private ToolbarController mToolbar;
private RadioPagerAdapter mRadioPagerAdapter;
@Override
+ public void onCarUiInsetsChanged(Insets insets) {
+ // This InsetsChangedListener is just a marker that we will later handle
+ // insets in fragments, since the fragments aren't added immediately.
+ // Otherwise CarUi will apply the insets to the content view incorrectly.
+ }
+
+ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -82,14 +96,18 @@ public class RadioActivity extends FragmentActivity {
ViewPager viewPager = findViewById(R.id.viewpager);
viewPager.setAdapter(mRadioPagerAdapter);
- mToolbar = requireViewById(R.id.toolbar);
+ mToolbar = requireToolbar(this);
+ mToolbar.setState(HOME);
+ mToolbar.setTitle(R.string.app_name);
+ mToolbar.setLogo(R.drawable.logo_fm_radio);
mToolbar.registerOnTabSelectedListener(t ->
viewPager.setCurrentItem(mToolbar.getTabLayout().getTabPosition(t)));
updateMenuItems();
setupTabsWithViewPager(viewPager);
- MediaSourceViewModel model = MediaSourceViewModel.get(getApplication());
+ MediaSourceViewModel model =
+ MediaSourceViewModel.get(getApplication(), MEDIA_SOURCE_MODE_BROWSE);
model.getPrimaryMediaSource().observe(this, source -> {
if (source != null) {
// Always go through the trampoline activity to keep all the dispatching logic
diff --git a/src/com/android/car/radio/service/RadioAppServiceWrapper.java b/src/com/android/car/radio/service/RadioAppServiceWrapper.java
index 0ab882d..154a408 100644
--- a/src/com/android/car/radio/service/RadioAppServiceWrapper.java
+++ b/src/com/android/car/radio/service/RadioAppServiceWrapper.java
@@ -202,7 +202,9 @@ public class RadioAppServiceWrapper {
throw new IllegalStateException(
"This is not a remote service wrapper, you can't unbind it");
}
- callService(service -> service.removeCallback(mCallback));
+ try {
+ callService(service -> service.removeCallback(mCallback));
+ } catch (IllegalStateException e) { } // it's fine if the service is not connected
mClientContext.unbindService(mServiceConnection);
}