summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGoogler <noreply@google.com>2022-01-27 22:54:19 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-01-27 22:54:19 +0000
commitc319e39461f262deef11f47c30c01fddc719d030 (patch)
treefb9949c0f45f0543a43aedeac231aa6a799a8fa5
parent5ef0c1063d237a4f08110623cbef00e9445c4cb6 (diff)
parenteccda78bf3a3df753ef9d3cdc119e0d9d84b8f89 (diff)
downloadsetupwizard-c319e39461f262deef11f47c30c01fddc719d030.tar.gz
Changes for Car Setup Wizard Support Library: am: 15612ebde2 am: f941384091 am: eccda78bf3
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/car/setupwizard/+/1959684 Change-Id: Ib055569f3327236a37251f08e1df5c4e0e12d99d
-rw-r--r--library/main/AndroidManifest.xml4
-rw-r--r--library/main/res/color/button_text_color.xml23
-rw-r--r--library/main/res/drawable/flat_button_background.xml44
-rw-r--r--library/main/res/drawable/list_item_background.xml46
-rw-r--r--library/main/res/drawable/primary_button_background.xml54
-rw-r--r--library/main/res/drawable/round_button_background.xml46
-rw-r--r--library/main/res/layout-land/action_bar.xml38
-rw-r--r--library/main/res/layout-land/rotary_action_bar.xml38
-rw-r--r--library/main/res/layout-land/rotary_split_nav_layout.xml71
-rw-r--r--library/main/res/layout-land/split_nav_layout.xml60
-rw-r--r--library/main/res/layout-w1760dp-land/rotary_split_nav_layout.xml67
-rw-r--r--library/main/res/layout-w1760dp-land/split_nav_layout.xml57
-rw-r--r--library/main/res/layout/action_bar.xml36
-rw-r--r--library/main/res/layout/car_setup_wizard_toolbar.xml14
-rw-r--r--library/main/res/layout/empty_fragment_frame_layout.xml5
-rw-r--r--library/main/res/layout/progressbar.xml26
-rw-r--r--library/main/res/layout/rotary_car_setup_wizard_layout.xml39
-rw-r--r--library/main/res/layout/rotary_split_nav_layout.xml67
-rw-r--r--library/main/res/layout/split_nav_compat_activity.xml27
-rw-r--r--library/main/res/layout/split_nav_design_activity.xml27
-rw-r--r--library/main/res/layout/split_nav_layout.xml53
-rw-r--r--library/main/res/values/attrs.xml5
-rw-r--r--library/main/res/values/colors.xml8
-rw-r--r--library/main/res/values/dimens.xml8
-rw-r--r--library/main/res/values/styles.xml2
-rw-r--r--library/main/src/com/android/car/setupwizardlib/BaseCompatActivity.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/BaseDesignActivity.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java71
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java264
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayout.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardDesignLayout.java2
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayout.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayoutInterface.java82
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java5
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java2
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java5
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/ResourceEntry.java1
-rw-r--r--library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java6
-rw-r--r--library/main/src/com/android/car/setupwizardlib/summary/SummaryAction.java11
-rw-r--r--library/main/src/com/android/car/setupwizardlib/summary/SummaryActionState.java24
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/CarDrivingStateMonitor.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/CarHelperRegistry.java2
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/CarSetupWizardUiUtils.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java265
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/FeatureResolver.java119
45 files changed, 1533 insertions, 209 deletions
diff --git a/library/main/AndroidManifest.xml b/library/main/AndroidManifest.xml
index 9bd2e16..e330c33 100644
--- a/library/main/AndroidManifest.xml
+++ b/library/main/AndroidManifest.xml
@@ -18,6 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.car.setupwizardlib">
<uses-sdk
- android:minSdkVersion="24"
- android:targetSdkVersion="26" />
+ android:minSdkVersion="29"
+ android:targetSdkVersion="31" />
</manifest>
diff --git a/library/main/res/color/button_text_color.xml b/library/main/res/color/button_text_color.xml
new file mode 100644
index 0000000..f4ed692
--- /dev/null
+++ b/library/main/res/color/button_text_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:color="@android:color/white"/>
+ <item android:state_enabled="false"
+ android:alpha="0.5"
+ android:color="@android:color/black"/>
+ <item android:color="@android:color/black"/>
+</selector> \ No newline at end of file
diff --git a/library/main/res/drawable/flat_button_background.xml b/library/main/res/drawable/flat_button_background.xml
new file mode 100644
index 0000000..ff5dbdc
--- /dev/null
+++ b/library/main/res/drawable/flat_button_background.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_pressed_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_pressed_stroke_width"
+ android:color="@color/suw_rotary_focus_pressed_stroke_color" />
+ <corners android:radius="@dimen/car_button_radius"/>
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_stroke_width"
+ android:color="@color/suw_rotary_focus_stroke_color" />
+ <corners android:radius="@dimen/car_button_radius"/>
+ </shape>
+ </item>
+ <item>
+ <ripple android:color="@color/car_grey_300">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="@color/car_card_ripple_background_light"/>
+ </shape>
+ </item>
+ </ripple>
+ </item>
+</selector>
diff --git a/library/main/res/drawable/list_item_background.xml b/library/main/res/drawable/list_item_background.xml
new file mode 100644
index 0000000..9f871dd
--- /dev/null
+++ b/library/main/res/drawable/list_item_background.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_pressed_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_pressed_stroke_width"
+ android:color="@color/suw_rotary_focus_pressed_stroke_color"/>
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_stroke_width"
+ android:color="@color/suw_rotary_focus_stroke_color"/>
+ </shape>
+ </item>
+ <item android:state_activated="true">
+ <shape android:shape="rectangle">
+ <solid android:color="?android:attr/colorControlHighlight"/>
+ </shape>
+ </item>
+ <item>
+ <ripple android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/car_card_ripple_background_light"/>
+ </shape>
+ </item>
+ </ripple>
+ </item>
+</selector> \ No newline at end of file
diff --git a/library/main/res/drawable/primary_button_background.xml b/library/main/res/drawable/primary_button_background.xml
new file mode 100644
index 0000000..e353b9c
--- /dev/null
+++ b/library/main/res/drawable/primary_button_background.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_pressed_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_pressed_stroke_width"
+ android:color="@color/suw_rotary_focus_pressed_stroke_color" />
+ <corners android:radius="@dimen/car_button_radius"/>
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/suw_rotary_focus_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_stroke_width"
+ android:color="@color/suw_rotary_focus_stroke_color" />
+ <corners android:radius="@dimen/car_button_radius"/>
+ </shape>
+ </item>
+ <item>
+ <ripple android:color="?attr/colorControlHighlight">
+ <item>
+ <selector>
+ <item android:state_enabled="false">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="@color/car_grey_300"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="?android:attr/colorButtonNormal"/>
+ </shape>
+ </item>
+ </selector>
+ </item>
+ </ripple>
+ </item>
+</selector> \ No newline at end of file
diff --git a/library/main/res/drawable/round_button_background.xml b/library/main/res/drawable/round_button_background.xml
new file mode 100644
index 0000000..eedce1f
--- /dev/null
+++ b/library/main/res/drawable/round_button_background.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true">
+ <shape android:shape="oval">
+ <solid android:color="@color/suw_rotary_focus_pressed_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_pressed_stroke_width"
+ android:color="@color/suw_rotary_focus_pressed_stroke_color"/>
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape android:shape="oval">
+ <solid android:color="@color/suw_rotary_focus_fill_color"/>
+ <stroke android:width="@dimen/suw_rotary_focus_stroke_width"
+ android:color="@color/suw_rotary_focus_stroke_color"/>
+ </shape>
+ </item>
+ <item android:state_activated="true">
+ <shape android:shape="oval">
+ <solid android:color="?android:attr/colorControlHighlight"/>
+ </shape>
+ </item>
+ <item>
+ <ripple android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <shape android:shape="oval">
+ <solid android:color="@color/car_card_ripple_background_light"/>
+ </shape>
+ </item>
+ </ripple>
+ </item>
+</selector> \ No newline at end of file
diff --git a/library/main/res/layout-land/action_bar.xml b/library/main/res/layout-land/action_bar.xml
new file mode 100644
index 0000000..71929a5
--- /dev/null
+++ b/library/main/res/layout-land/action_bar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/button_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/actionbar_height"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_4"
+ android:paddingHorizontal="@dimen/suw_padding_7"
+ android:orientation="horizontal">
+ <ViewStub
+ android:id="@+id/primary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inflatedId="@+id/primary_toolbar_button"
+ android:layout="@layout/primary_button"/>
+ <ViewStub
+ android:id="@+id/secondary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/suw_padding_7"
+ android:inflatedId="@+id/secondary_toolbar_button"
+ android:layout="@layout/flat_button"/>
+</LinearLayout> \ No newline at end of file
diff --git a/library/main/res/layout-land/rotary_action_bar.xml b/library/main/res/layout-land/rotary_action_bar.xml
new file mode 100644
index 0000000..8f02f29
--- /dev/null
+++ b/library/main/res/layout-land/rotary_action_bar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.car.ui.FocusArea xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/button_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/actionbar_height"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_4"
+ android:paddingHorizontal="@dimen/suw_padding_7"
+ android:orientation="horizontal">
+ <ViewStub
+ android:id="@+id/primary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inflatedId="@+id/primary_toolbar_button"
+ android:layout="@layout/primary_button"/>
+ <ViewStub
+ android:id="@+id/secondary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/suw_padding_7"
+ android:inflatedId="@+id/secondary_toolbar_button"
+ android:layout="@layout/flat_button"/>
+</com.android.car.ui.FocusArea> \ No newline at end of file
diff --git a/library/main/res/layout-land/rotary_split_nav_layout.xml b/library/main/res/layout-land/rotary_split_nav_layout.xml
new file mode 100644
index 0000000..b69c5b2
--- /dev/null
+++ b/library/main/res/layout-land/rotary_split_nav_layout.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <com.android.car.ui.FocusParkingView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <com.android.car.ui.FocusArea
+ android:id="@+id/application_bar"
+ android:layout_width="@dimen/sidebar_width"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_3"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/back_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_arrow_back"/>
+
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/close_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_close"/>
+ </com.android.car.ui.FocusArea>
+
+ <LinearLayout
+ android:id="@+id/content_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <include layout="@layout/progressbar"/>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </com.android.car.ui.FocusArea>
+
+ <include layout="@layout/rotary_action_bar"/>
+ </LinearLayout>
+</merge> \ No newline at end of file
diff --git a/library/main/res/layout-land/split_nav_layout.xml b/library/main/res/layout-land/split_nav_layout.xml
new file mode 100644
index 0000000..16a017f
--- /dev/null
+++ b/library/main/res/layout-land/split_nav_layout.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <FrameLayout
+ android:id="@+id/application_bar"
+ android:layout_width="@dimen/sidebar_width"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_3">
+
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/back_button_content_description"
+ android:src="@drawable/car_ic_arrow_back"/>
+
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/close_button_content_description"
+ android:src="@drawable/car_ic_close"/>
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/content_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <include layout="@layout/progressbar"/>
+
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+ <include layout="@layout/action_bar"/>
+ </LinearLayout>
+</merge> \ No newline at end of file
diff --git a/library/main/res/layout-w1760dp-land/rotary_split_nav_layout.xml b/library/main/res/layout-w1760dp-land/rotary_split_nav_layout.xml
new file mode 100644
index 0000000..8ff4854
--- /dev/null
+++ b/library/main/res/layout-w1760dp-land/rotary_split_nav_layout.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <com.android.car.ui.FocusParkingView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <com.android.car.ui.FocusArea
+ android:id="@+id/application_bar"
+ android:layout_width="@dimen/sidebar_width"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_3"
+ android:orientation="vertical">
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/back_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_arrow_back"/>
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/close_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_close"/>
+ </com.android.car.ui.FocusArea>
+ <LinearLayout
+ android:id="@+id/ultra_wide_content_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <include layout="@layout/progressbar"/>
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </com.android.car.ui.FocusArea>
+ <include layout="@layout/rotary_action_bar"/>
+ </LinearLayout>
+ <FrameLayout
+ android:id="@+id/ultra_wide_space_filler"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@color/suw_color_background"/>
+</merge>
diff --git a/library/main/res/layout-w1760dp-land/split_nav_layout.xml b/library/main/res/layout-w1760dp-land/split_nav_layout.xml
new file mode 100644
index 0000000..c118c66
--- /dev/null
+++ b/library/main/res/layout-w1760dp-land/split_nav_layout.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <FrameLayout
+ android:id="@+id/application_bar"
+ android:layout_width="@dimen/sidebar_width"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:paddingTop="@dimen/suw_padding_3">
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/back_button_content_description"
+ android:src="@drawable/car_ic_arrow_back"/>
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/close_button_content_description"
+ android:src="@drawable/car_ic_close"/>
+ </FrameLayout>
+ <LinearLayout
+ android:id="@+id/ultra_wide_content_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <include layout="@layout/progressbar"/>
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+ <include layout="@layout/action_bar"/>
+ </LinearLayout>
+ <FrameLayout
+ android:id="@+id/ultra_wide_space_filler"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@color/suw_color_background"/>
+</merge>
diff --git a/library/main/res/layout/action_bar.xml b/library/main/res/layout/action_bar.xml
new file mode 100644
index 0000000..0920bb1
--- /dev/null
+++ b/library/main/res/layout/action_bar.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/button_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/actionbar_height"
+ android:paddingHorizontal="@dimen/suw_padding_7">
+ <ViewStub
+ android:id="@+id/primary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:inflatedId="@+id/primary_toolbar_button"
+ android:layout="@layout/primary_button"/>
+ <ViewStub
+ android:id="@+id/secondary_toolbar_button_stub"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:inflatedId="@+id/secondary_toolbar_button"
+ android:layout="@layout/flat_button"/>
+</RelativeLayout> \ No newline at end of file
diff --git a/library/main/res/layout/car_setup_wizard_toolbar.xml b/library/main/res/layout/car_setup_wizard_toolbar.xml
index 5ae4e11..ff397d5 100644
--- a/library/main/res/layout/car_setup_wizard_toolbar.xml
+++ b/library/main/res/layout/car_setup_wizard_toolbar.xml
@@ -31,20 +31,22 @@
<ImageView
android:id="@+id/back_button"
- android:layout_width="@dimen/car_primary_icon_size"
- android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="center"
- android:background="@drawable/button_ripple_bg"
+ android:background="@drawable/round_button_background"
android:contentDescription="@string/back_button_content_description"
+ android:padding="@dimen/car_padding_2"
android:src="@drawable/car_ic_arrow_back"/>
<ImageView
android:id="@+id/close_button"
- android:layout_width="@dimen/car_primary_icon_size"
- android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="center"
- android:background="@drawable/button_ripple_bg"
+ android:background="@drawable/round_button_background"
android:contentDescription="@string/close_button_content_description"
+ android:padding="@dimen/car_padding_2"
android:src="@drawable/car_ic_close"/>
</FrameLayout>
diff --git a/library/main/res/layout/empty_fragment_frame_layout.xml b/library/main/res/layout/empty_fragment_frame_layout.xml
new file mode 100644
index 0000000..0ea8da7
--- /dev/null
+++ b/library/main/res/layout/empty_fragment_frame_layout.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/empty_fragment_frame_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" /> \ No newline at end of file
diff --git a/library/main/res/layout/progressbar.xml b/library/main/res/layout/progressbar.xml
new file mode 100644
index 0000000..3056662
--- /dev/null
+++ b/library/main/res/layout/progressbar.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/progress_bar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="match_parent"
+ android:layout_height="2dp"
+ android:minHeight="0dp"
+ android:maxHeight="20dp"
+ android:indeterminateDrawable="@drawable/progress_indeterminate_horizontal_material_trimmed"
+ android:indeterminateTint="?android:attr/colorAccent"
+ android:indeterminateTintMode="src_in"/> \ No newline at end of file
diff --git a/library/main/res/layout/rotary_car_setup_wizard_layout.xml b/library/main/res/layout/rotary_car_setup_wizard_layout.xml
new file mode 100644
index 0000000..9e9819f
--- /dev/null
+++ b/library/main/res/layout/rotary_car_setup_wizard_layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <com.android.car.ui.FocusParkingView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <include
+ android:id="@+id/application_bar"
+ layout="@layout/car_setup_wizard_toolbar"/>
+ </com.android.car.ui.FocusArea>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </com.android.car.ui.FocusArea>
+</merge>
diff --git a/library/main/res/layout/rotary_split_nav_layout.xml b/library/main/res/layout/rotary_split_nav_layout.xml
new file mode 100644
index 0000000..1a8a004
--- /dev/null
+++ b/library/main/res/layout/rotary_split_nav_layout.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <com.android.car.ui.FocusParkingView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <com.android.car.ui.FocusArea
+ android:id="@+id/application_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/suw_padding_8"
+ android:paddingStart="@dimen/navbar_padding_start"
+ android:gravity="start">
+
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/back_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_arrow_back"/>
+
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/round_button_background"
+ android:contentDescription="@string/close_button_content_description"
+ android:padding="@dimen/car_padding_2"
+ android:src="@drawable/car_ic_close"/>
+ </com.android.car.ui.FocusArea>
+
+ <include layout="@layout/progressbar"/>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </com.android.car.ui.FocusArea>
+
+ <com.android.car.ui.FocusArea
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <include layout="@layout/action_bar"/>
+ </com.android.car.ui.FocusArea>
+</merge> \ No newline at end of file
diff --git a/library/main/res/layout/split_nav_compat_activity.xml b/library/main/res/layout/split_nav_compat_activity.xml
new file mode 100644
index 0000000..ee4b0eb
--- /dev/null
+++ b/library/main/res/layout/split_nav_compat_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.car.setupwizardlib.CarSetupWizardCompatLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/car_setup_wizard_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:showBackButton="true"
+ app:showPrimaryToolbarButton="true"
+ app:primaryToolbarButtonEnabled="true"
+ app:supportsSplitNavLayout="true"
+ app:supportsRotaryControl="true"/> \ No newline at end of file
diff --git a/library/main/res/layout/split_nav_design_activity.xml b/library/main/res/layout/split_nav_design_activity.xml
new file mode 100644
index 0000000..19454c6
--- /dev/null
+++ b/library/main/res/layout/split_nav_design_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<com.android.car.setupwizardlib.CarSetupWizardDesignLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/car_setup_wizard_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:showBackButton="true"
+ app:showPrimaryToolbarButton="true"
+ app:primaryToolbarButtonEnabled="true"
+ app:supportsSplitNavLayout="true"
+ app:supportsRotaryControl="true"/>
diff --git a/library/main/res/layout/split_nav_layout.xml b/library/main/res/layout/split_nav_layout.xml
new file mode 100644
index 0000000..03ee676
--- /dev/null
+++ b/library/main/res/layout/split_nav_layout.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <FrameLayout
+ android:id="@+id/application_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/suw_padding_8"
+ android:paddingStart="@dimen/navbar_padding_start"
+ android:gravity="start">
+
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/back_button_content_description"
+ android:src="@drawable/car_ic_arrow_back"/>
+
+ <ImageView
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/close_button_content_description"
+ android:src="@drawable/car_ic_close"/>
+ </FrameLayout>
+
+ <include layout="@layout/progressbar"/>
+
+ <ViewStub
+ android:id="@+id/layout_content_stub"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+ <include layout="@layout/action_bar"/>
+</merge> \ No newline at end of file
diff --git a/library/main/res/values/attrs.xml b/library/main/res/values/attrs.xml
index 31d2f5b..d5fd07b 100644
--- a/library/main/res/values/attrs.xml
+++ b/library/main/res/values/attrs.xml
@@ -90,6 +90,11 @@
of the progress bar -->
<attr name="showProgressBar"/>
<attr name="indeterminateProgressBar"/>
+
+ <!-- Attributes related to the split nav layout -->
+ <attr name="supportsSplitNavLayout" format="boolean"/>
+ <!-- Attributes related to the rotary support -->
+ <attr name="supportsRotaryControl" format="boolean"/>
</declare-styleable>
</resources>
diff --git a/library/main/res/values/colors.xml b/library/main/res/values/colors.xml
index a3df84d..77a2748 100644
--- a/library/main/res/values/colors.xml
+++ b/library/main/res/values/colors.xml
@@ -36,4 +36,12 @@
<color name="suw_color_divider">#3C4043</color>
<!-- Material grey900 -->
<color name="suw_color_background">#202124</color>
+ <!-- Material grey868 -->
+ <color name="suw_color_split_nav_toolbar_background">#282B2D</color>
+
+ <!-- Rotary focus highlight -->
+ <color name="suw_rotary_focus_stroke_color">#94CBFF</color>
+ <color name="suw_rotary_focus_fill_color">#3D94CBFF</color>
+ <color name="suw_rotary_focus_pressed_stroke_color">#94CBFF</color>
+ <color name="suw_rotary_focus_pressed_fill_color">#8A94CBFF</color>
</resources>
diff --git a/library/main/res/values/dimens.xml b/library/main/res/values/dimens.xml
index db6c833..6c2b322 100644
--- a/library/main/res/values/dimens.xml
+++ b/library/main/res/values/dimens.xml
@@ -27,4 +27,12 @@
<dimen name="suw_page_margin_horizontal">112dp</dimen>
<!-- The column inner padding of a two-column layout. N/A in portrait -->
<dimen name="suw_column_inner_padding_horizontal">0dp</dimen>
+
+ <dimen name="sidebar_width">@dimen/suw_padding_8</dimen>
+ <dimen name="navbar_padding_start">10dp</dimen>
+ <dimen name="actionbar_height">@dimen/suw_padding_9</dimen>
+
+ <!-- Rotary focus highlight -->
+ <dimen name="suw_rotary_focus_stroke_width">8dp</dimen>
+ <dimen name="suw_rotary_focus_pressed_stroke_width">4dp</dimen>
</resources> \ No newline at end of file
diff --git a/library/main/res/values/styles.xml b/library/main/res/values/styles.xml
index 6ab739d..8155505 100644
--- a/library/main/res/values/styles.xml
+++ b/library/main/res/values/styles.xml
@@ -18,11 +18,13 @@
<style name="Widget.Car.SetupWizard.Button" parent="Widget.Car.Button.DarkText">
<item name="android:fontFamily">@font/sans_medium</item>
<item name="android:textAllCaps">false</item>
+ <item name="android:background">@drawable/primary_button_background</item>
</style>
<style name="Widget.Car.SetupWizard.Button.Borderless.Colored"
parent="Widget.Car.Button.Borderless.Colored">
<item name="android:fontFamily">@font/sans_medium</item>
<item name="android:textAllCaps">false</item>
+ <item name="android:background">@drawable/flat_button_background</item>
</style>
</resources>
diff --git a/library/main/src/com/android/car/setupwizardlib/BaseCompatActivity.java b/library/main/src/com/android/car/setupwizardlib/BaseCompatActivity.java
index c8bcf4b..5cca557 100644
--- a/library/main/src/com/android/car/setupwizardlib/BaseCompatActivity.java
+++ b/library/main/src/com/android/car/setupwizardlib/BaseCompatActivity.java
@@ -24,7 +24,8 @@ public class BaseCompatActivity extends BaseSetupWizardActivity {
@Override
@LayoutRes
int getLayout() {
- return R.layout.base_compat_activity;
+ return isSplitNavLayoutSupported()
+ ? R.layout.split_nav_compat_activity : R.layout.base_compat_activity;
}
@Override
diff --git a/library/main/src/com/android/car/setupwizardlib/BaseDesignActivity.java b/library/main/src/com/android/car/setupwizardlib/BaseDesignActivity.java
index a7288b5..5650f71 100644
--- a/library/main/src/com/android/car/setupwizardlib/BaseDesignActivity.java
+++ b/library/main/src/com/android/car/setupwizardlib/BaseDesignActivity.java
@@ -24,7 +24,8 @@ public class BaseDesignActivity extends BaseSetupWizardActivity {
@Override
@LayoutRes
int getLayout() {
- return R.layout.base_design_activity;
+ return isSplitNavLayoutSupported()
+ ? R.layout.split_nav_design_activity : R.layout.base_design_activity;
}
@Override
diff --git a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
index 36caae0..f8d9342 100644
--- a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
+++ b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
@@ -19,7 +19,9 @@ package com.android.car.setupwizardlib;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewStub;
import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes;
@@ -48,6 +50,8 @@ import com.android.car.setupwizardlib.util.CarWizardManagerHelper;
* component attributes
*/
abstract class BaseSetupWizardActivity extends FragmentActivity {
+ private static final String TAG = BaseSetupWizardActivity.class.getSimpleName();
+
@VisibleForTesting
static final String CONTENT_FRAGMENT_TAG = "CONTENT_FRAGMENT_TAG";
/**
@@ -91,13 +95,9 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
mCarSetupWizardLayout = findViewById(R.id.car_setup_wizard_layout);
- mCarSetupWizardLayout.setBackButtonListener(v -> {
- if (!handleBackButton()) {
- finish();
- }
- });
+ mCarSetupWizardLayout.setBackButtonListener(v -> handleBackButtonEvent());
- mCarSetupWizardLayout.setCloseButtonListener(v-> handleCloseButton());
+ mCarSetupWizardLayout.setCloseButtonListener(v -> handleCloseButton());
resetPrimaryToolbarButtonOnClickListener();
resetSecondaryToolbarButtonOnClickListener();
@@ -176,8 +176,9 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
@CallSuper
protected void setContentFragmentWithBackstack(Fragment fragment) {
if (mAllowFragmentCommits) {
+ inflateEmptyFragmentFrameLayout();
getSupportFragmentManager().beginTransaction()
- .replace(R.id.car_setup_wizard_layout, fragment, CONTENT_FRAGMENT_TAG)
+ .replace(getFragmentContainerViewId(), fragment, CONTENT_FRAGMENT_TAG)
.addToBackStack(null)
.commit();
getSupportFragmentManager().executePendingTransactions();
@@ -199,13 +200,14 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
@CallSuper
protected void setContentFragment(Fragment fragment) {
if (mAllowFragmentCommits) {
+ inflateEmptyFragmentFrameLayout();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(
android.R.animator.fade_in,
android.R.animator.fade_out,
android.R.animator.fade_in,
android.R.animator.fade_out)
- .replace(R.id.car_setup_wizard_layout, fragment, CONTENT_FRAGMENT_TAG)
+ .replace(getFragmentContainerViewId(), fragment, CONTENT_FRAGMENT_TAG)
.commitNow();
onContentFragmentSet(getContentFragment());
}
@@ -242,10 +244,25 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
*/
@CallSuper
protected View setContentLayout(@LayoutRes int id) {
+ ViewStub viewStub = findViewById(R.id.layout_content_stub);
+ if (viewStub != null) {
+ viewStub.setLayoutResource(id);
+ return viewStub.inflate();
+ }
return getLayoutInflater().inflate(id, mCarSetupWizardLayout);
}
/**
+ * Method used when back button is pressed, if the back button wasn't handled by the activity
+ * finish() will be called.
+ */
+ private void handleBackButtonEvent() {
+ if (!handleBackButton()) {
+ finish();
+ }
+ }
+
+ /**
* Method to be overwritten by subclasses wanting to implement their own back behavior.
* Default behavior is to pop a fragment off of the backstack if one exists, otherwise call
* finish()
@@ -256,6 +273,16 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
return popBackStackImmediate();
}
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ handleBackButtonEvent();
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
/**
* Method to be overwritten by subclasses wanting to implement their own close behavior.
* Default behavior is finishAction.
@@ -486,6 +513,10 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
mCarSetupWizardLayout.setProgressBarVisible(visible);
}
+ protected boolean isSplitNavLayoutSupported() {
+ return false;
+ }
+
private void launchNextAction(int resultCode, Intent data, boolean forResult) {
if (resultCode == RESULT_CANCELED) {
throw new IllegalArgumentException("Cannot call nextAction with RESULT_CANCELED");
@@ -509,6 +540,30 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
}
@VisibleForTesting
+ int getFragmentContainerViewId() {
+ // Check if the inflated frame layout is still available. Add the fragment to frame
+ // layout only if it's available. Otherwise, fall back to default layout to attach
+ // fragment. Note that frame layout might not be available if hosting activity inflated
+ // viewStub already with other views than before calling setFragmentContent().
+ View frameLayout = findViewById(R.id.empty_fragment_frame_layout);
+ int containerViewId = frameLayout == null ? R.id.car_setup_wizard_layout :
+ R.id.empty_fragment_frame_layout;
+ Log.v(TAG, "fragmentContainerViewId: "
+ + getResources().getResourceEntryName(containerViewId));
+ return containerViewId;
+
+ }
+
+ @VisibleForTesting
+ void inflateEmptyFragmentFrameLayout() {
+ ViewStub viewStub = findViewById(R.id.layout_content_stub);
+ if (viewStub != null) {
+ viewStub.setLayoutResource(R.layout.empty_fragment_frame_layout);
+ viewStub.inflate();
+ }
+ }
+
+ @VisibleForTesting
boolean getAllowFragmentCommits() {
return mAllowFragmentCommits;
}
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
index 715315a..4fd1808 100644
--- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
@@ -18,6 +18,7 @@ package com.android.car.setupwizardlib;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.Typeface;
@@ -39,14 +40,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
-
import com.android.car.setupwizardlib.partner.PartnerConfig;
import com.android.car.setupwizardlib.partner.PartnerConfigHelper;
-
+import com.android.car.setupwizardlib.util.FeatureResolver;
import java.util.Locale;
import java.util.Objects;
@@ -56,17 +55,20 @@ import java.util.Objects;
* done through methods provided by this class unless that is not possible so as to keep the state
* internally consistent.
*/
-class CarSetupWizardBaseLayout extends LinearLayout {
+class CarSetupWizardBaseLayout extends LinearLayout implements CarSetupWizardLayoutInterface {
private static final String TAG = CarSetupWizardBaseLayout.class.getSimpleName();
private static final int INVALID_COLOR = 0;
// For mirroring an image
private static final float IMAGE_MIRROR_ROTATION = 180.0f;
+ private static final float MIN_ULTRA_WIDE_CONTENT_WIDTH = 1240.0f;
private View mBackButton;
private View mCloseButton;
private View mTitleBar;
private TextView mToolbarTitle;
private PartnerConfigHelper mPartnerConfigHelper;
+ private boolean mSupportsSplitNavLayout;
+ private boolean mSupportsRotaryControl;
/* <p>The Primary Toolbar Button should always be used when there is only a single action that
* moves the wizard to the next screen (e.g. Only need a 'Skip' button).
@@ -95,7 +97,7 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
CarSetupWizardBaseLayout(Context context, @Nullable AttributeSet attrs,
- int defStyleAttr) {
+ int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
@@ -104,7 +106,7 @@ class CarSetupWizardBaseLayout extends LinearLayout {
* the custom views that can be set by the user (e.g. back button, continue button).
*/
CarSetupWizardBaseLayout(Context context, @Nullable AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
+ int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mPartnerConfigHelper = PartnerConfigHelper.get(context);
@@ -164,12 +166,19 @@ class CarSetupWizardBaseLayout extends LinearLayout {
R.styleable.CarSetupWizardBaseLayout_showProgressBar, false);
indeterminateProgressBar = attrArray.getBoolean(
R.styleable.CarSetupWizardBaseLayout_indeterminateProgressBar, true);
+ mSupportsSplitNavLayout = attrArray.getBoolean(
+ R.styleable.CarSetupWizardBaseLayout_supportsSplitNavLayout, false);
+ mSupportsRotaryControl = attrArray.getBoolean(
+ R.styleable.CarSetupWizardBaseLayout_supportsRotaryControl, false);
} finally {
attrArray.recycle();
}
LayoutInflater inflater = LayoutInflater.from(getContext());
- inflater.inflate(R.layout.car_setup_wizard_layout, this);
+ inflater.inflate(getLayoutResourceId(), this);
+
+ maybeSetUltraWideScreenContentWidth();
+
View toolbar = findViewById(R.id.application_bar);
// The toolbar will not be mirrored in RTL
toolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
@@ -206,10 +215,15 @@ class CarSetupWizardBaseLayout extends LinearLayout {
// Se the title bar.
setTitleBar(findViewById(R.id.application_bar));
- int toolbarBgColor =
- mPartnerConfigHelper.getColor(getContext(), PartnerConfig.CONFIG_TOOLBAR_BG_COLOR);
- if (toolbarBgColor != 0) {
- mTitleBar.setBackgroundColor(toolbarBgColor);
+ if (isSplitNavLayoutUsed()) {
+ mTitleBar.setBackgroundColor(getResources()
+ .getColor(R.color.suw_color_split_nav_toolbar_background, null));
+ } else {
+ int toolbarBgColor = mPartnerConfigHelper.getColor(
+ getContext(), PartnerConfig.CONFIG_TOOLBAR_BG_COLOR);
+ if (toolbarBgColor != 0) {
+ mTitleBar.setBackgroundColor(toolbarBgColor);
+ }
}
// Set the toolbar title visibility and text based on the custom attributes.
@@ -264,7 +278,25 @@ class CarSetupWizardBaseLayout extends LinearLayout {
initDivider();
// Set orientation programmatically since the inflated layout uses <merge>
- setOrientation(LinearLayout.VERTICAL);
+ if (isSplitNavLayoutUsed() && getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE) {
+ setOrientation(LinearLayout.HORIZONTAL);
+ // The vertical bar will not be mirrored in RTL
+ setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+
+ View contentContainer = getContentContainer();
+ if (contentContainer != null) {
+ // The content should be mirrored in RTL
+ contentContainer.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
+ }
+ View actionBar = findViewById(R.id.button_container);
+ if (actionBar != null) {
+ // The action bar will not be mirrored in RTL
+ actionBar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+ }
+ } else {
+ setOrientation(LinearLayout.VERTICAL);
+ }
}
/**
@@ -400,6 +432,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
* Sets the header title visibility to given value.
*/
public void setToolbarTitleVisible(boolean visible) {
+ if (mToolbarTitle == null) {
+ return;
+ }
setViewVisible(mToolbarTitle, visible);
}
@@ -407,6 +442,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
* Sets the header title text to the provided text.
*/
public void setToolbarTitleText(String text) {
+ if (mToolbarTitle == null) {
+ return;
+ }
mToolbarTitle.setText(text);
}
@@ -414,6 +452,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
* Sets the style for the toolbar title.
*/
public void setToolbarTitleStyle(@StyleRes int style) {
+ if (mToolbarTitle == null) {
+ return;
+ }
mToolbarTitle.setTextAppearance(style);
}
@@ -557,28 +598,109 @@ class CarSetupWizardBaseLayout extends LinearLayout {
return mProgressBar;
}
- /**
- * Sets the progress bar visibility to the given visibility.
- */
+ @Override
public void setProgressBarVisible(boolean visible) {
setViewVisible(mProgressBar, visible);
}
- /**
- * Sets the progress bar indeterminate/determinate state.
- */
+ @Override
public void setProgressBarIndeterminate(boolean indeterminate) {
mProgressBar.setIndeterminate(indeterminate);
}
- /**
- * Sets the progress bar's progress.
- */
+ @Override
public void setProgressBarProgress(int progress) {
setProgressBarIndeterminate(false);
mProgressBar.setProgress(progress);
}
+ @Override
+ public Button getPrimaryActionButton() {
+ return getPrimaryToolbarButton();
+ }
+
+ @Override
+ public void setPrimaryActionButtonVisible(boolean visible) {
+ setPrimaryToolbarButtonVisible(visible);
+ }
+
+ @Override
+ public void setPrimaryActionButtonEnabled(boolean enabled) {
+ setPrimaryToolbarButtonEnabled(enabled);
+ }
+
+ @Override
+ public void setPrimaryActionButtonText(String text) {
+ setPrimaryToolbarButtonText(text);
+ }
+
+ @Override
+ public void setPrimaryActionButtonListener(@Nullable View.OnClickListener listener) {
+ setPrimaryToolbarButtonListener(listener);
+ }
+
+ @Override
+ public void setPrimaryActionButtonFlat(boolean isFlat) {
+ setPrimaryToolbarButtonFlat(isFlat);
+ }
+
+ @Override
+ public boolean isPrimaryActionButtonFlat() {
+ return getPrimaryToolbarButtonFlat();
+ }
+
+ @Override
+ public Button getSecondaryActionButton() {
+ return getSecondaryToolbarButton();
+ }
+
+ @Override
+ public void setSecondaryActionButtonVisible(boolean visible) {
+ setSecondaryToolbarButtonVisible(visible);
+ }
+
+ @Override
+ public void setSecondaryActionButtonEnabled(boolean enabled) {
+ setSecondaryToolbarButtonEnabled(enabled);
+ }
+
+ @Override
+ public void setSecondaryActionButtonText(String text) {
+ setSecondaryToolbarButtonText(text);
+ }
+
+ @Override
+ public void setSecondaryActionButtonListener(@Nullable View.OnClickListener listener) {
+ setSecondaryToolbarButtonListener(listener);
+ }
+
+ /**
+ * Returns whether split-nav layout is currently being used. Do not use this API to determine
+ * whether content ViewStub should be inflated. Use {@code getContentViewStub} for that purpose.
+ */
+ public boolean isSplitNavLayoutUsed() {
+ boolean isSplitNavLayoutEnabled = FeatureResolver.get(getContext())
+ .isSplitNavLayoutFeatureEnabled();
+ return mSupportsSplitNavLayout && isSplitNavLayoutEnabled;
+ }
+
+ /**
+ * Returns the content ViewStub of the split-nav layout.
+ *
+ * @deprecated Use {@code getContentViewStub}.
+ */
+ @Deprecated
+ public ViewStub getSplitNavContentViewStub() {
+ return findViewById(R.id.layout_content_stub);
+ }
+
+ /**
+ * Returns the content ViewStub when split-nav layout is used or rotary control is supported
+ */
+ public ViewStub getContentViewStub() {
+ return findViewById(R.id.layout_content_stub);
+ }
+
/**
* Sets the locale to be used for rendering.
*/
@@ -588,8 +710,10 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
int direction = TextUtils.getLayoutDirectionFromLocale(locale);
- mToolbarTitle.setTextLocale(locale);
- mToolbarTitle.setLayoutDirection(direction);
+ if (mToolbarTitle != null) {
+ mToolbarTitle.setTextLocale(locale);
+ mToolbarTitle.setLayoutDirection(direction);
+ }
mPrimaryToolbarButton.setTextLocale(locale);
mPrimaryToolbarButton.setLayoutDirection(direction);
@@ -641,7 +765,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
}
- /** Sets button text color using partner overlay if exists */
+ /**
+ * Sets button text color using partner overlay if exists
+ */
@VisibleForTesting
void setButtonTextColor(TextView button, PartnerConfig config) {
ColorStateList colorStateList =
@@ -669,7 +795,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
}
- /** Sets button background color using partner overlay if exists */
+ /**
+ * Sets button background color using partner overlay if exists
+ */
@VisibleForTesting
void setBackgroundColor(View button, PartnerConfig config) {
ColorStateList color = mPartnerConfigHelper.getColorStateList(getContext(), config);
@@ -678,7 +806,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
}
- /** Sets button text size using partner overlay if exists */
+ /**
+ * Sets button text size using partner overlay if exists
+ */
@VisibleForTesting
void setButtonTextSize(TextView button) {
float dimension = mPartnerConfigHelper.getDimension(
@@ -692,13 +822,13 @@ class CarSetupWizardBaseLayout extends LinearLayout {
@VisibleForTesting
boolean shouldMirrorNavIcons() {
return getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- && mPartnerConfigHelper.getBoolean(
- getContext(),
- PartnerConfig.CONFIG_TOOLBAR_NAV_ICON_MIRRORING_IN_RTL,
- true);
+ && mPartnerConfigHelper.getBoolean(
+ getContext(), PartnerConfig.CONFIG_TOOLBAR_NAV_ICON_MIRRORING_IN_RTL, true);
}
- /** Sets button type face with partner overlay if exists */
+ /**
+ * Sets button type face with partner overlay if exists
+ */
private void setButtonTypeFace(TextView button) {
String fontFamily = mPartnerConfigHelper.getString(
getContext(),
@@ -716,7 +846,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
button.setTypeface(typeface);
}
- /** Sets button radius using partner overlay if exists */
+ /**
+ * Sets button radius using partner overlay if exists
+ */
private void setButtonRadius(Button button) {
float radius = mPartnerConfigHelper.getDimension(
getContext(),
@@ -760,8 +892,23 @@ class CarSetupWizardBaseLayout extends LinearLayout {
setButtonTextColor(primaryButton, textColorConfig);
}
+ private int getLayoutResourceId() {
+ if (isSplitNavLayoutUsed()) {
+ return mSupportsRotaryControl
+ ? R.layout.rotary_split_nav_layout
+ : R.layout.split_nav_layout;
+ }
+
+ return mSupportsRotaryControl
+ ? R.layout.rotary_car_setup_wizard_layout
+ : R.layout.car_setup_wizard_layout;
+ }
+
private void initDivider() {
mDivider = findViewById(R.id.divider);
+ if (mDivider == null) {
+ return;
+ }
float dividerHeight = mPartnerConfigHelper.getDimension(
getContext(),
PartnerConfig.CONFIG_TOOLBAR_DIVIDER_LINE_WEIGHT);
@@ -791,7 +938,9 @@ class CarSetupWizardBaseLayout extends LinearLayout {
if (drawable instanceof InsetDrawable) {
return getGradientDrawableFromInsetDrawable((InsetDrawable) drawable);
}
- return (GradientDrawable) drawable;
+ if (drawable instanceof GradientDrawable) {
+ return (GradientDrawable) drawable;
+ }
}
return null;
@@ -803,4 +952,53 @@ class CarSetupWizardBaseLayout extends LinearLayout {
}
return null;
}
+
+ private void maybeSetUltraWideScreenContentWidth() {
+ View contentContainer = findViewById(R.id.ultra_wide_content_container);
+ if (contentContainer == null) {
+ return;
+ }
+
+ float configurableContentWidth = mPartnerConfigHelper.getDimension(
+ getContext(),
+ PartnerConfig.CONFIG_ULTRA_WIDE_SCREEN_CONTENT_WIDTH);
+
+ float pxMinWidth = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ MIN_ULTRA_WIDE_CONTENT_WIDTH,
+ getResources().getDisplayMetrics());
+
+ if (configurableContentWidth >= pxMinWidth) {
+ ViewGroup.LayoutParams layoutParams = contentContainer.getLayoutParams();
+ layoutParams.width = (int) configurableContentWidth;
+ Log.d(TAG, String.format("Applying content width %f px", configurableContentWidth));
+ contentContainer.setLayoutParams(layoutParams);
+ } else {
+ if (configurableContentWidth != 0) {
+ Log.w(TAG, String.format("The minimum ultra wide screen content width is %d dp",
+ (int) MIN_ULTRA_WIDE_CONTENT_WIDTH));
+ }
+
+ LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
+ 0, LayoutParams.MATCH_PARENT);
+ contentParams.weight = 1;
+ contentContainer.setLayoutParams(contentParams);
+
+ LinearLayout.LayoutParams fillerParams = new LinearLayout.LayoutParams(
+ 0, LayoutParams.MATCH_PARENT);
+ fillerParams.weight = 0;
+ View filler = findViewById(R.id.ultra_wide_space_filler);
+ filler.setLayoutParams(fillerParams);
+ }
+ }
+
+ private View getContentContainer() {
+ View contentContainer = findViewById(R.id.content_container);
+ if (contentContainer == null) {
+ // Try ultra-wide container
+ return findViewById(R.id.ultra_wide_content_container);
+
+ }
+ return contentContainer;
+ }
}
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayout.java
index f5191cc..72f4f1b 100644
--- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayout.java
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayout.java
@@ -18,7 +18,6 @@ package com.android.car.setupwizardlib;
import android.content.Context;
import android.util.AttributeSet;
-
import androidx.annotation.Nullable;
/**
@@ -43,5 +42,7 @@ public class CarSetupWizardCompatLayout extends CarSetupWizardBaseLayout {
public CarSetupWizardCompatLayout(Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+
+ setBackgroundColor(getResources().getColor(R.color.suw_color_background, null));
}
}
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardDesignLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardDesignLayout.java
index 92269f0..c0a1831 100644
--- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardDesignLayout.java
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardDesignLayout.java
@@ -18,9 +18,7 @@ package com.android.car.setupwizardlib;
import android.content.Context;
import android.util.AttributeSet;
-
import androidx.annotation.Nullable;
-
import com.android.car.setupwizardlib.partner.PartnerConfig;
import com.android.car.setupwizardlib.partner.PartnerConfigHelper;
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayout.java
index 19a1923..67bb795 100644
--- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayout.java
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayout.java
@@ -38,14 +38,11 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
-
import com.android.car.setupwizardlib.partner.PartnerConfig;
import com.android.car.setupwizardlib.partner.PartnerConfigHelper;
-
import java.util.Locale;
import java.util.Objects;
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayoutInterface.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayoutInterface.java
new file mode 100644
index 0000000..7126560
--- /dev/null
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardLayoutInterface.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.setupwizardlib;
+
+import android.view.View;
+import android.widget.Button;
+import androidx.annotation.Nullable;
+
+/**
+ * The interface defines the functionality of the layouts used in CarSetupWizard. It
+ * makes it easy to switch to a different layout.
+ */
+public interface CarSetupWizardLayoutInterface {
+
+ /** Returns the primary action button. */
+ Button getPrimaryActionButton();
+
+ /** Sets whether the primary action button is visible. */
+ void setPrimaryActionButtonVisible(boolean visible);
+
+ /** Sets whether the primary action button is enabled. */
+ void setPrimaryActionButtonEnabled(boolean enabled);
+
+ /** Sets the text of the primary action button. */
+ void setPrimaryActionButtonText(String text);
+
+ /**
+ * Sets the onClick listener of the primary action button.
+ *
+ * @param listener the listener to be set. When it's null, the previously set listener will be
+ * removed
+ */
+ void setPrimaryActionButtonListener(@Nullable View.OnClickListener listener);
+
+ /** Sets whether the primary action button is flat which means it does not have a background. */
+ void setPrimaryActionButtonFlat(boolean isFlat);
+
+ /** Returns whether the primary action button is flat. */
+ boolean isPrimaryActionButtonFlat();
+
+ /** Returns the secondary action button. */
+ Button getSecondaryActionButton();
+
+ /** Sets whether the secondary action button is visible. */
+ void setSecondaryActionButtonVisible(boolean visible);
+
+ /** Sets whether the secondary action button is enabled. */
+ void setSecondaryActionButtonEnabled(boolean enabled);
+
+ /** Sets the text of the secondary action button. */
+ void setSecondaryActionButtonText(String text);
+
+ /**
+ * Sets the onClick listener of the secondary action button.
+ *
+ * @param listener the listener to be set. When it's null, the previously set listener will be
+ * removed
+ */
+ void setSecondaryActionButtonListener(@Nullable View.OnClickListener listener);
+
+ /** Sets whether the progress bar is visible. */
+ void setProgressBarVisible(boolean visible);
+
+ /** Sets whether the progress bar is indeterminate. */
+ void setProgressBarIndeterminate(boolean indeterminate);
+
+ /** Sets the progress bar's progress. */
+ void setProgressBarProgress(int progress);
+}
diff --git a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java
index 54d1e6e..2ee8d07 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java
@@ -83,7 +83,10 @@ public enum PartnerConfig {
PartnerConfigKey.KEY_LOADING_INDICATOR_LINE_WEIGHT, ResourceType.DIMENSION),
CONFIG_LAYOUT_BG_COLOR(
- PartnerConfigKey.KEY_LAYOUT_BG_COLOR, ResourceType.COLOR);
+ PartnerConfigKey.KEY_LAYOUT_BG_COLOR, ResourceType.COLOR),
+
+ CONFIG_ULTRA_WIDE_SCREEN_CONTENT_WIDTH(
+ PartnerConfigKey.KEY_ULTRA_WIDE_SCREEN_CONTENT_WIDTH, ResourceType.DIMENSION);
public enum ResourceType {
COLOR,
diff --git a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java
index dfb134f..093961b 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigHelper.java
@@ -27,12 +27,10 @@ import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
-
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-
import java.util.EnumMap;
/** The helper reads and caches the partner configurations from Car Setup Wizard. */
diff --git a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
index 7f9dadd..e7800d1 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
@@ -44,7 +44,8 @@ import java.lang.annotation.RetentionPolicy;
PartnerConfigKey.KEY_TOOLBAR_DIVIDER_LINE_WEIGHT,
PartnerConfigKey.KEY_LOADING_INDICATOR_COLOR,
PartnerConfigKey.KEY_LOADING_INDICATOR_LINE_WEIGHT,
- PartnerConfigKey.KEY_LAYOUT_BG_COLOR
+ PartnerConfigKey.KEY_LAYOUT_BG_COLOR,
+ PartnerConfigKey.KEY_ULTRA_WIDE_SCREEN_CONTENT_WIDTH
})
/** Resource names that can be customized by partner overlay APK. */
@@ -96,4 +97,6 @@ public @interface PartnerConfigKey {
String KEY_LOADING_INDICATOR_LINE_WEIGHT = "suw_compat_loading_indicator_line_weight";
String KEY_LAYOUT_BG_COLOR = "suw_design_layout_bg_color";
+
+ String KEY_ULTRA_WIDE_SCREEN_CONTENT_WIDTH = "suw_compat_ultra_wide_screen_content_width";
}
diff --git a/library/main/src/com/android/car/setupwizardlib/partner/ResourceEntry.java b/library/main/src/com/android/car/setupwizardlib/partner/ResourceEntry.java
index 6d5d39b..456f1e6 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/ResourceEntry.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/ResourceEntry.java
@@ -18,7 +18,6 @@ package com.android.car.setupwizardlib.partner;
import android.content.pm.PackageManager;
import android.os.Bundle;
-
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
diff --git a/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java b/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java
index 2dfb04b..84842f3 100644
--- a/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java
+++ b/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java
@@ -27,9 +27,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
-
import androidx.annotation.Nullable;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -151,11 +149,13 @@ public class PartnerSummaryActionsCollector {
String completedDescription =
summaryStateBundle.getString(EXTRA_SUMMARY_COMPLETED_DESCRIPTION, description);
+ SummaryActionState completeState = completed
+ ? SummaryActionState.COMPLETED : SummaryActionState.NOT_COMPLETED;
return new SummaryAction(
title,
description,
requiresNetwork,
- completed,
+ completeState,
priority,
scriptUri,
hasUnfinishedDependency,
diff --git a/library/main/src/com/android/car/setupwizardlib/summary/SummaryAction.java b/library/main/src/com/android/car/setupwizardlib/summary/SummaryAction.java
index 6f9e626..55d71d7 100644
--- a/library/main/src/com/android/car/setupwizardlib/summary/SummaryAction.java
+++ b/library/main/src/com/android/car/setupwizardlib/summary/SummaryAction.java
@@ -28,7 +28,7 @@ public class SummaryAction implements Comparable<SummaryAction> {
public final int priority;
public final boolean hasUnfinishedDependency;
public final String dependencyDescription;
- public final boolean completed;
+ public final SummaryActionState completeState;
public final String iconResourceName;
public final String completedDescription;
@@ -36,7 +36,7 @@ public class SummaryAction implements Comparable<SummaryAction> {
String actionTitle,
String actionDescription,
boolean requiresNetwork,
- boolean completed,
+ SummaryActionState completeState,
int priority,
String scriptUri,
boolean hasUnfinishedDependency,
@@ -46,7 +46,7 @@ public class SummaryAction implements Comparable<SummaryAction> {
this.actionTitle = actionTitle;
this.actionDescription = actionDescription;
this.requiresNetwork = requiresNetwork;
- this.completed = completed;
+ this.completeState = completeState;
this.priority = priority;
this.scriptUri = scriptUri;
this.hasUnfinishedDependency = hasUnfinishedDependency;
@@ -55,6 +55,11 @@ public class SummaryAction implements Comparable<SummaryAction> {
this.completedDescription = completedDescription;
}
+ /** Returns {@code true} if the action is completed. */
+ public boolean isCompleted() {
+ return completeState == SummaryActionState.COMPLETED;
+ }
+
@Override
public int compareTo(@NonNull SummaryAction o) {
if (o == null) {
diff --git a/library/main/src/com/android/car/setupwizardlib/summary/SummaryActionState.java b/library/main/src/com/android/car/setupwizardlib/summary/SummaryActionState.java
new file mode 100644
index 0000000..2b7daf2
--- /dev/null
+++ b/library/main/src/com/android/car/setupwizardlib/summary/SummaryActionState.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.setupwizardlib.summary;
+
+/** Complete state of the action. */
+public enum SummaryActionState {
+ COMPLETED,
+ NOT_COMPLETED,
+ WAITING_TO_RESOLVE
+}
diff --git a/library/main/src/com/android/car/setupwizardlib/util/CarDrivingStateMonitor.java b/library/main/src/com/android/car/setupwizardlib/util/CarDrivingStateMonitor.java
index c58e352..9528502 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/CarDrivingStateMonitor.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/CarDrivingStateMonitor.java
@@ -33,13 +33,12 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
-
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
/**
* Monitor that listens for changes in the driving state so that it can trigger an exit of the
- * setup wizard when {@link CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP}
+ * setup wizard when {@link CarUxRestrictions#UX_RESTRICTIONS_NO_SETUP}
* is active.
*/
public class CarDrivingStateMonitor implements
diff --git a/library/main/src/com/android/car/setupwizardlib/util/CarHelperRegistry.java b/library/main/src/com/android/car/setupwizardlib/util/CarHelperRegistry.java
index 01447aa..148ba32 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/CarHelperRegistry.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/CarHelperRegistry.java
@@ -17,11 +17,9 @@
package com.android.car.setupwizardlib.util;
import android.content.Context;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-
import java.util.concurrent.ConcurrentHashMap;
/** A registry of singleton-like helpers, which can be injected by the application for testing. */
diff --git a/library/main/src/com/android/car/setupwizardlib/util/CarSetupWizardUiUtils.java b/library/main/src/com/android/car/setupwizardlib/util/CarSetupWizardUiUtils.java
index 4e1d8ca..2740455 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/CarSetupWizardUiUtils.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/CarSetupWizardUiUtils.java
@@ -38,6 +38,9 @@ public final class CarSetupWizardUiUtils {
public static final String EXTRA_NEW_LANDSCAPE_LAYOUT_SUPPORTED =
"extra_new_landscape_layout_supported";
+ /* Setup Wizard Package Name **/
+ public static final String SETUP_WIZARD_PACKAGE = "com.google.android.car.setupwizard";
+
/** Hide system UI */
public static void hideSystemUI(Activity activity) {
maybeHideSystemUI(activity);
diff --git a/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java b/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java
index ff83b55..8f67220 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java
@@ -20,153 +20,144 @@ import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
-/**
- * <p>Derived from {@code com.android.setupwizardlib/WizardManagerHelper.java}
- */
+/** Derived from {@code com.android.setupwizardlib/WizardManagerHelper.java} */
public final class CarWizardManagerHelper {
- public static final String EXTRA_WIZARD_BUNDLE = "wizardBundle";
- public static final String EXTRA_IS_FIRST_RUN = "firstRun";
- public static final String EXTRA_IS_DEALER = "dealer";
- public static final String EXTRA_IS_DEFERRED_SETUP = "deferredSetup";
- private static final String ACTION_NEXT = "com.android.wizard.NEXT";
- private static final String EXTRA_RESULT_CODE = "com.android.setupwizard.ResultCode";
-
- private CarWizardManagerHelper() {
- }
+ public static final String EXTRA_WIZARD_BUNDLE = "wizardBundle";
+ public static final String EXTRA_IS_FIRST_RUN = "firstRun";
+ public static final String EXTRA_IS_DEALER = "dealer";
+ public static final String EXTRA_IS_DEFERRED_SETUP = "deferredSetup";
+ private static final String ACTION_NEXT = "com.android.wizard.NEXT";
+ private static final String EXTRA_RESULT_CODE = "com.android.setupwizard.ResultCode";
- /**
- * Get an intent that will invoke the next step of setup wizard.
- *
- * @param originalIntent The original intent that was used to start the step, usually via
- * {@link android.app.Activity#getIntent()}.
- * @param resultCode The result code of the step. See {@link ResultCodes}.
- * @return A new intent that can be used with
- * {@link android.app.Activity#startActivityForResult(Intent, int)} to start the next
- * step of the setup flow.
- */
- public static Intent getNextIntent(Intent originalIntent, int resultCode) {
- return getNextIntent(originalIntent, resultCode, null);
- }
+ private CarWizardManagerHelper() {}
- /**
- * Get an intent that will invoke the next step of setup wizard.
- *
- * @param originalIntent The original intent that was used to start the step, usually via
- * {@link android.app.Activity#getIntent()}.
- * @param resultCode The result code of the step. See {@link ResultCodes}.
- * @param data An intent containing extra result data.
- * @return A new intent that can be used with
- * {@link android.app.Activity#startActivityForResult(Intent, int)} to start the next
- * step of the setup flow.
- */
- public static Intent getNextIntent(Intent originalIntent, int resultCode, Intent data) {
- Intent intent = new Intent(ACTION_NEXT);
- copyWizardManagerExtras(originalIntent, intent);
- intent.putExtra(EXTRA_RESULT_CODE, resultCode);
- if (data != null && data.getExtras() != null) {
- intent.putExtras(data.getExtras());
- }
+ /**
+ * Get an intent that will invoke the next step of setup wizard.
+ *
+ * @param originalIntent The original intent that was used to start the step, usually via {@link
+ * android.app.Activity#getIntent()}.
+ * @param resultCode The result code of the step. See {@link ResultCodes}.
+ * @return A new intent that can be used with {@link
+ * android.app.Activity#startActivityForResult(Intent, int)} to start the next step of the
+ * setup flow.
+ */
+ public static Intent getNextIntent(Intent originalIntent, int resultCode) {
+ return getNextIntent(originalIntent, resultCode, null);
+ }
- return intent;
+ /**
+ * Get an intent that will invoke the next step of setup wizard.
+ *
+ * @param originalIntent The original intent that was used to start the step, usually via {@link
+ * android.app.Activity#getIntent()}.
+ * @param resultCode The result code of the step. See {@link ResultCodes}.
+ * @param data An intent containing extra result data.
+ * @return A new intent that can be used with {@link
+ * android.app.Activity#startActivityForResult(Intent, int)} to start the next step of the
+ * setup flow.
+ */
+ public static Intent getNextIntent(Intent originalIntent, int resultCode, Intent data) {
+ Intent intent = new Intent(ACTION_NEXT);
+ copyWizardManagerExtras(originalIntent, intent);
+ intent.putExtra(EXTRA_RESULT_CODE, resultCode);
+ if (data != null && data.getExtras() != null) {
+ intent.putExtras(data.getExtras());
}
- /**
- * Copy the internal extras used by setup wizard from one intent to another. For low-level use
- * only, such as when using {@link Intent#FLAG_ACTIVITY_FORWARD_RESULT} to relay to another
- * intent.
- *
- * @param srcIntent Intent to get the wizard manager extras from.
- * @param dstIntent Intent to copy the wizard manager extras to.
- */
- public static void copyWizardManagerExtras(Intent srcIntent, Intent dstIntent) {
- dstIntent.putExtra(EXTRA_WIZARD_BUNDLE, srcIntent.getBundleExtra(EXTRA_WIZARD_BUNDLE));
- dstIntent.putExtra(EXTRA_IS_FIRST_RUN,
- srcIntent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false));
- dstIntent.putExtra(EXTRA_IS_DEALER,
- srcIntent.getBooleanExtra(EXTRA_IS_DEALER, false));
- dstIntent.putExtra(EXTRA_IS_DEFERRED_SETUP,
- srcIntent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false));
- }
+ return intent;
+ }
- /**
- * Check whether an intent is intended to be used within the setup wizard flow.
- *
- * @param intent The intent to be checked, usually from
- * {@link android.app.Activity#getIntent()}.
- * @return true if the intent passed in was intended to be used with setup wizard.
- */
- public static boolean isSetupWizardIntent(Intent intent) {
- return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
- }
+ /**
+ * Copy the internal extras used by setup wizard from one intent to another. For low-level use
+ * only, such as when using {@link Intent#FLAG_ACTIVITY_FORWARD_RESULT} to relay to another
+ * intent.
+ *
+ * @param srcIntent Intent to get the wizard manager extras from.
+ * @param dstIntent Intent to copy the wizard manager extras to.
+ */
+ public static void copyWizardManagerExtras(Intent srcIntent, Intent dstIntent) {
+ dstIntent.putExtra(EXTRA_WIZARD_BUNDLE, srcIntent.getBundleExtra(EXTRA_WIZARD_BUNDLE));
+ dstIntent.putExtra(EXTRA_IS_FIRST_RUN, srcIntent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false));
+ dstIntent.putExtra(EXTRA_IS_DEALER, srcIntent.getBooleanExtra(EXTRA_IS_DEALER, false));
+ dstIntent.putExtra(
+ EXTRA_IS_DEFERRED_SETUP, srcIntent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false));
+ }
- /**
- * Checks whether an intent is running in the deferred setup wizard flow.
- *
- * @param intent The intent to be checked, usually from
- * {@link android.app.Activity#getIntent()}.
- * @return true if the intent passed in was running in deferred setup wizard.
- */
- public static boolean isDeferredIntent(Intent intent) {
- return intent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false);
- }
+ /**
+ * Check whether an intent is intended to be used within the setup wizard flow.
+ *
+ * @param intent The intent to be checked, usually from {@link android.app.Activity#getIntent()}.
+ * @return true if the intent passed in was intended to be used with setup wizard.
+ */
+ public static boolean isSetupWizardIntent(Intent intent) {
+ return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
+ }
- /**
- * Check whether an intent is intended for the dealer.
- *
- * @param intent The intent to be checked, usually from
- * {@link android.app.Activity#getIntent()}.
- * @return true if the intent passed in was intended to be used with setup wizard.
- */
- public static boolean isDealerIntent(Intent intent) {
- return intent.getBooleanExtra(EXTRA_IS_DEALER, false);
- }
+ /**
+ * Checks whether an intent is running in the deferred setup wizard flow.
+ *
+ * @param intent The intent to be checked, usually from {@link android.app.Activity#getIntent()}.
+ * @return true if the intent passed in was running in deferred setup wizard.
+ */
+ public static boolean isDeferredIntent(Intent intent) {
+ return intent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false);
+ }
- /**
- * Checks whether the current user has completed Setup Wizard. This is true if the current user
- * has gone through Setup Wizard. The current user may or may not be the device owner and the
- * device owner may have already completed setup wizard.
- *
- * @param context The context to retrieve the settings.
- * @return true if the current user has completed Setup Wizard.
- * @see #isDeviceProvisioned(Context)
- */
- public static boolean isUserSetupComplete(Context context) {
- return Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0) == 1;
- }
+ /**
+ * Check whether an intent is intended for the dealer.
+ *
+ * @param intent The intent to be checked, usually from {@link android.app.Activity#getIntent()}.
+ * @return true if the intent passed in was intended to be used with setup wizard.
+ */
+ public static boolean isDealerIntent(Intent intent) {
+ return intent.getBooleanExtra(EXTRA_IS_DEALER, false);
+ }
- /**
- * Checks whether the device is provisioned. This means that the device has gone through Setup
- * Wizard at least once. Note that the user can still be in Setup Wizard even if this is true,
- * for a secondary user profile triggered through Settings > Add account.
- *
- * @param context The context to retrieve the settings.
- * @return true if the device is provisioned.
- * @see #isUserSetupComplete(Context)
- */
- public static boolean isDeviceProvisioned(Context context) {
- return Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) == 1;
- }
- /**
- * Checks whether an intent is running in the initial setup wizard flow.
- *
- * @param intent The intent to be checked, usually from {@link Activity#getIntent()}.
- * @return true if the intent passed in was intended to be used with setup wizard.
- */
- public static boolean isInitialSetupWizard(Intent intent) {
- return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
- }
+ /**
+ * Checks whether the current user has completed Setup Wizard. This is true if the current user
+ * has gone through Setup Wizard. The current user may or may not be the device owner and the
+ * device owner may have already completed setup wizard.
+ *
+ * @param context The context to retrieve the settings.
+ * @return true if the current user has completed Setup Wizard.
+ * @see #isDeviceProvisioned(Context)
+ */
+ public static boolean isUserSetupComplete(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0) == 1;
+ }
- /**
- * Checks whether an intent is running in the deferred setup wizard flow.
- *
- * @param originalIntent The original intent that was used to start the step, usually via {@link
- * Activity#getIntent()}.
- * @return true if the intent passed in was running in deferred setup wizard.
- */
- public static boolean isDeferredSetupWizard(Intent originalIntent) {
- return originalIntent != null && originalIntent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP,
- false);
- }
+ /**
+ * Checks whether the device is provisioned. This means that the device has gone through Setup
+ * Wizard at least once. Note that the user can still be in Setup Wizard even if this is true, for
+ * a secondary user profile triggered through Settings > Add account.
+ *
+ * @param context The context to retrieve the settings.
+ * @return true if the device is provisioned.
+ * @see #isUserSetupComplete(Context)
+ */
+ public static boolean isDeviceProvisioned(Context context) {
+ return Settings.Global.getInt(
+ context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0)
+ == 1;
+ }
+ /**
+ * Checks whether an intent is running in the initial setup wizard flow.
+ *
+ * @param intent The intent to be checked, usually from {@link android.app.Activity#getIntent()}
+ * @return true if the intent passed in was intended to be used with setup wizard.
+ */
+ public static boolean isInitialSetupWizard(Intent intent) {
+ return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
+ }
+
+ /**
+ * Checks whether an intent is running in the deferred setup wizard flow.
+ *
+ * @param originalIntent The original intent that was used to start the step, usually via {@link
+ * android.app.Activity#getIntent()}.
+ * @return true if the intent passed in was running in deferred setup wizard.
+ */
+ public static boolean isDeferredSetupWizard(Intent originalIntent) {
+ return originalIntent != null && originalIntent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false);
+ }
}
diff --git a/library/main/src/com/android/car/setupwizardlib/util/FeatureResolver.java b/library/main/src/com/android/car/setupwizardlib/util/FeatureResolver.java
new file mode 100644
index 0000000..8f0114f
--- /dev/null
+++ b/library/main/src/com/android/car/setupwizardlib/util/FeatureResolver.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.setupwizardlib.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A class to resolve feature enablement and versions
+ */
+public class FeatureResolver {
+
+ private static final String TAG = FeatureResolver.class.getSimpleName();
+ private static volatile FeatureResolver sInstance = null;
+
+ static final String AUTHORITY =
+ CarSetupWizardUiUtils.SETUP_WIZARD_PACKAGE + ".feature_management";
+ static final String GET_FEATURE_VERSION_METHOD = "getFeatureVersion";
+ static final String SPLIT_NAV_LAYOUT_FEATURE = "split_nav_layout";
+ static final String G_MODAL_FEATURE = "g_modal";
+ static final String VALUE = "value";
+
+ private Context mContext;
+
+ private Map<String, Bundle> mResultMap = new HashMap<>();
+
+ /**
+ * Factory method to get an instance
+ */
+ public static FeatureResolver get(@NonNull Context context) {
+ if (sInstance == null) {
+ synchronized (FeatureResolver.class) {
+ if (sInstance == null) {
+ sInstance = new FeatureResolver(context);
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * Returns whether the alternative layout feature is enabled
+ */
+ public boolean isSplitNavLayoutFeatureEnabled() {
+ Bundle bundle;
+ if (mResultMap.containsKey(SPLIT_NAV_LAYOUT_FEATURE)) {
+ bundle = mResultMap.get(SPLIT_NAV_LAYOUT_FEATURE);
+ } else {
+ bundle = getFeatureBundle(SPLIT_NAV_LAYOUT_FEATURE);
+ mResultMap.put(SPLIT_NAV_LAYOUT_FEATURE, bundle);
+ }
+ boolean isSplitNavLayoutFeatureEnabled = bundle != null
+ && bundle.getBoolean(VALUE, false);
+ Log.v(TAG, String.format("isSplitNavLayoutEnabled: %s", isSplitNavLayoutFeatureEnabled));
+ return isSplitNavLayoutFeatureEnabled;
+ }
+
+ /**
+ * Returns the gModalVersion
+ */
+ public int getGModalVersion() {
+ Bundle bundle;
+ if (mResultMap.containsKey(G_MODAL_FEATURE)) {
+ bundle = mResultMap.get(G_MODAL_FEATURE);
+ } else {
+ bundle = getFeatureBundle(G_MODAL_FEATURE);
+ mResultMap.put(G_MODAL_FEATURE, bundle);
+ }
+
+ int gModalVersion = bundle != null ? bundle.getInt(VALUE, 0) : 0;
+ Log.v(TAG, String.format("gModalVersion: %s", gModalVersion));
+ return gModalVersion;
+ }
+
+ private Bundle getFeatureBundle(String feature) {
+ try {
+ Uri contentUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .appendPath(GET_FEATURE_VERSION_METHOD)
+ .build();
+ return mContext.getContentResolver().call(
+ contentUri,
+ GET_FEATURE_VERSION_METHOD,
+ feature,
+ /* extras= */ null);
+ } catch (IllegalArgumentException exception) {
+ Log.w(TAG, String.format("Fail to resolve %s feature from suw provider", feature));
+ return null;
+ }
+ }
+
+ private FeatureResolver(Context context) {
+ this.mContext = context;
+ }
+}