1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.settings.biometrics.fingerprint; 18 19 import android.content.ContentResolver; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.graphics.SurfaceTexture; 23 import android.media.MediaPlayer; 24 import android.media.MediaPlayer.OnInfoListener; 25 import android.media.MediaPlayer.OnPreparedListener; 26 import android.net.Uri; 27 import android.util.AttributeSet; 28 import android.view.Surface; 29 import android.view.TextureView; 30 import android.view.View; 31 32 import androidx.annotation.VisibleForTesting; 33 34 import com.android.settings.R; 35 36 /** 37 * A view containing a VideoView for showing the user how to enroll a fingerprint 38 */ 39 public class FingerprintLocationAnimationVideoView extends TextureView 40 implements FingerprintFindSensorAnimation { 41 protected float mAspect = 1.0f; // initial guess until we know 42 protected MediaPlayer mMediaPlayer; 43 FingerprintLocationAnimationVideoView(Context context, AttributeSet attrs)44 public FingerprintLocationAnimationVideoView(Context context, AttributeSet attrs) { 45 super(context, attrs); 46 } 47 48 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)49 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 50 // Width is driven by measurespec, height is derrived from aspect ratio 51 int originalWidth = MeasureSpec.getSize(widthMeasureSpec); 52 int height = Math.round(mAspect * originalWidth); 53 super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 54 } 55 getFingerprintLocationAnimation()56 protected Uri getFingerprintLocationAnimation() { 57 return resourceEntryToUri(getContext(), R.raw.fingerprint_location_animation); 58 } 59 60 @Override onFinishInflate()61 protected void onFinishInflate() { 62 super.onFinishInflate(); 63 setSurfaceTextureListener(new SurfaceTextureListener() { 64 private SurfaceTexture mTextureToDestroy = null; 65 66 @Override 67 public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, 68 int height) { 69 setVisibility(View.INVISIBLE); 70 Uri videoUri = getFingerprintLocationAnimation(); 71 if (mMediaPlayer != null) { 72 mMediaPlayer.release(); 73 } 74 if (mTextureToDestroy != null) { 75 mTextureToDestroy.release(); 76 mTextureToDestroy = null; 77 } 78 mMediaPlayer = createMediaPlayer(mContext, videoUri); 79 if (mMediaPlayer == null) { 80 // MediaPlayer.create() method can return null 81 return; 82 } 83 mMediaPlayer.setSurface(new Surface(surfaceTexture)); 84 mMediaPlayer.setOnPreparedListener(new OnPreparedListener() { 85 @Override 86 public void onPrepared(MediaPlayer mediaPlayer) { 87 mediaPlayer.setLooping(true); 88 } 89 }); 90 mMediaPlayer.setOnInfoListener(new OnInfoListener() { 91 @Override 92 public boolean onInfo(MediaPlayer mediaPlayer, int what, int extra) { 93 if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) { 94 // Keep the view hidden until video starts 95 setVisibility(View.VISIBLE); 96 } 97 return false; 98 } 99 }); 100 mAspect = (float) mMediaPlayer.getVideoHeight() / mMediaPlayer.getVideoWidth(); 101 requestLayout(); 102 startAnimation(); 103 } 104 105 @Override 106 public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, 107 int width, int height) { 108 } 109 110 @Override 111 public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { 112 mTextureToDestroy = surfaceTexture; 113 return false; 114 } 115 116 @Override 117 public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { 118 } 119 }); 120 } 121 122 @VisibleForTesting createMediaPlayer(Context context, Uri videoUri)123 MediaPlayer createMediaPlayer(Context context, Uri videoUri) { 124 return MediaPlayer.create(mContext, videoUri); 125 } 126 resourceEntryToUri(Context context, int id)127 protected static Uri resourceEntryToUri (Context context, int id) { 128 Resources res = context.getResources(); 129 return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + 130 res.getResourcePackageName(id) + '/' + 131 res.getResourceTypeName(id) + '/' + 132 res.getResourceEntryName(id)); 133 } 134 135 @Override startAnimation()136 public void startAnimation() { 137 if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) { 138 mMediaPlayer.start(); 139 } 140 } 141 142 @Override stopAnimation()143 public void stopAnimation() { 144 if (mMediaPlayer != null) { 145 mMediaPlayer.stop(); 146 mMediaPlayer.release(); 147 mMediaPlayer = null; 148 } 149 } 150 151 @Override pauseAnimation()152 public void pauseAnimation() { 153 if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { 154 mMediaPlayer.pause(); 155 } 156 } 157 158 } 159