Commit e16b6ef2 authored by Sarah Hu's avatar Sarah Hu Committed by Commit Bot

cros: Update fingerprint unlock UI per latest mock.

Bug: 835357
Change-Id: I61be44e86f85175a3472669aecf630ddb5bb2fa2
Reviewed-on: https://chromium-review.googlesource.com/1159383Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarJacob Dufault <jdufault@chromium.org>
Commit-Queue: Xiaoyin Hu <xiaoyinh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580914}
parent ea304b71
...@@ -200,6 +200,7 @@ component("ash") { ...@@ -200,6 +200,7 @@ component("ash") {
"login/ui/animated_rounded_image_view.h", "login/ui/animated_rounded_image_view.h",
"login/ui/animation_frame.h", "login/ui/animation_frame.h",
"login/ui/arrow_button_view.h", "login/ui/arrow_button_view.h",
"login/ui/horizontal_image_sequence_animation_decoder.h",
"login/ui/hover_notifier.h", "login/ui/hover_notifier.h",
"login/ui/image_parser.h", "login/ui/image_parser.h",
"login/ui/lock_contents_view.h", "login/ui/lock_contents_view.h",
...@@ -849,6 +850,7 @@ component("ash") { ...@@ -849,6 +850,7 @@ component("ash") {
"login/login_screen_controller_observer.cc", "login/login_screen_controller_observer.cc",
"login/ui/animated_rounded_image_view.cc", "login/ui/animated_rounded_image_view.cc",
"login/ui/arrow_button_view.cc", "login/ui/arrow_button_view.cc",
"login/ui/horizontal_image_sequence_animation_decoder.cc",
"login/ui/hover_notifier.cc", "login/ui/hover_notifier.cc",
"login/ui/image_parser.cc", "login/ui/image_parser.cc",
"login/ui/lock_contents_view.cc", "login/ui/lock_contents_view.cc",
...@@ -1334,6 +1336,7 @@ component("ash") { ...@@ -1334,6 +1336,7 @@ component("ash") {
"//ash/components/shortcut_viewer/public/mojom", "//ash/components/shortcut_viewer/public/mojom",
"//ash/components/tap_visualizer/public/mojom", "//ash/components/tap_visualizer/public/mojom",
"//ash/keyboard/arc", "//ash/keyboard/arc",
"//ash/login/resources:resources_grit",
"//ash/system/message_center/arc", "//ash/system/message_center/arc",
"//ash/touch_hud", "//ash/touch_hud",
"//base", "//base",
......
...@@ -47,19 +47,22 @@ AnimatedRoundedImageView::AnimatedRoundedImageView(const gfx::Size& size, ...@@ -47,19 +47,22 @@ AnimatedRoundedImageView::AnimatedRoundedImageView(const gfx::Size& size,
AnimatedRoundedImageView::~AnimatedRoundedImageView() = default; AnimatedRoundedImageView::~AnimatedRoundedImageView() = default;
void AnimatedRoundedImageView::SetAnimationDecoder( void AnimatedRoundedImageView::SetAnimationDecoder(
std::unique_ptr<AnimationDecoder> decoder) { std::unique_ptr<AnimationDecoder> decoder,
Playback playback) {
decoder_ = std::move(decoder); decoder_ = std::move(decoder);
playback_ = playback;
// Force a new decode and repaint. // Force a new decode and repaint.
frames_scale_ = NAN; frames_scale_ = NAN;
SchedulePaint(); SchedulePaint();
} }
void AnimatedRoundedImageView::SetImage(const gfx::ImageSkia& image) { void AnimatedRoundedImageView::SetImage(const gfx::ImageSkia& image) {
SetAnimationDecoder(std::make_unique<SingleFrameImageDecoder>(image)); SetAnimationDecoder(std::make_unique<SingleFrameImageDecoder>(image),
Playback::kFirstFrameOnly);
} }
void AnimatedRoundedImageView::SetAnimationEnabled(bool enabled) { void AnimatedRoundedImageView::SetAnimationPlayback(Playback playback) {
should_animate_ = enabled; playback_ = playback;
StartOrStopAnimation(); StartOrStopAnimation();
} }
...@@ -100,7 +103,7 @@ void AnimatedRoundedImageView::OnPaint(gfx::Canvas* canvas) { ...@@ -100,7 +103,7 @@ void AnimatedRoundedImageView::OnPaint(gfx::Canvas* canvas) {
void AnimatedRoundedImageView::StartOrStopAnimation() { void AnimatedRoundedImageView::StartOrStopAnimation() {
// If animation is disabled or if there are less than 2 frames, show a static // If animation is disabled or if there are less than 2 frames, show a static
// image. // image.
if (!should_animate_ || frames_.size() < 2) { if (playback_ == Playback::kFirstFrameOnly || frames_.size() < 2) {
active_frame_ = 0; active_frame_ = 0;
update_frame_timer_.Stop(); update_frame_timer_.Stop();
SchedulePaint(); SchedulePaint();
...@@ -119,11 +122,14 @@ void AnimatedRoundedImageView::UpdateAnimationFrame() { ...@@ -119,11 +122,14 @@ void AnimatedRoundedImageView::UpdateAnimationFrame() {
active_frame_ = (active_frame_ + 1) % frames_.size(); active_frame_ = (active_frame_ + 1) % frames_.size();
SchedulePaint(); SchedulePaint();
// Schedule next frame update. if (static_cast<size_t>(active_frame_ + 1) < frames_.size() ||
update_frame_timer_.Start( playback_ == Playback::kRepeat) {
FROM_HERE, frames_[active_frame_].duration, // Schedule next frame update.
base::BindRepeating(&AnimatedRoundedImageView::UpdateAnimationFrame, update_frame_timer_.Start(
base::Unretained(this))); FROM_HERE, frames_[active_frame_].duration,
base::BindRepeating(&AnimatedRoundedImageView::UpdateAnimationFrame,
base::Unretained(this)));
}
} }
void AnimatedRoundedImageView::BuildAnimationFrames(float image_scale) { void AnimatedRoundedImageView::BuildAnimationFrames(float image_scale) {
......
...@@ -21,6 +21,12 @@ namespace ash { ...@@ -21,6 +21,12 @@ namespace ash {
// A custom image view with rounded edges. // A custom image view with rounded edges.
class AnimatedRoundedImageView : public views::View { class AnimatedRoundedImageView : public views::View {
public: public:
enum class Playback {
kFirstFrameOnly, // Only the first frame in the animation will be shown.
kSingle, // Play the animation only once.
kRepeat, // Play the animation repeatly.
};
// Provides animation frames. // Provides animation frames.
class AnimationDecoder { class AnimationDecoder {
public: public:
...@@ -33,14 +39,15 @@ class AnimatedRoundedImageView : public views::View { ...@@ -33,14 +39,15 @@ class AnimatedRoundedImageView : public views::View {
AnimatedRoundedImageView(const gfx::Size& size, int corner_radius); AnimatedRoundedImageView(const gfx::Size& size, int corner_radius);
~AnimatedRoundedImageView() override; ~AnimatedRoundedImageView() override;
// Show an animation. // Show an animation with specified playback mode.
void SetAnimationDecoder(std::unique_ptr<AnimationDecoder> decoder); void SetAnimationDecoder(std::unique_ptr<AnimationDecoder> decoder,
Playback playback);
// Show a static image. // Show a static image.
void SetImage(const gfx::ImageSkia& image); void SetImage(const gfx::ImageSkia& image);
// Start or stop animation. // Set playback type of the animation.
void SetAnimationEnabled(bool enabled); void SetAnimationPlayback(Playback playback);
// views::View: // views::View:
gfx::Size CalculatePreferredSize() const override; gfx::Size CalculatePreferredSize() const override;
...@@ -51,10 +58,6 @@ class AnimatedRoundedImageView : public views::View { ...@@ -51,10 +58,6 @@ class AnimatedRoundedImageView : public views::View {
void UpdateAnimationFrame(); void UpdateAnimationFrame();
void BuildAnimationFrames(float image_scale); void BuildAnimationFrames(float image_scale);
// If true and there are multiple frames, the animation will play. If false,
// only the first frame in the animation will be shown.
bool should_animate_ = false;
// Currently displayed animation frame. // Currently displayed animation frame.
int active_frame_ = 0; int active_frame_ = 0;
...@@ -64,6 +67,8 @@ class AnimatedRoundedImageView : public views::View { ...@@ -64,6 +67,8 @@ class AnimatedRoundedImageView : public views::View {
float frames_scale_ = NAN; float frames_scale_ = NAN;
// The raw decoded animation frames. // The raw decoded animation frames.
AnimationFrames frames_; AnimationFrames frames_;
// Animation playback type.
Playback playback_ = Playback::kFirstFrameOnly;
const gfx::Size image_size_; const gfx::Size image_size_;
const int corner_radius_; const int corner_radius_;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/login/ui/horizontal_image_sequence_animation_decoder.h"
namespace ash {
HorizontalImageSequenceAnimationDecoder::
HorizontalImageSequenceAnimationDecoder(const gfx::ImageSkia& image,
base::TimeDelta duration,
int num_frames)
: image_(image), duration_(duration), num_frames_(num_frames) {}
HorizontalImageSequenceAnimationDecoder::
~HorizontalImageSequenceAnimationDecoder() = default;
AnimationFrames HorizontalImageSequenceAnimationDecoder::Decode(
float image_scale) {
SkBitmap bitmap = image_.GetRepresentation(image_scale).sk_bitmap();
float frame_width = static_cast<float>(bitmap.width()) / num_frames_;
base::TimeDelta frame_duration = duration_ / num_frames_;
AnimationFrames animation;
animation.reserve(num_frames_);
for (int i = 0; i < num_frames_; ++i) {
// Get the subsection of the animation strip.
SkBitmap frame_bitmap;
bitmap.extractSubset(
&frame_bitmap,
SkIRect::MakeXYWH(std::round(i * frame_width), 0,
std::round(frame_width), bitmap.height()));
// Add an animation frame.
AnimationFrame frame;
frame.duration = frame_duration;
frame.image = gfx::ImageSkia::CreateFrom1xBitmap(frame_bitmap);
animation.push_back(frame);
}
return animation;
}
} // namespace ash
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_LOGIN_UI_HORIZONTAL_IMAGE_SEQUENCE_ANIMATION_DECODER_H_
#define ASH_LOGIN_UI_HORIZONTAL_IMAGE_SEQUENCE_ANIMATION_DECODER_H_
#include "ash/login/ui/animated_rounded_image_view.h"
namespace ash {
// Decodes an animation strip that is laid out 1xN (ie, the image grows in
// width, not height). There is no padding between frames in the animation
// strip.
//
// As an example, if the following ASCII art is 100 pixels wide, it has 4 frames
// each 25 pixels wide. The frames go from [0, 25), [25, 50), [50, 75), [75,
// 100). All frames have the same height of 25 pixels.
//
// [1][2][3][4]
//
class HorizontalImageSequenceAnimationDecoder
: public AnimatedRoundedImageView::AnimationDecoder {
public:
HorizontalImageSequenceAnimationDecoder(const gfx::ImageSkia& image,
base::TimeDelta duration,
int num_frames);
~HorizontalImageSequenceAnimationDecoder() override;
// AnimatedRoundedImageView::AnimationDecoder:
AnimationFrames Decode(float image_scale) override;
private:
// The animation image source.
gfx::ImageSkia image_;
// The total duration of the animation.
base::TimeDelta duration_;
// The total number of frames in the animation.
int num_frames_;
DISALLOW_COPY_AND_ASSIGN(HorizontalImageSequenceAnimationDecoder);
};
} // namespace ash
#endif // ASH_LOGIN_UI_HORIZONTAL_IMAGE_SEQUENCE_ANIMATION_DECODER_H_
...@@ -1446,11 +1446,8 @@ void LockContentsView::UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update, ...@@ -1446,11 +1446,8 @@ void LockContentsView::UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update,
const bool is_keyboard_visible = const bool is_keyboard_visible =
keyboard_controller ? keyboard_controller->IsKeyboardVisible() keyboard_controller ? keyboard_controller->IsKeyboardVisible()
: false; : false;
if (state->show_pin && !is_keyboard_visible && if (state->show_pin && !is_keyboard_visible)
state->fingerprint_state ==
mojom::FingerprintUnlockState::UNAVAILABLE) {
to_update_auth |= LoginAuthUserView::AUTH_PIN; to_update_auth |= LoginAuthUserView::AUTH_PIN;
}
if (state->enable_tap_auth) if (state->enable_tap_auth)
to_update_auth |= LoginAuthUserView::AUTH_TAP; to_update_auth |= LoginAuthUserView::AUTH_TAP;
if (state->fingerprint_state != if (state->fingerprint_state !=
......
...@@ -52,6 +52,7 @@ enum { ...@@ -52,6 +52,7 @@ enum {
kGlobalCycleAuthErrorMessage, kGlobalCycleAuthErrorMessage,
kPerUserTogglePin, kPerUserTogglePin,
kPerUserCycleEasyUnlockState, kPerUserCycleEasyUnlockState,
kPerUserCycleFingerprintState,
kPerUserForceOnlineSignIn, kPerUserForceOnlineSignIn,
kPerUserToggleAuthEnabled, kPerUserToggleAuthEnabled,
kPerUserUseDetachableBase, kPerUserUseDetachableBase,
...@@ -97,6 +98,8 @@ struct UserMetadata { ...@@ -97,6 +98,8 @@ struct UserMetadata {
bool enable_auth = true; bool enable_auth = true;
user_manager::UserType type = user_manager::USER_TYPE_REGULAR; user_manager::UserType type = user_manager::USER_TYPE_REGULAR;
mojom::EasyUnlockIconId easy_unlock_id = mojom::EasyUnlockIconId::NONE; mojom::EasyUnlockIconId easy_unlock_id = mojom::EasyUnlockIconId::NONE;
mojom::FingerprintUnlockState fingerprint_state =
mojom::FingerprintUnlockState::UNAVAILABLE;
}; };
std::string DetachableBasePairingStatusToString( std::string DetachableBasePairingStatusToString(
...@@ -301,6 +304,33 @@ class LockDebugView::DebugDataDispatcherTransformer ...@@ -301,6 +304,33 @@ class LockDebugView::DebugDataDispatcherTransformer
debug_user->account_id, debug_user->enable_click_to_unlock); debug_user->account_id, debug_user->enable_click_to_unlock);
} }
// Enables fingerprint auth for the user at |user_index|.
void CycleFingerprintUnlockForUserIndex(size_t user_index) {
DCHECK(user_index >= 0 && user_index < debug_users_.size());
UserMetadata* debug_user = &debug_users_[user_index];
// FingerprintUnlockState transition.
auto get_next_state = [](mojom::FingerprintUnlockState state) {
switch (state) {
case mojom::FingerprintUnlockState::UNAVAILABLE:
return mojom::FingerprintUnlockState::AVAILABLE;
case mojom::FingerprintUnlockState::AVAILABLE:
return mojom::FingerprintUnlockState::AUTH_SUCCESS;
case mojom::FingerprintUnlockState::AUTH_SUCCESS:
return mojom::FingerprintUnlockState::AUTH_FAILED;
case mojom::FingerprintUnlockState::AUTH_FAILED:
return mojom::FingerprintUnlockState::AUTH_DISABLED;
case mojom::FingerprintUnlockState::AUTH_DISABLED:
return mojom::FingerprintUnlockState::UNAVAILABLE;
}
};
debug_user->fingerprint_state =
get_next_state(debug_user->fingerprint_state);
debug_dispatcher_.SetFingerprintUnlockState(debug_user->account_id,
debug_user->fingerprint_state);
}
// Force online sign-in for the user at |user_index|. // Force online sign-in for the user at |user_index|.
void ForceOnlineSignInForUserIndex(size_t user_index) { void ForceOnlineSignInForUserIndex(size_t user_index) {
DCHECK(user_index >= 0 && user_index < debug_users_.size()); DCHECK(user_index >= 0 && user_index < debug_users_.size());
...@@ -873,6 +903,10 @@ void LockDebugView::ButtonPressed(views::Button* sender, ...@@ -873,6 +903,10 @@ void LockDebugView::ButtonPressed(views::Button* sender,
if (sender->id() == ButtonId::kPerUserCycleEasyUnlockState) if (sender->id() == ButtonId::kPerUserCycleEasyUnlockState)
debug_data_dispatcher_->CycleEasyUnlockForUserIndex(sender->tag()); debug_data_dispatcher_->CycleEasyUnlockForUserIndex(sender->tag());
// Cycle fingerprint unlock state.
if (sender->id() == ButtonId::kPerUserCycleFingerprintState)
debug_data_dispatcher_->CycleFingerprintUnlockForUserIndex(sender->tag());
// Force online sign-in. // Force online sign-in.
if (sender->id() == ButtonId::kPerUserForceOnlineSignIn) if (sender->id() == ButtonId::kPerUserForceOnlineSignIn)
debug_data_dispatcher_->ForceOnlineSignInForUserIndex(sender->tag()); debug_data_dispatcher_->ForceOnlineSignInForUserIndex(sender->tag());
...@@ -916,6 +950,9 @@ void LockDebugView::UpdatePerUserActionContainer() { ...@@ -916,6 +950,9 @@ void LockDebugView::UpdatePerUserActionContainer() {
AddButton("Toggle PIN", ButtonId::kPerUserTogglePin, row)->set_tag(i); AddButton("Toggle PIN", ButtonId::kPerUserTogglePin, row)->set_tag(i);
AddButton("Cycle easy unlock", ButtonId::kPerUserCycleEasyUnlockState, row) AddButton("Cycle easy unlock", ButtonId::kPerUserCycleEasyUnlockState, row)
->set_tag(i); ->set_tag(i);
AddButton("Cycle fingerprint unlock",
ButtonId::kPerUserCycleFingerprintState, row)
->set_tag(i);
AddButton("Force online sign-in", ButtonId::kPerUserForceOnlineSignIn, row) AddButton("Force online sign-in", ButtonId::kPerUserForceOnlineSignIn, row)
->set_tag(i); ->set_tag(i);
AddButton("Toggle auth enabled", ButtonId::kPerUserToggleAuthEnabled, row) AddButton("Toggle auth enabled", ButtonId::kPerUserToggleAuthEnabled, row)
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <memory> #include <memory>
#include "ash/login/login_screen_controller.h" #include "ash/login/login_screen_controller.h"
#include "ash/login/resources/grit/login_resources.h"
#include "ash/login/ui/horizontal_image_sequence_animation_decoder.h"
#include "ash/login/ui/lock_screen.h" #include "ash/login/ui/lock_screen.h"
#include "ash/login/ui/login_display_style.h" #include "ash/login/ui/login_display_style.h"
#include "ash/login/ui/login_password_view.h" #include "ash/login/ui/login_password_view.h"
...@@ -51,10 +53,10 @@ constexpr const char kLoginAuthUserViewClassName[] = "LoginAuthUserView"; ...@@ -51,10 +53,10 @@ constexpr const char kLoginAuthUserViewClassName[] = "LoginAuthUserView";
const int kDistanceBetweenUserViewAndPasswordDp = 28; const int kDistanceBetweenUserViewAndPasswordDp = 28;
// Distance between the password textfield and the the pin keyboard. // Distance between the password textfield and the the pin keyboard.
const int kDistanceBetweenPasswordFieldAndPinKeyboard = 20; const int kDistanceBetweenPasswordFieldAndPinKeyboardDp = 20;
// Distance from the end of pin keyboard to the bottom of the big user view. // Distance from the end of pin keyboard to the bottom of the big user view.
const int kDistanceFromPinKeyboardToBigUserViewBottom = 50; const int kDistanceFromPinKeyboardToBigUserViewBottomDp = 50;
// Distance from the top of the user view to the user icon. // Distance from the top of the user view to the user icon.
constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54; constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54;
...@@ -62,16 +64,16 @@ constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54; ...@@ -62,16 +64,16 @@ constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54;
// The color of the online sign-in message text. // The color of the online sign-in message text.
constexpr SkColor kOnlineSignInMessageColor = SkColorSetRGB(0xE6, 0x7C, 0x73); constexpr SkColor kOnlineSignInMessageColor = SkColorSetRGB(0xE6, 0x7C, 0x73);
constexpr SkColor kFingerprintIconViewBorderColor = constexpr SkColor kFingerprintTextColor =
SkColorSetARGB(0x57, 0xFF, 0xFF, 0xFF);
constexpr SkColor kFingerprintIconAndTextColor =
SkColorSetARGB(0x8A, 0xFF, 0xFF, 0xFF); SkColorSetARGB(0x8A, 0xFF, 0xFF, 0xFF);
constexpr int kFingerprintIconViewBorderThickness = 1;
constexpr int kFingerprintIconViewSizeDp = 64;
constexpr int kFingerprintIconSizeDp = 32; constexpr int kFingerprintIconSizeDp = 32;
constexpr int kResetToDefaultIconColorDelayMs = 500; constexpr int kResetToDefaultIconDelayMs = 1300;
constexpr int kFingerprintIconTopSpacing = 50; constexpr int kFingerprintIconTopSpacingDp = 20;
constexpr int kSpacingBetweenFingerprintIconAndLabel = 20; constexpr int kSpacingBetweenFingerprintIconAndLabelDp = 15;
constexpr int kFingerprintViewWidthDp = 204;
constexpr int kDistanceBetweenPasswordFieldAndFingerprintViewDp = 90;
constexpr int kFingerprintFailedAnimationDurationMs = 700;
constexpr int kFingerprintFailedAnimationNumFrames = 45;
constexpr int kDisabledAuthMessageVerticalBorderDp = 14; constexpr int kDisabledAuthMessageVerticalBorderDp = 14;
constexpr int kDisabledAuthMessageHorizontalBorderDp = 0; constexpr int kDisabledAuthMessageHorizontalBorderDp = 0;
...@@ -83,6 +85,8 @@ constexpr int kDisabledAuthMessageTitleFontSizeDeltaDp = 3; ...@@ -83,6 +85,8 @@ constexpr int kDisabledAuthMessageTitleFontSizeDeltaDp = 3;
constexpr int kDisabledAuthMessageContentsFontSizeDeltaDp = -1; constexpr int kDisabledAuthMessageContentsFontSizeDeltaDp = -1;
constexpr int kDisabledAuthMessageRoundedCornerRadiusDp = 8; constexpr int kDisabledAuthMessageRoundedCornerRadiusDp = 8;
constexpr int kNonEmptyWidthDp = 1;
// Returns an observer that will hide |view| when it fires. The observer will // Returns an observer that will hide |view| when it fires. The observer will
// delete itself after firing. Make sure to call |observer->SetReady()| after // delete itself after firing. Make sure to call |observer->SetReady()| after
// attaching it. // attaching it.
...@@ -121,61 +125,6 @@ class ClearPasswordAnimationObserver : public ui::ImplicitAnimationObserver { ...@@ -121,61 +125,6 @@ class ClearPasswordAnimationObserver : public ui::ImplicitAnimationObserver {
DISALLOW_COPY_AND_ASSIGN(ClearPasswordAnimationObserver); DISALLOW_COPY_AND_ASSIGN(ClearPasswordAnimationObserver);
}; };
// A view which has a round border and a fingerprint icon at the center.
class FingerprintIconView : public views::View {
public:
FingerprintIconView() {
SetPreferredSize(
gfx::Size(kFingerprintIconViewSizeDp, kFingerprintIconViewSizeDp));
icon_ = new views::ImageView;
icon_->SetVerticalAlignment(views::ImageView::CENTER);
icon_->SetPreferredSize(
gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp));
icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintIcon,
kFingerprintIconSizeDp, color_));
AddChildView(icon_);
SetBorder(views::CreateRoundedRectBorder(
kFingerprintIconViewBorderThickness, kFingerprintIconViewSizeDp / 2,
kFingerprintIconViewBorderColor));
}
~FingerprintIconView() override = default;
// Set color of the icon. The color will be reset to
// kFingerprintIconAndTextColor after a short period if different.
void SetIconColor(SkColor color) {
if (color_ == color)
return;
color_ = color;
reset_icon_color_.Stop();
icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintIcon,
kFingerprintIconSizeDp, color));
if (color_ != kFingerprintIconAndTextColor) {
reset_icon_color_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kResetToDefaultIconColorDelayMs),
base::BindRepeating(&FingerprintIconView::SetIconColor,
base::Unretained(this),
kFingerprintIconAndTextColor));
}
}
void Layout() override {
gfx::Rect icon_bounds = GetContentsBounds();
icon_bounds.ClampToCenteredSize(
gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp));
icon_->SetBoundsRect(icon_bounds);
}
private:
views::ImageView* icon_ = nullptr;
base::OneShotTimer reset_icon_color_;
SkColor color_ = kFingerprintIconAndTextColor;
DISALLOW_COPY_AND_ASSIGN(FingerprintIconView);
};
} // namespace } // namespace
// Consists of fingerprint icon view and a label. // Consists of fingerprint icon view and a label.
...@@ -184,46 +133,103 @@ class LoginAuthUserView::FingerprintView : public views::View { ...@@ -184,46 +133,103 @@ class LoginAuthUserView::FingerprintView : public views::View {
FingerprintView() { FingerprintView() {
SetPaintToLayer(); SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false); layer()->SetFillsBoundsOpaquely(false);
SetBorder(views::CreateEmptyBorder(kFingerprintIconTopSpacingDp, 0, 0, 0));
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical, gfx::Insets(),
kSpacingBetweenFingerprintIconAndLabelDp));
layout->set_main_axis_alignment(
views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
icon_ = new AnimatedRoundedImageView(
gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp),
0 /*corner_radius*/);
icon_->SetImage(gfx::CreateVectorIcon(
kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE));
AddChildView(icon_);
icon_view_ = new FingerprintIconView();
AddChildView(icon_view_);
label_ = new views::Label( label_ = new views::Label(
l10n_util::GetStringUTF16(IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_MESSAGE)); l10n_util::GetStringUTF16(IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_MESSAGE));
label_->SetSubpixelRenderingEnabled(false); label_->SetSubpixelRenderingEnabled(false);
label_->SetAutoColorReadabilityEnabled(false); label_->SetAutoColorReadabilityEnabled(false);
label_->SetEnabledColor(kFingerprintIconAndTextColor); label_->SetEnabledColor(kFingerprintTextColor);
AddChildView(label_); AddChildView(label_);
} }
void SetIconColor(SkColor color) { icon_view_->SetIconColor(color); } void SetIcon(mojom::FingerprintUnlockState state) {
switch (state) {
void Layout() override { case mojom::FingerprintUnlockState::UNAVAILABLE:
gfx::Rect bounds = GetContentsBounds(); case mojom::FingerprintUnlockState::AVAILABLE:
icon_view_->SizeToPreferredSize(); case mojom::FingerprintUnlockState::AUTH_SUCCESS:
icon_view_->SetPosition( icon_->SetImage(gfx::CreateVectorIcon(
gfx::Point((bounds.width() - icon_view_->width()) / 2, kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE));
bounds.y() + kFingerprintIconTopSpacing)); return;
label_->SizeToPreferredSize(); case mojom::FingerprintUnlockState::AUTH_FAILED:
label_->SetPosition( case mojom::FingerprintUnlockState::AUTH_DISABLED:
gfx::Point(bounds.x(), icon_view_->bounds().bottom() + icon_->SetAnimationDecoder(
kSpacingBetweenFingerprintIconAndLabel)); std::make_unique<HorizontalImageSequenceAnimationDecoder>(
*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
IDR_LOGIN_FINGERPRINT_UNLOCK_SPINNER),
base::TimeDelta::FromMilliseconds(
kFingerprintFailedAnimationDurationMs),
kFingerprintFailedAnimationNumFrames),
AnimatedRoundedImageView::Playback::kSingle);
return;
}
}
void SetText(mojom::FingerprintUnlockState state) {
auto get_label_id = [&]() -> int {
switch (state) {
case mojom::FingerprintUnlockState::UNAVAILABLE:
case mojom::FingerprintUnlockState::AVAILABLE:
case mojom::FingerprintUnlockState::AUTH_SUCCESS:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_MESSAGE;
case mojom::FingerprintUnlockState::AUTH_FAILED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_FAILED_MESSAGE;
case mojom::FingerprintUnlockState::AUTH_DISABLED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_MESSAGE;
}
};
label_->SetText(l10n_util::GetStringUTF16(get_label_id()));
}
void SetState(mojom::FingerprintUnlockState state) {
if (state_ == state)
return;
state_ = state;
SetVisible(state != mojom::FingerprintUnlockState::UNAVAILABLE);
SetIcon(state);
SetText(state);
// Fingerprint icon reset to default sometime after AUTH_FAILED.
reset_state_.Stop();
if (state == mojom::FingerprintUnlockState::AUTH_FAILED) {
reset_state_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kResetToDefaultIconDelayMs),
base::BindRepeating(&FingerprintView::SetState,
base::Unretained(this),
mojom::FingerprintUnlockState::AVAILABLE));
}
} }
~FingerprintView() override = default; ~FingerprintView() override = default;
gfx::Size CalculatePreferredSize() const override { gfx::Size CalculatePreferredSize() const override {
int preferred_height = label_->GetPreferredSize().height() + gfx::Size size = views::View::CalculatePreferredSize();
icon_view_->GetPreferredSize().height() + size.set_width(kFingerprintViewWidthDp);
kFingerprintIconTopSpacing + return size;
kSpacingBetweenFingerprintIconAndLabel;
int preferred_width = std::max(label_->GetPreferredSize().width(),
icon_view_->GetPreferredSize().width());
return gfx::Size(preferred_width, preferred_height);
} }
private: private:
FingerprintIconView* icon_view_ = nullptr;
views::Label* label_ = nullptr; views::Label* label_ = nullptr;
AnimatedRoundedImageView* icon_ = nullptr;
base::OneShotTimer reset_state_;
mojom::FingerprintUnlockState state_ =
mojom::FingerprintUnlockState::UNAVAILABLE;
DISALLOW_COPY_AND_ASSIGN(FingerprintView); DISALLOW_COPY_AND_ASSIGN(FingerprintView);
}; };
...@@ -308,6 +314,7 @@ struct LoginAuthUserView::AnimationState { ...@@ -308,6 +314,7 @@ struct LoginAuthUserView::AnimationState {
gfx::Point pin_start_in_screen; gfx::Point pin_start_in_screen;
bool had_pin = false; bool had_pin = false;
bool had_password = false; bool had_password = false;
bool had_fingerprint = false;
explicit AnimationState(LoginAuthUserView* view) { explicit AnimationState(LoginAuthUserView* view) {
non_pin_y_start_in_screen = view->GetBoundsInScreen().y(); non_pin_y_start_in_screen = view->GetBoundsInScreen().y();
...@@ -316,6 +323,8 @@ struct LoginAuthUserView::AnimationState { ...@@ -316,6 +323,8 @@ struct LoginAuthUserView::AnimationState {
had_pin = (view->auth_methods() & LoginAuthUserView::AUTH_PIN) != 0; had_pin = (view->auth_methods() & LoginAuthUserView::AUTH_PIN) != 0;
had_password = had_password =
(view->auth_methods() & LoginAuthUserView::AUTH_PASSWORD) != 0; (view->auth_methods() & LoginAuthUserView::AUTH_PASSWORD) != 0;
had_fingerprint =
(view->auth_methods() & LoginAuthUserView::AUTH_FINGERPRINT) != 0;
} }
}; };
...@@ -383,6 +392,10 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user, ...@@ -383,6 +392,10 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
base::Unretained(password_view_))); base::Unretained(password_view_)));
DCHECK(pin_view_->layer()); DCHECK(pin_view_->layer());
padding_below_password_view_ = new NonAccessibleView();
padding_below_password_view_->SetPreferredSize(gfx::Size(
kNonEmptyWidthDp, kDistanceBetweenPasswordFieldAndPinKeyboardDp));
// Initialization of |password_view_| is deferred because it needs the // Initialization of |password_view_| is deferred because it needs the
// |pin_view_| pointer. // |pin_view_| pointer.
password_view_->Init( password_view_->Init(
...@@ -415,14 +428,17 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user, ...@@ -415,14 +428,17 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
login_views_utils::WrapViewForPreferredSize(pin_view_); login_views_utils::WrapViewForPreferredSize(pin_view_);
auto* wrapped_fingerprint_view = auto* wrapped_fingerprint_view =
login_views_utils::WrapViewForPreferredSize(fingerprint_view_); login_views_utils::WrapViewForPreferredSize(fingerprint_view_);
auto* wrapped_padding_below_password_view =
login_views_utils::WrapViewForPreferredSize(padding_below_password_view_);
// Add views in tabbing order; they are rendered in a different order below. // Add views in tabbing order; they are rendered in a different order below.
AddChildView(wrapped_password_view); AddChildView(wrapped_password_view);
AddChildView(wrapped_online_sign_in_message_view); AddChildView(wrapped_online_sign_in_message_view);
AddChildView(wrapped_disabled_auth_message_view); AddChildView(wrapped_disabled_auth_message_view);
AddChildView(wrapped_fingerprint_view);
AddChildView(wrapped_pin_view); AddChildView(wrapped_pin_view);
AddChildView(wrapped_fingerprint_view);
AddChildView(wrapped_user_view); AddChildView(wrapped_user_view);
AddChildView(wrapped_padding_below_password_view);
// Use views::GridLayout instead of views::BoxLayout because views::BoxLayout // Use views::GridLayout instead of views::BoxLayout because views::BoxLayout
// lays out children according to the view->children order. // lays out children according to the view->children order.
...@@ -447,10 +463,10 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user, ...@@ -447,10 +463,10 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
add_view(wrapped_password_view); add_view(wrapped_password_view);
add_view(wrapped_online_sign_in_message_view); add_view(wrapped_online_sign_in_message_view);
add_view(wrapped_disabled_auth_message_view); add_view(wrapped_disabled_auth_message_view);
add_padding(kDistanceBetweenPasswordFieldAndPinKeyboard); add_view(wrapped_padding_below_password_view);
add_view(wrapped_fingerprint_view);
add_view(wrapped_pin_view); add_view(wrapped_pin_view);
add_padding(kDistanceFromPinKeyboardToBigUserViewBottom); add_view(wrapped_fingerprint_view);
add_padding(kDistanceFromPinKeyboardToBigUserViewBottomDp);
// Update authentication UI. // Update authentication UI.
SetAuthMethods(auth_methods_); SetAuthMethods(auth_methods_);
...@@ -485,6 +501,13 @@ void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods) { ...@@ -485,6 +501,13 @@ void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods) {
pin_view_->SetVisible(has_pin); pin_view_->SetVisible(has_pin);
fingerprint_view_->SetVisible(has_fingerprint); fingerprint_view_->SetVisible(has_fingerprint);
int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp;
if (has_fingerprint && !has_pin) {
padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp;
}
padding_below_password_view_->SetPreferredSize(
gfx::Size(kNonEmptyWidthDp, padding_view_height));
// Note: if both |has_tap| and |has_pin| are true, prefer tap placeholder. // Note: if both |has_tap| and |has_pin| are true, prefer tap placeholder.
if (has_tap) { if (has_tap) {
password_view_->SetPlaceholderText( password_view_->SetPlaceholderText(
...@@ -529,6 +552,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() { ...@@ -529,6 +552,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
bool has_password = (auth_methods() & AUTH_PASSWORD) != 0; bool has_password = (auth_methods() & AUTH_PASSWORD) != 0;
bool has_pin = (auth_methods() & AUTH_PIN) != 0; bool has_pin = (auth_methods() & AUTH_PIN) != 0;
bool has_fingerprint = (auth_methods() & AUTH_FINGERPRINT) != 0;
//////// ////////
// Animate the user info (ie, icon, name) up or down the screen. // Animate the user info (ie, icon, name) up or down the screen.
...@@ -612,6 +636,26 @@ void LoginAuthUserView::ApplyAnimationPostLayout() { ...@@ -612,6 +636,26 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
pin_view_->layer()->GetAnimator()->ScheduleAnimation(sequence); pin_view_->layer()->GetAnimator()->ScheduleAnimation(sequence);
} }
////////
// Fade the fingerprint view if it is being hidden or shown.
if (cached_animation_state_->had_fingerprint != has_fingerprint) {
float opacity_start = 0, opacity_end = 1;
if (!has_fingerprint)
std::swap(opacity_start, opacity_end);
fingerprint_view_->layer()->SetOpacity(opacity_start);
{
ui::ScopedLayerAnimationSettings settings(
password_view_->layer()->GetAnimator());
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
login_constants::kChangeUserAnimationDurationMs));
settings.SetTweenType(gfx::Tween::Type::FAST_OUT_SLOW_IN);
fingerprint_view_->layer()->SetOpacity(opacity_end);
}
}
cached_animation_state_.reset(); cached_animation_state_.reset();
} }
...@@ -625,16 +669,7 @@ void LoginAuthUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) { ...@@ -625,16 +669,7 @@ void LoginAuthUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
void LoginAuthUserView::SetFingerprintState( void LoginAuthUserView::SetFingerprintState(
mojom::FingerprintUnlockState state) { mojom::FingerprintUnlockState state) {
fingerprint_view_->SetVisible(state != fingerprint_view_->SetState(state);
mojom::FingerprintUnlockState::UNAVAILABLE);
SkColor color = kFingerprintIconAndTextColor;
if (state == mojom::FingerprintUnlockState::AUTH_SUCCESS) {
color = SK_ColorBLUE;
} else if (state == mojom::FingerprintUnlockState::AUTH_FAILED) {
color = SK_ColorRED;
}
fingerprint_view_->SetIconColor(color);
} }
void LoginAuthUserView::SetAuthReenabledTime( void LoginAuthUserView::SetAuthReenabledTime(
......
...@@ -165,6 +165,11 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView, ...@@ -165,6 +165,11 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
views::LabelButton* online_sign_in_message_ = nullptr; views::LabelButton* online_sign_in_message_ = nullptr;
DisabledAuthMessageView* disabled_auth_message_ = nullptr; DisabledAuthMessageView* disabled_auth_message_ = nullptr;
FingerprintView* fingerprint_view_ = nullptr; FingerprintView* fingerprint_view_ = nullptr;
// Displays padding between:
// 1. Password field and pin keyboard
// 2. Password field and fingerprint view, when pin is not available.
// Preferred size will change base on current auth method.
NonAccessibleView* padding_below_password_view_ = nullptr;
const OnAuthCallback on_auth_; const OnAuthCallback on_auth_;
const LoginUserView::OnTap on_tap_; const LoginUserView::OnTap on_tap_;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ash/login/ui/login_password_view.h" #include "ash/login/ui/login_password_view.h"
#include "ash/login/ui/horizontal_image_sequence_animation_decoder.h"
#include "ash/login/ui/hover_notifier.h" #include "ash/login/ui/hover_notifier.h"
#include "ash/login/ui/lock_screen.h" #include "ash/login/ui/lock_screen.h"
#include "ash/login/ui/login_button.h" #include "ash/login/ui/login_button.h"
...@@ -159,62 +160,6 @@ IconBundle GetEasyUnlockResources(mojom::EasyUnlockIconId id) { ...@@ -159,62 +160,6 @@ IconBundle GetEasyUnlockResources(mojom::EasyUnlockIconId id) {
IDR_EASY_UNLOCK_LOCKED_PRESSED); IDR_EASY_UNLOCK_LOCKED_PRESSED);
} }
// Decodes an animation strip that is laid out 1xN (ie, the image grows in
// width, not height). There is no padding between frames in the animation
// strip.
//
// As an example, if the following ASCII art is 100 pixels wide, it has 4 frames
// each 25 pixels wide. The frames go from [0, 25), [25, 50), [50, 75), [75,
// 100). All frames have the same height of 25 pixels.
//
// [1][2][3][4]
//
class EasyUnlockAnimationDecoder
: public AnimatedRoundedImageView::AnimationDecoder {
public:
EasyUnlockAnimationDecoder(const gfx::ImageSkia& image,
base::TimeDelta duration,
int num_frames)
: image_(image), duration_(duration), num_frames_(num_frames) {}
~EasyUnlockAnimationDecoder() override = default;
// AnimatedRoundedImageView::AnimationDecoder:
AnimationFrames Decode(float image_scale) override {
SkBitmap bitmap = image_.GetRepresentation(image_scale).sk_bitmap();
int frame_width = bitmap.width() / num_frames_;
base::TimeDelta frame_duration = duration_ / num_frames_;
AnimationFrames animation;
animation.reserve(num_frames_);
for (int i = 0; i < num_frames_; ++i) {
// Get the subsection of the animation strip.
SkBitmap frame_bitmap;
bitmap.extractSubset(
&frame_bitmap,
SkIRect::MakeXYWH(i * frame_width, 0, frame_width, bitmap.height()));
// Add an animation frame.
AnimationFrame frame;
frame.duration = frame_duration;
frame.image = gfx::ImageSkia::CreateFrom1xBitmap(frame_bitmap);
animation.push_back(frame);
}
return animation;
}
private:
// The animation image source.
gfx::ImageSkia image_;
// The total duration of the animation.
base::TimeDelta duration_;
// The total number of frames in the animation.
int num_frames_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockAnimationDecoder);
};
} // namespace } // namespace
class LoginPasswordView::EasyUnlockIcon : public views::Button, class LoginPasswordView::EasyUnlockIcon : public views::Button,
...@@ -225,7 +170,6 @@ class LoginPasswordView::EasyUnlockIcon : public views::Button, ...@@ -225,7 +170,6 @@ class LoginPasswordView::EasyUnlockIcon : public views::Button,
SetPreferredSize(size); SetPreferredSize(size);
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
icon_ = new AnimatedRoundedImageView(size, corner_radius); icon_ = new AnimatedRoundedImageView(size, corner_radius);
icon_->SetAnimationEnabled(true);
AddChildView(icon_); AddChildView(icon_);
} }
~EasyUnlockIcon() override = default; ~EasyUnlockIcon() override = default;
...@@ -328,8 +272,10 @@ class LoginPasswordView::EasyUnlockIcon : public views::Button, ...@@ -328,8 +272,10 @@ class LoginPasswordView::EasyUnlockIcon : public views::Button,
DCHECK_EQ(resources.normal, resources.hover); DCHECK_EQ(resources.normal, resources.hover);
DCHECK_EQ(resources.normal, resources.pressed); DCHECK_EQ(resources.normal, resources.pressed);
if (changed_states) { if (changed_states) {
icon_->SetAnimationDecoder(std::make_unique<EasyUnlockAnimationDecoder>( icon_->SetAnimationDecoder(
*image, resources.duration, resources.num_frames)); std::make_unique<HorizontalImageSequenceAnimationDecoder>(
*image, resources.duration, resources.num_frames),
AnimatedRoundedImageView::Playback::kRepeat);
} }
} else { } else {
icon_->SetImage(*image); icon_->SetImage(*image);
......
...@@ -139,7 +139,11 @@ class LoginUserView::UserImage : public NonAccessibleView { ...@@ -139,7 +139,11 @@ class LoginUserView::UserImage : public NonAccessibleView {
} }
} }
void SetAnimationEnabled(bool enable) { image_->SetAnimationEnabled(enable); } void SetAnimationEnabled(bool enable) {
image_->SetAnimationPlayback(
enable ? AnimatedRoundedImageView::Playback::kRepeat
: AnimatedRoundedImageView::Playback::kFirstFrameOnly);
}
private: private:
void OnImageDecoded(AnimationFrames animation) { void OnImageDecoded(AnimationFrames animation) {
...@@ -150,7 +154,8 @@ class LoginUserView::UserImage : public NonAccessibleView { ...@@ -150,7 +154,8 @@ class LoginUserView::UserImage : public NonAccessibleView {
} }
image_->SetAnimationDecoder( image_->SetAnimationDecoder(
std::make_unique<PassthroughAnimationDecoder>(animation)); std::make_unique<PassthroughAnimationDecoder>(animation),
AnimatedRoundedImageView::Playback::kRepeat);
} }
AnimatedRoundedImageView* image_ = nullptr; AnimatedRoundedImageView* image_ = nullptr;
......
...@@ -46,8 +46,14 @@ enum FingerprintUnlockState { ...@@ -46,8 +46,14 @@ enum FingerprintUnlockState {
AVAILABLE, AVAILABLE,
// The unlock attempt is successful, the fingerprint is matched. // The unlock attempt is successful, the fingerprint is matched.
AUTH_SUCCESS, AUTH_SUCCESS,
// The unlock attempt is unsuccessful, the fingerprint is not recognized. // The unlock attempt is unsuccessful; the fingerprint is not
// recognized; however, the user can make another fingerprint auth
// attempt.
AUTH_FAILED, AUTH_FAILED,
// The unlock attempt is unsuccessful; the fingerprint is not
// recognized. There have been too many unlock attempts and fingerprint
// is now disabled.
AUTH_DISABLED,
}; };
// Information about the custom icon in the user pod. // Information about the custom icon in the user pod.
......
...@@ -42,14 +42,16 @@ constexpr char kLockDisplay[] = "lock"; ...@@ -42,14 +42,16 @@ constexpr char kLockDisplay[] = "lock";
ash::mojom::FingerprintUnlockState ConvertFromFingerprintState( ash::mojom::FingerprintUnlockState ConvertFromFingerprintState(
ScreenLocker::FingerprintState state) { ScreenLocker::FingerprintState state) {
switch (state) { switch (state) {
case ScreenLocker::FingerprintState::kRemoved:
case ScreenLocker::FingerprintState::kHidden: case ScreenLocker::FingerprintState::kHidden:
case ScreenLocker::FingerprintState::kDefault:
return ash::mojom::FingerprintUnlockState::UNAVAILABLE; return ash::mojom::FingerprintUnlockState::UNAVAILABLE;
case ScreenLocker::FingerprintState::kDefault:
return ash::mojom::FingerprintUnlockState::AVAILABLE;
case ScreenLocker::FingerprintState::kSignin: case ScreenLocker::FingerprintState::kSignin:
return ash::mojom::FingerprintUnlockState::AUTH_SUCCESS; return ash::mojom::FingerprintUnlockState::AUTH_SUCCESS;
case ScreenLocker::FingerprintState::kFailed: case ScreenLocker::FingerprintState::kFailed:
return ash::mojom::FingerprintUnlockState::AUTH_FAILED; return ash::mojom::FingerprintUnlockState::AUTH_FAILED;
case ScreenLocker::FingerprintState::kRemoved:
return ash::mojom::FingerprintUnlockState::AUTH_DISABLED;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment