summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2021-10-06 22:53:37 +0000
committerXin Li <delphij@google.com>2021-10-06 22:53:37 +0000
commit7decde09917ebb1562c310b9c59423d798d40735 (patch)
tree033a2ea54f61c1238a5e634fdcc6ee9b4c81fc3a
parentf9cc2a3b3ae82ee117a5a437823dd78e9d28a719 (diff)
parent0cc7edea8e2bd634fb708f6076b1f93fb1eb145b (diff)
downloadsetupwizard-android-s-v2-preview-1.tar.gz
Bug: 202323961 Merged-In: I08740b2e36340d196b0a64d1ab75ae2d3541b603 Change-Id: I90f3deb9857825eaa3bae14e935b96fbfb9a37dd
-rw-r--r--library/main/res/drawable/car_ic_close.xml25
-rw-r--r--library/main/res/layout/car_setup_wizard_toolbar.xml9
-rw-r--r--library/main/res/values/attrs.xml2
-rw-r--r--library/main/res/values/strings.xml3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java18
-rw-r--r--library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java76
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java3
-rw-r--r--library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java4
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java21
-rw-r--r--library/main/src/com/android/car/setupwizardlib/util/ResultCodes.java4
-rw-r--r--library/main/tests/robotests/res/values/attrs.xml2
-rw-r--r--library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java68
-rw-r--r--library/utils/src/com/android/car/setupwizardlib/InitialLockSetupClient.java194
-rw-r--r--library/utils/src/com/android/car/setupwizardlib/InitialLockSetupConstants.java18
-rw-r--r--library/utils/src/com/android/car/setupwizardlib/InitialLockSetupHelper.java9
16 files changed, 394 insertions, 65 deletions
diff --git a/library/main/res/drawable/car_ic_close.xml b/library/main/res/drawable/car_ic_close.xml
new file mode 100644
index 0000000..08b5e36
--- /dev/null
+++ b/library/main/res/drawable/car_ic_close.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/car_primary_icon_size"
+ android:height="@dimen/car_primary_icon_size"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"
+ android:fillColor="@color/car_tint_light"/>
+</vector>
diff --git a/library/main/res/layout/car_setup_wizard_toolbar.xml b/library/main/res/layout/car_setup_wizard_toolbar.xml
index 5c5703b..5ae4e11 100644
--- a/library/main/res/layout/car_setup_wizard_toolbar.xml
+++ b/library/main/res/layout/car_setup_wizard_toolbar.xml
@@ -37,6 +37,15 @@
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"
+ android:background="@drawable/button_ripple_bg"
+ android:contentDescription="@string/close_button_content_description"
+ android:src="@drawable/car_ic_close"/>
</FrameLayout>
<TextView
diff --git a/library/main/res/values/attrs.xml b/library/main/res/values/attrs.xml
index 74bb14e..31d2f5b 100644
--- a/library/main/res/values/attrs.xml
+++ b/library/main/res/values/attrs.xml
@@ -68,6 +68,8 @@
<declare-styleable name="CarSetupWizardBaseLayout">
<!-- Attributes related to the visibility of the back button -->
<attr name="showBackButton"/>
+ <!-- Attributes related to the visibility of the close button -->
+ <attr name="showCloseButton" format="boolean"/>
<!-- Attributes related to the visibility and text of the toolbar title -->
<attr name="showToolbarTitle"/>
diff --git a/library/main/res/values/strings.xml b/library/main/res/values/strings.xml
index beb37dc..027a683 100644
--- a/library/main/res/values/strings.xml
+++ b/library/main/res/values/strings.xml
@@ -17,4 +17,7 @@
<resources>
<!-- Content description of the back button for accessibility services like Tallback [CHAR LIMIT=120] -->
<string name="back_button_content_description">Navigate back</string>
+
+ <!-- Content description of the close button for accessibility services like Tallback [CHAR LIMIT=120] -->
+ <string name="close_button_content_description">Close</string>
</resources> \ No newline at end of file
diff --git a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
index a2fdff3..36caae0 100644
--- a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
+++ b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java
@@ -97,6 +97,8 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
}
});
+ mCarSetupWizardLayout.setCloseButtonListener(v-> handleCloseButton());
+
resetPrimaryToolbarButtonOnClickListener();
resetSecondaryToolbarButtonOnClickListener();
@@ -255,6 +257,14 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
}
/**
+ * Method to be overwritten by subclasses wanting to implement their own close behavior.
+ * Default behavior is finishAction.
+ */
+ protected void handleCloseButton() {
+ finishAction();
+ }
+
+ /**
* Called when nextAction has been invoked, should be overridden on derived class when it is
* needed perform work when nextAction has been invoked.
*/
@@ -350,6 +360,14 @@ abstract class BaseSetupWizardActivity extends FragmentActivity {
}
/**
+ * Sets whether the close button is visible. If this value is {@code true}, clicking the button
+ * will finish the current flow.
+ */
+ protected void setCloseButtonVisible(boolean visible) {
+ mCarSetupWizardLayout.setCloseButtonVisible(visible);
+ }
+
+ /**
* Sets whether the toolbar title is visible.
*/
protected void setToolbarTitleVisible(boolean visible) {
diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
index 43d300e..715315a 100644
--- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
+++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java
@@ -63,6 +63,7 @@ class CarSetupWizardBaseLayout extends LinearLayout {
private static final float IMAGE_MIRROR_ROTATION = 180.0f;
private View mBackButton;
+ private View mCloseButton;
private View mTitleBar;
private TextView mToolbarTitle;
private PartnerConfigHelper mPartnerConfigHelper;
@@ -120,6 +121,7 @@ class CarSetupWizardBaseLayout extends LinearLayout {
*/
private void init(TypedArray attrArray) {
boolean showBackButton;
+ boolean showCloseButton;
boolean showToolbarTitle;
String toolbarTitleText;
@@ -138,6 +140,8 @@ class CarSetupWizardBaseLayout extends LinearLayout {
try {
showBackButton = attrArray.getBoolean(
R.styleable.CarSetupWizardBaseLayout_showBackButton, true);
+ showCloseButton = attrArray.getBoolean(
+ R.styleable.CarSetupWizardBaseLayout_showCloseButton, false);
showToolbarTitle = attrArray.getBoolean(
R.styleable.CarSetupWizardBaseLayout_showToolbarTitle, false);
toolbarTitleText = attrArray.getString(
@@ -171,18 +175,34 @@ class CarSetupWizardBaseLayout extends LinearLayout {
toolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
setBackButton(findViewById(R.id.back_button));
+ setCloseButton(findViewById(R.id.close_button));
+
Drawable drawable = mPartnerConfigHelper.getDrawable(
getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_BACK);
if (drawable != null) {
((ImageView) mBackButton).setImageDrawable(drawable);
}
+ Drawable closeButtonDrawable = mPartnerConfigHelper.getDrawable(
+ getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_CLOSE);
+ if (closeButtonDrawable != null) {
+ ((ImageView) mCloseButton).setImageDrawable(closeButtonDrawable);
+ }
+
if (shouldMirrorNavIcons()) {
Log.v(TAG, "Mirroring navigation icons");
mBackButton.setRotation(IMAGE_MIRROR_ROTATION);
+ mCloseButton.setRotation(IMAGE_MIRROR_ROTATION);
}
+ if (showBackButton && showCloseButton) {
+ Log.w(TAG, "Showing Back and Close button simultaneously is not supported");
+ }
+
+ // Set the back button visibility based on the custom attribute.
setBackButtonVisible(showBackButton);
+ // Set the close button visibility based on the custom attribute.
+ setCloseButtonVisible(showCloseButton);
// Se the title bar.
setTitleBar(findViewById(R.id.application_bar));
@@ -252,19 +272,25 @@ class CarSetupWizardBaseLayout extends LinearLayout {
*/
@VisibleForTesting
void setViewVisible(View view, boolean visible) {
+ if (view == null) {
+ return;
+ }
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
// Add or remove the back button touch delegate depending on whether it is visible.
@VisibleForTesting
- void updateBackButtonTouchDelegate(boolean visible) {
+ void updateNavigationButtonTouchDelegate(View button, boolean visible) {
+ if (button == null) {
+ return;
+ }
if (visible) {
// Post this action in the parent's message queue to make sure the parent
// lays out its children before getHitRect() is called
this.post(() -> {
Rect delegateArea = new Rect();
- mBackButton.getHitRect(delegateArea);
+ button.getHitRect(delegateArea);
/*
* Update the delegate area based on the difference between the current size and
@@ -283,17 +309,16 @@ class CarSetupWizardBaseLayout extends LinearLayout {
delegateArea.top -= sizeDifference;
// Set the TouchDelegate on the parent view
- TouchDelegate touchDelegate = new TouchDelegate(delegateArea,
- mBackButton);
+ TouchDelegate touchDelegate = new TouchDelegate(delegateArea, button);
- if (View.class.isInstance(mBackButton.getParent())) {
- ((View) mBackButton.getParent()).setTouchDelegate(touchDelegate);
+ if (View.class.isInstance(button.getParent())) {
+ ((View) button.getParent()).setTouchDelegate(touchDelegate);
}
});
} else {
// Set the TouchDelegate to null if the back button is not visible.
- if (View.class.isInstance(mBackButton.getParent())) {
- ((View) mBackButton.getParent()).setTouchDelegate(null);
+ if (View.class.isInstance(button.getParent())) {
+ ((View) button.getParent()).setTouchDelegate(null);
}
}
}
@@ -322,8 +347,41 @@ class CarSetupWizardBaseLayout extends LinearLayout {
* Set the back button visibility to the given visibility.
*/
public void setBackButtonVisible(boolean visible) {
+ if (visible) {
+ setViewVisible(mCloseButton, false);
+ updateNavigationButtonTouchDelegate(mCloseButton, false);
+ }
setViewVisible(mBackButton, visible);
- updateBackButtonTouchDelegate(visible);
+ updateNavigationButtonTouchDelegate(mBackButton, visible);
+ }
+
+ public View getCloseButton() {
+ return mCloseButton;
+ }
+
+ @VisibleForTesting
+ final void setCloseButton(View closeButton) {
+ mCloseButton = closeButton;
+ }
+
+ /**
+ * Set the close button onClickListener to given listener. Can be null if the listener should
+ * be overridden so no callback is made.
+ */
+ public void setCloseButtonListener(@Nullable View.OnClickListener listener) {
+ mCloseButton.setOnClickListener(listener);
+ }
+
+ /**
+ * Set the back button visibility to the given visibility.
+ */
+ public void setCloseButtonVisible(boolean visible) {
+ if (visible) {
+ setViewVisible(mBackButton, false);
+ updateNavigationButtonTouchDelegate(mBackButton, false);
+ }
+ setViewVisible(mCloseButton, visible);
+ updateNavigationButtonTouchDelegate(mCloseButton, visible);
}
/**
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 27ea753..54d1e6e 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java
@@ -28,6 +28,9 @@ public enum PartnerConfig {
CONFIG_TOOLBAR_BUTTON_ICON_BACK(
PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK, ResourceType.DRAWABLE),
+ CONFIG_TOOLBAR_BUTTON_ICON_CLOSE(
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_CLOSE, ResourceType.DRAWABLE),
+
CONFIG_TOOLBAR_NAV_ICON_MIRRORING_IN_RTL(
PartnerConfigKey.KEY_TOOLBAR_NAV_BUTTON_MIRRORING_IN_RTL, ResourceType.BOOLEAN),
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 8556fa7..7f9dadd 100644
--- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
+++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java
@@ -26,6 +26,7 @@ import java.lang.annotation.RetentionPolicy;
PartnerConfigKey.KEY_IMMERSIVE_MODE,
PartnerConfigKey.KEY_TOOLBAR_BG_COLOR,
PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK,
+ PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_CLOSE,
PartnerConfigKey.KEY_TOOLBAR_NAV_BUTTON_MIRRORING_IN_RTL,
PartnerConfigKey.KEY_TOOLBAR_BUTTON_FONT_FAMILY,
PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_HORIZONTAL,
@@ -55,6 +56,8 @@ public @interface PartnerConfigKey {
String KEY_TOOLBAR_BUTTON_ICON_BACK = "suw_compat_toolbar_button_icon_back";
+ String KEY_TOOLBAR_BUTTON_ICON_CLOSE = "suw_compat_toolbar_button_icon_close";
+
String KEY_TOOLBAR_NAV_BUTTON_MIRRORING_IN_RTL =
"suw_compat_toolbar_nav_button_mirroring_in_rtl";
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 ebf0d35..2dfb04b 100644
--- a/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java
+++ b/library/main/src/com/android/car/setupwizardlib/summary/PartnerSummaryActionsCollector.java
@@ -86,14 +86,14 @@ public class PartnerSummaryActionsCollector {
ResolveInfo resolveInfo = getSummaryContentProviderResolveInfo(context.getPackageManager());
if (resolveInfo == null) {
- Log.e(TAG, "Could not find partner content provider, ignoring partner summary items.");
+ Log.i(TAG, "Could not find partner content provider, ignoring partner summary items.");
return;
}
mContentProviderUri = getSummaryContentProviderUri(resolveInfo);
if (mContentProviderUri == null) {
- Log.e(TAG, "Could not fetch content provider URI, ignoring partner summary items.");
+ Log.i(TAG, "Could not fetch content provider URI, ignoring partner summary items.");
}
}
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 7f5cf7a..ff83b55 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/CarWizardManagerHelper.java
@@ -148,4 +148,25 @@ public final class CarWizardManagerHelper {
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 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);
+ }
}
diff --git a/library/main/src/com/android/car/setupwizardlib/util/ResultCodes.java b/library/main/src/com/android/car/setupwizardlib/util/ResultCodes.java
index 604e8b0..89b8d11 100644
--- a/library/main/src/com/android/car/setupwizardlib/util/ResultCodes.java
+++ b/library/main/src/com/android/car/setupwizardlib/util/ResultCodes.java
@@ -23,7 +23,11 @@ import static android.app.Activity.RESULT_FIRST_USER;
*/
public final class ResultCodes {
public static final int RESULT_SKIP = RESULT_FIRST_USER;
+ public static final int RESULT_RETRY = RESULT_FIRST_USER + 1;
public static final int RESULT_ACTIVITY_NOT_FOUND = RESULT_FIRST_USER + 2;
+ public static final int RESULT_LIFECYCLE_NOT_MATCHED = RESULT_FIRST_USER + 3;
+ public static final int RESULT_FLOW_NOT_MATCHED = RESULT_FIRST_USER + 4;
+
public static final int RESULT_FIRST_SETUP_USER = RESULT_FIRST_USER + 100;
private ResultCodes() {
diff --git a/library/main/tests/robotests/res/values/attrs.xml b/library/main/tests/robotests/res/values/attrs.xml
index 4454939..0591552 100644
--- a/library/main/tests/robotests/res/values/attrs.xml
+++ b/library/main/tests/robotests/res/values/attrs.xml
@@ -19,6 +19,8 @@
<declare-styleable name="CarSetupWizardBaseLayout">
<!-- Attributes related to the visibility of the back button -->
<attr name="showBackButton" format="boolean"/>
+ <!-- Attributes related to the visibility of the close button -->
+ <attr name="showCloseButton" format="boolean"/>
<!-- Attributes related to the visibility and text of the toolbar title -->
<attr name="showToolbarTitle" format="boolean"/>
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
index 541cf4c..3ed02c0 100644
--- a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
@@ -104,8 +104,22 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest {
}
/**
+ * Test that {@link CarSetupWizardCompatLayout#setCloseButtonListener} does set the close button
+ * listener.
+ */
+ @Test
+ public void testSetCloseButtonListener() {
+ View.OnClickListener spyListener = TestHelper.createSpyListener();
+
+ mCarSetupWizardCompatLayout.setCloseButtonListener(spyListener);
+ mCarSetupWizardCompatLayout.getCloseButton().performClick();
+ Mockito.verify(spyListener).onClick(mCarSetupWizardCompatLayout.getCloseButton());
+ }
+
+ /**
* Test that {@link CarSetupWizardCompatLayout#setBackButtonVisible} does set the view
- * visible/not visible and calls updateBackButtonTouchDelegate.
+ * visible/not visible and calls
+ * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}.
*/
@Test
public void testSetBackButtonVisibleTrue() {
@@ -115,12 +129,18 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest {
spyCarSetupWizardCompatLayout.setBackButtonVisible(true);
View backButton = spyCarSetupWizardCompatLayout.getBackButton();
TestHelper.assertViewVisible(backButton);
- Mockito.verify(spyCarSetupWizardCompatLayout).updateBackButtonTouchDelegate(true);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(backButton, true);
+ View closeButton = spyCarSetupWizardCompatLayout.getCloseButton();
+ TestHelper.assertViewNotVisible(closeButton);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(closeButton, false);
}
/**
* Test that {@link CarSetupWizardCompatLayout#setBackButtonVisible} does set the view
- * visible/not visible and calls updateBackButtonTouchDelegate.
+ * visible/not visible and calls
+ * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}.
*/
@Test
public void testSetBackButtonVisibleFalse() {
@@ -130,7 +150,47 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest {
spyCarSetupWizardCompatLayout.setBackButtonVisible(false);
View backButton = spyCarSetupWizardCompatLayout.getBackButton();
TestHelper.assertViewNotVisible(backButton);
- Mockito.verify(spyCarSetupWizardCompatLayout).updateBackButtonTouchDelegate(false);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(backButton, false);
+ }
+
+ /**
+ * Test that {@link CarSetupWizardCompatLayout#setCloseButtonVisible} does set the view
+ * visible/not visible and calls
+ * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}.
+ */
+ @Test
+ public void testSetCloseButtonVisibleTrue() {
+ CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout =
+ Mockito.spy(mCarSetupWizardCompatLayout);
+
+ spyCarSetupWizardCompatLayout.setCloseButtonVisible(true);
+ View closeButton = spyCarSetupWizardCompatLayout.getCloseButton();
+ TestHelper.assertViewVisible(closeButton);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(closeButton, true);
+ View backButton = spyCarSetupWizardCompatLayout.getBackButton();
+ TestHelper.assertViewNotVisible(backButton);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(backButton, false);
+ }
+
+
+ /**
+ * Test that {@link CarSetupWizardCompatLayout#setCloseButtonVisible} does set the view
+ * visible/not visible and calls
+ * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}.
+ */
+ @Test
+ public void testSetCloseButtonVisibleFalse() {
+ CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout =
+ Mockito.spy(mCarSetupWizardCompatLayout);
+
+ spyCarSetupWizardCompatLayout.setCloseButtonVisible(false);
+ View closeButton = spyCarSetupWizardCompatLayout.getCloseButton();
+ TestHelper.assertViewNotVisible(closeButton);
+ Mockito.verify(spyCarSetupWizardCompatLayout)
+ .updateNavigationButtonTouchDelegate(closeButton, false);
}
/**
diff --git a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupClient.java b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupClient.java
index 4ef851e..6c7830f 100644
--- a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupClient.java
+++ b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupClient.java
@@ -16,11 +16,13 @@
package com.android.car.setupwizardlib;
+import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -28,6 +30,7 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.car.setupwizardlib.InitialLockSetupConstants.LockTypes;
+import com.android.car.setupwizardlib.InitialLockSetupConstants.PasswordComplexity;
import com.android.car.setupwizardlib.InitialLockSetupConstants.SetLockCodes;
import com.android.car.setupwizardlib.InitialLockSetupConstants.ValidateLockFlags;
@@ -56,6 +59,7 @@ public class InitialLockSetupClient implements ServiceConnection {
private InitialLockListener mInitialLockListener;
private Context mContext;
+ private KeyguardManager mKeyguardManager;
private IInitialLockSetupService mInitialLockSetupService;
private ValidateLockAsyncTask mCurrentValidateLockTask;
private SaveLockAsyncTask mCurrentSaveLockTask;
@@ -65,6 +69,7 @@ public class InitialLockSetupClient implements ServiceConnection {
public InitialLockSetupClient(Context context) {
mContext = context.getApplicationContext();
+ mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
}
/**
@@ -120,8 +125,8 @@ public class InitialLockSetupClient implements ServiceConnection {
* Fetches the set of {@link LockConfig}s that define the lock constraints for the device.
*/
public void getLockConfigs() {
- LockConfigsAsyncTask lockConfigsAsyncTask = new LockConfigsAsyncTask(mInitialLockListener,
- mInitialLockSetupService);
+ LockConfigsAsyncTask lockConfigsAsyncTask = new LockConfigsAsyncTask(
+ mInitialLockListener, mInitialLockSetupService, mKeyguardManager);
lockConfigsAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);
}
@@ -136,8 +141,8 @@ public class InitialLockSetupClient implements ServiceConnection {
&& mCurrentValidateLockTask.getStatus() != AsyncTask.Status.FINISHED) {
mCurrentValidateLockTask.cancel(true);
}
- mCurrentValidateLockTask = new ValidateLockAsyncTask(
- mInitialLockListener, mInitialLockSetupService, LockTypes.PASSWORD);
+ mCurrentValidateLockTask = new ValidateLockAsyncTask(mInitialLockListener,
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PASSWORD);
mCurrentValidateLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, password);
}
@@ -151,8 +156,8 @@ public class InitialLockSetupClient implements ServiceConnection {
&& mCurrentValidateLockTask.getStatus() != AsyncTask.Status.FINISHED) {
mCurrentValidateLockTask.cancel(true);
}
- mCurrentValidateLockTask = new ValidateLockAsyncTask(
- mInitialLockListener, mInitialLockSetupService, LockTypes.PIN);
+ mCurrentValidateLockTask = new ValidateLockAsyncTask(mInitialLockListener,
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PIN);
mCurrentValidateLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pin);
}
@@ -166,8 +171,8 @@ public class InitialLockSetupClient implements ServiceConnection {
&& mCurrentValidateLockTask.getStatus() != AsyncTask.Status.FINISHED) {
mCurrentValidateLockTask.cancel(true);
}
- mCurrentValidateLockTask = new ValidateLockAsyncTask(
- mInitialLockListener, mInitialLockSetupService, LockTypes.PATTERN);
+ mCurrentValidateLockTask = new ValidateLockAsyncTask(mInitialLockListener,
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PATTERN);
mCurrentValidateLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pattern);
}
@@ -184,7 +189,7 @@ public class InitialLockSetupClient implements ServiceConnection {
return;
}
mCurrentSaveLockTask = new SaveLockAsyncTask(mInitialLockListener,
- mInitialLockSetupService, LockTypes.PASSWORD);
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PASSWORD);
mCurrentSaveLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, password);
}
@@ -200,7 +205,7 @@ public class InitialLockSetupClient implements ServiceConnection {
return;
}
mCurrentSaveLockTask = new SaveLockAsyncTask(mInitialLockListener,
- mInitialLockSetupService, LockTypes.PIN);
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PIN);
mCurrentSaveLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pin);
}
@@ -217,7 +222,7 @@ public class InitialLockSetupClient implements ServiceConnection {
return;
}
mCurrentSaveLockTask = new SaveLockAsyncTask(mInitialLockListener,
- mInitialLockSetupService, LockTypes.PATTERN);
+ mInitialLockSetupService, mKeyguardManager, LockTypes.PATTERN);
mCurrentSaveLockTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pattern);
}
@@ -282,29 +287,56 @@ public class InitialLockSetupClient implements ServiceConnection {
private WeakReference<InitialLockListener> mInitialLockListener;
private WeakReference<IInitialLockSetupService> mInitialLockSetupService;
+ private WeakReference<KeyguardManager> mKeyguardManager;
LockConfigsAsyncTask(InitialLockListener initialLockListener,
- IInitialLockSetupService initialLockSetupService) {
+ IInitialLockSetupService initialLockSetupService,
+ KeyguardManager keyguardManager) {
mInitialLockListener = new WeakReference<>(initialLockListener);
mInitialLockSetupService = new WeakReference<>(initialLockSetupService);
+ mKeyguardManager = new WeakReference<>(keyguardManager);
}
@Override
protected Map<Integer, LockConfig> doInBackground(Void... voids) {
- IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
- if (initialLockSetupService == null) {
- InitialLockSetupClient.logVerbose(
- "Lost reference to service in LockConfigsAsyncTask");
- return null;
- }
LockConfig passwordConfig, pinConfig, patternConfig;
- try {
- passwordConfig = initialLockSetupService.getLockConfig(LockTypes.PASSWORD);
- pinConfig = initialLockSetupService.getLockConfig(LockTypes.PIN);
- patternConfig = initialLockSetupService.getLockConfig(LockTypes.PATTERN);
- } catch (RemoteException e) {
- e.printStackTrace();
- return null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ KeyguardManager km = mKeyguardManager.get();
+ if (km == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to keyguardManager in LockConfigsAsyncTask");
+ return null;
+ }
+ passwordConfig =
+ new LockConfig(
+ /* enabled= */ true,
+ km.getMinLockLength(
+ /* isPin= */ false, PasswordComplexity.PASSWORD_COMPLEXITY_MEDIUM));
+ pinConfig =
+ new LockConfig(
+ /* enabled= */ true,
+ km.getMinLockLength(
+ /* isPin= */ true, PasswordComplexity.PASSWORD_COMPLEXITY_LOW));
+ patternConfig =
+ new LockConfig(
+ /* enabled= */ true,
+ km.getMinLockLength(
+ /* isPin= */ false, PasswordComplexity.PASSWORD_COMPLEXITY_LOW));
+ } else {
+ IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
+ if (initialLockSetupService == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to service in LockConfigsAsyncTask");
+ return null;
+ }
+ try {
+ passwordConfig = initialLockSetupService.getLockConfig(LockTypes.PASSWORD);
+ pinConfig = initialLockSetupService.getLockConfig(LockTypes.PIN);
+ patternConfig = initialLockSetupService.getLockConfig(LockTypes.PATTERN);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return null;
+ }
}
Map<Integer, LockConfig> map = new HashMap<>();
map.put(LockTypes.PASSWORD, passwordConfig);
@@ -327,32 +359,64 @@ public class InitialLockSetupClient implements ServiceConnection {
private WeakReference<InitialLockListener> mInitialLockListener;
private WeakReference<IInitialLockSetupService> mInitialLockSetupService;
+ private WeakReference<KeyguardManager> mKeyguardManager;
private int mLockType;
ValidateLockAsyncTask(
InitialLockListener initialLockListener,
IInitialLockSetupService initialLockSetupService,
+ KeyguardManager keyguardManager,
@LockTypes int lockType) {
mInitialLockListener = new WeakReference<>(initialLockListener);
mInitialLockSetupService = new WeakReference<>(initialLockSetupService);
+ mKeyguardManager = new WeakReference<>(keyguardManager);
mLockType = lockType;
}
@Override
protected Integer doInBackground(byte[]... passwords) {
InitialLockSetupClient.logVerbose("ValidateLockAsyncTask doInBackground");
- IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
- if (initialLockSetupService == null) {
- InitialLockSetupClient.logVerbose(
- "Lost reference to service in ValidateLockAsyncTask");
- return ValidateLockFlags.INVALID_GENERIC;
- }
- try {
- int output = initialLockSetupService.checkValidLock(mLockType, passwords[0]);
- return output;
- } catch (RemoteException e) {
- e.printStackTrace();
- return ValidateLockFlags.INVALID_GENERIC;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ KeyguardManager km = mKeyguardManager.get();
+ if (km == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to keyguardManager in LockConfigsAsyncTask");
+ return null;
+ }
+ int complexity;
+ switch (mLockType) {
+ case LockTypes.PASSWORD:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_MEDIUM;
+ break;
+ case LockTypes.PIN:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_LOW;
+ break;
+ case LockTypes.PATTERN:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_LOW;
+ passwords[0] =
+ InitialLockSetupHelper.getNumericEquivalentByteArray(passwords[0]);
+ break;
+ default:
+ Log.e(TAG, "other lock type, returning generic error");
+ return ValidateLockFlags.INVALID_GENERIC;
+ }
+ return km.isValidLockPasswordComplexity(mLockType, passwords[0], complexity)
+ ? 0
+ : ValidateLockFlags.INVALID_GENERIC;
+ } else {
+ IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
+ if (initialLockSetupService == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to service in ValidateLockAsyncTask");
+ return ValidateLockFlags.INVALID_GENERIC;
+ }
+ try {
+ int output = initialLockSetupService.checkValidLock(mLockType, passwords[0]);
+ return output;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return ValidateLockFlags.INVALID_GENERIC;
+ }
}
}
@@ -373,32 +437,64 @@ public class InitialLockSetupClient implements ServiceConnection {
private WeakReference<InitialLockListener> mInitialLockListener;
private WeakReference<IInitialLockSetupService> mInitialLockSetupService;
+ private WeakReference<KeyguardManager> mKeyguardManager;
private int mLockType;
SaveLockAsyncTask(
InitialLockListener initialLockListener,
IInitialLockSetupService initialLockSetupService,
+ KeyguardManager keyguardManager,
@LockTypes int lockType) {
mInitialLockListener = new WeakReference<>(initialLockListener);
mInitialLockSetupService = new WeakReference<>(initialLockSetupService);
+ mKeyguardManager = new WeakReference<>(keyguardManager);
mLockType = lockType;
}
@Override
protected Integer doInBackground(byte[]... passwords) {
InitialLockSetupClient.logVerbose("SaveLockAsyncTask doInBackground");
- IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
- if (initialLockSetupService == null) {
- InitialLockSetupClient.logVerbose(
- "Lost reference to service in SaveLockAsyncTask");
- return SetLockCodes.FAIL_LOCK_GENERIC;
- }
- try {
- int output = initialLockSetupService.setLock(mLockType, passwords[0]);
- return output;
- } catch (RemoteException e) {
- e.printStackTrace();
- return SetLockCodes.FAIL_LOCK_GENERIC;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ KeyguardManager km = mKeyguardManager.get();
+ if (km == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to keyguardManager in SaveLockAsyncTask");
+ return null;
+ }
+ int complexity;
+ switch (mLockType) {
+ case LockTypes.PASSWORD:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_MEDIUM;
+ break;
+ case LockTypes.PIN:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_LOW;
+ break;
+ case LockTypes.PATTERN:
+ complexity = PasswordComplexity.PASSWORD_COMPLEXITY_LOW;
+ passwords[0] =
+ InitialLockSetupHelper.getNumericEquivalentByteArray(passwords[0]);
+ break;
+ default:
+ Log.e(TAG, "other lock type, returning generic error");
+ return SetLockCodes.FAIL_LOCK_GENERIC;
+ }
+ return km.setLock(mLockType, passwords[0], complexity)
+ ? 1
+ : SetLockCodes.FAIL_LOCK_GENERIC;
+ } else {
+ IInitialLockSetupService initialLockSetupService = mInitialLockSetupService.get();
+ if (initialLockSetupService == null) {
+ InitialLockSetupClient.logVerbose(
+ "Lost reference to service in SaveLockAsyncTask");
+ return SetLockCodes.FAIL_LOCK_GENERIC;
+ }
+ try {
+ int output = initialLockSetupService.setLock(mLockType, passwords[0]);
+ return output;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return SetLockCodes.FAIL_LOCK_GENERIC;
+ }
}
}
diff --git a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupConstants.java b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupConstants.java
index 7081e78..8ca5c6e 100644
--- a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupConstants.java
+++ b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupConstants.java
@@ -36,12 +36,14 @@ public interface InitialLockSetupConstants {
@IntDef({
LockTypes.PASSWORD,
LockTypes.PIN,
- LockTypes.PATTERN
+ LockTypes.PATTERN,
+ LockTypes.NONE
})
@interface LockTypes {
int PASSWORD = 0;
int PIN = 1;
int PATTERN = 2;
+ int NONE = 3;
}
/**
@@ -75,5 +77,19 @@ public interface InitialLockSetupConstants {
int FAIL_LOCK_INVALID = -2;
int FAIL_LOCK_GENERIC = -3;
}
+
+ /** PasswordComplexity as defined in DevicePolicyManager. */
+ @IntDef({
+ PasswordComplexity.PASSWORD_COMPLEXITY_NONE,
+ PasswordComplexity.PASSWORD_COMPLEXITY_LOW,
+ PasswordComplexity.PASSWORD_COMPLEXITY_MEDIUM,
+ PasswordComplexity.PASSWORD_COMPLEXITY_HIGH,
+ })
+ @interface PasswordComplexity {
+ int PASSWORD_COMPLEXITY_NONE = 0;
+ int PASSWORD_COMPLEXITY_LOW = 0x10000;
+ int PASSWORD_COMPLEXITY_MEDIUM = 0x30000;
+ int PASSWORD_COMPLEXITY_HIGH = 0x50000;
+ }
}
diff --git a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupHelper.java b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupHelper.java
index 9820680..191ddbc 100644
--- a/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupHelper.java
+++ b/library/utils/src/com/android/car/setupwizardlib/InitialLockSetupHelper.java
@@ -81,4 +81,13 @@ public class InitialLockSetupHelper {
}
return charSequence;
}
+
+ /** Return an ASCII-equivalent array of character digits for a numeric byte input. */
+ public static byte[] getNumericEquivalentByteArray(byte[] input) {
+ byte[] output = new byte[input.length];
+ for (int i = 0; i < input.length; i++) {
+ output[i] = (byte) (input[i] + 48);
+ }
+ return output;
+ }
}