import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.UserHandle;
+import android.support.annotation.Nullable;
+import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
private static final int ENROLLING = 2;
public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
+ @Nullable
private FingerprintFindSensorAnimation mAnimation;
private boolean mLaunchedConfirmLock;
private FingerprintEnrollSidecar mSidecar;
} else if (mToken != null) {
startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
}
- mAnimation = (FingerprintFindSensorAnimation) findViewById(
- R.id.fingerprint_sensor_location_animation);
+ View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
+ if (animationView instanceof FingerprintFindSensorAnimation) {
+ mAnimation = (FingerprintFindSensorAnimation) animationView;
+ } else {
+ mAnimation = null;
+ }
}
protected int getContentView() {
@Override
protected void onStart() {
super.onStart();
- mAnimation.startAnimation();
+ if (mAnimation != null) {
+ mAnimation.startAnimation();
+ }
}
private void startLookingForFingerprint() {
@Override
protected void onStop() {
super.onStop();
- mAnimation.pauseAnimation();
+ if (mAnimation != null) {
+ mAnimation.pauseAnimation();
+ }
}
@Override
protected void onDestroy() {
super.onDestroy();
- mAnimation.stopAnimation();
+ if (mAnimation != null) {
+ mAnimation.stopAnimation();
+ }
}
@Override
--- /dev/null
+<?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.
+-->
+
+<com.android.setupwizardlib.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/setup_wizard_layout"
+ style="?attr/fingerprint_layout_theme"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <FrameLayout
+ android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
+ android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
+ android:layout_gravity="center_horizontal|bottom">
+
+ <ImageView
+ android:id="@+id/fingerprint_sensor_location_animation"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@string/security_settings_fingerprint_enroll_find_sensor_content_description"
+ android:src="@drawable/fingerprint_sensor_location"
+ android:scaleType="centerInside"/>
+
+ </FrameLayout>
+
+ <LinearLayout
+ style="@style/SuwContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <TextView
+ style="@style/SuwDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/suw_description_glif_margin_top"
+ android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
+
+ <View
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_weight="1"/>
+
+ <Button
+ style="@style/SuwGlifButton.Primary"
+ android:id="@+id/next_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_gravity="end"
+ android:text="@string/fingerprint_enroll_button_next" />
+
+ </LinearLayout>
+ </FrameLayout>
+</com.android.setupwizardlib.GlifLayout>
@Test
public void clickNextAndFingerprint_shouldNotCrash() {
- ArgumentCaptor<EnrollmentCallback> callbackCaptor =
- ArgumentCaptor.forClass(EnrollmentCallback.class);
- verify(mFingerprintManager).enroll(
- any(byte[].class),
- any(CancellationSignal.class),
- anyInt(),
- anyInt(),
- callbackCaptor.capture());
+ EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
Button nextButton = mActivity.findViewById(R.id.next_button);
nextButton.performClick();
- callbackCaptor.getValue().onEnrollmentProgress(123);
+ enrollmentCallback.onEnrollmentProgress(123);
nextButton.performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
assertThat(shadowActivity.getNextStartedActivityForResult()).named("Next activity 2")
.isNull();
}
+
+ // Use a non-default resource qualifier to load the test layout in
+ // robotests/res/layout-mcc999/fingerprint_enroll_find_sensor. This layout is a copy of the
+ // regular find sensor layout, with the animation removed.
+ @Config(qualifiers = "mcc999")
+ @Test
+ public void layoutWithoutAnimation_shouldNotCrash() {
+ EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
+ enrollmentCallback.onEnrollmentProgress(123);
+
+ Button nextButton = mActivity.findViewById(R.id.next_button);
+ nextButton.performClick();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
+ IntentForResult startedActivity =
+ shadowActivity.getNextStartedActivityForResult();
+ assertThat(startedActivity).named("Next activity").isNotNull();
+ assertThat(startedActivity.intent.getComponent())
+ .isEqualTo(new ComponentName(application, FingerprintEnrollEnrolling.class));
+ }
+
+ private EnrollmentCallback verifyAndCaptureEnrollmentCallback() {
+ ArgumentCaptor<EnrollmentCallback> callbackCaptor =
+ ArgumentCaptor.forClass(EnrollmentCallback.class);
+ verify(mFingerprintManager).enroll(
+ any(byte[].class),
+ any(CancellationSignal.class),
+ anyInt(),
+ anyInt(),
+ callbackCaptor.capture());
+
+ return callbackCaptor.getValue();
+ }
}