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.dialer.dialpadview;
18 
19 import android.animation.Animator;
20 import android.animation.Animator.AnimatorListener;
21 import android.animation.ArgbEvaluator;
22 import android.animation.ValueAnimator;
23 import android.content.Context;
24 import android.graphics.Color;
25 import android.graphics.ColorFilter;
26 import android.graphics.LightingColorFilter;
27 import android.os.Handler;
28 import android.os.Vibrator;
29 import android.view.View;
30 
31 /** Animates the dial button on "emergency" phone numbers. */
32 public class PseudoEmergencyAnimator {
33 
34   static final String PSEUDO_EMERGENCY_NUMBER = "01189998819991197253";
35   private static final int VIBRATE_LENGTH_MILLIS = 200;
36   private static final int ITERATION_LENGTH_MILLIS = 1000;
37   private static final int ANIMATION_ITERATION_COUNT = 6;
38   private ViewProvider viewProvider;
39   private ValueAnimator pseudoEmergencyColorAnimator;
40 
PseudoEmergencyAnimator(ViewProvider viewProvider)41   PseudoEmergencyAnimator(ViewProvider viewProvider) {
42     this.viewProvider = viewProvider;
43   }
44 
destroy()45   public void destroy() {
46     end();
47     viewProvider = null;
48   }
49 
start()50   public void start() {
51     if (pseudoEmergencyColorAnimator == null) {
52       Integer colorFrom = Color.BLUE;
53       Integer colorTo = Color.RED;
54       pseudoEmergencyColorAnimator =
55           ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
56 
57       pseudoEmergencyColorAnimator.addUpdateListener(
58           animator -> {
59             try {
60               int color = (int) animator.getAnimatedValue();
61               ColorFilter colorFilter = new LightingColorFilter(Color.BLACK, color);
62 
63               if (viewProvider.getFab() != null) {
64                 viewProvider.getFab().getBackground().setColorFilter(colorFilter);
65               }
66             } catch (Exception e) {
67               animator.cancel();
68             }
69           });
70 
71       pseudoEmergencyColorAnimator.addListener(
72           new AnimatorListener() {
73             @Override
74             public void onAnimationCancel(Animator animation) {}
75 
76             @Override
77             public void onAnimationRepeat(Animator animation) {
78               try {
79                 vibrate(VIBRATE_LENGTH_MILLIS);
80               } catch (Exception e) {
81                 animation.cancel();
82               }
83             }
84 
85             @Override
86             public void onAnimationStart(Animator animation) {}
87 
88             @Override
89             public void onAnimationEnd(Animator animation) {
90               try {
91                 if (viewProvider.getFab() != null) {
92                   viewProvider.getFab().getBackground().clearColorFilter();
93                 }
94 
95                 new Handler()
96                     .postDelayed(
97                         () -> {
98                           try {
99                             vibrate(VIBRATE_LENGTH_MILLIS);
100                           } catch (Exception e) {
101                             // ignored
102                           }
103                         },
104                         ITERATION_LENGTH_MILLIS);
105               } catch (Exception e) {
106                 animation.cancel();
107               }
108             }
109           });
110 
111       pseudoEmergencyColorAnimator.setDuration(VIBRATE_LENGTH_MILLIS);
112       pseudoEmergencyColorAnimator.setRepeatMode(ValueAnimator.REVERSE);
113       pseudoEmergencyColorAnimator.setRepeatCount(ANIMATION_ITERATION_COUNT);
114     }
115     if (!pseudoEmergencyColorAnimator.isStarted()) {
116       pseudoEmergencyColorAnimator.start();
117     }
118   }
119 
end()120   public void end() {
121     if (pseudoEmergencyColorAnimator != null && pseudoEmergencyColorAnimator.isStarted()) {
122       pseudoEmergencyColorAnimator.end();
123     }
124   }
125 
vibrate(long milliseconds)126   private void vibrate(long milliseconds) {
127     Context context = viewProvider.getContext();
128     if (context != null) {
129       Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
130       if (vibrator != null) {
131         vibrator.vibrate(milliseconds);
132       }
133     }
134   }
135 
136   interface ViewProvider {
137 
getFab()138     View getFab();
139 
getContext()140     Context getContext();
141   }
142 }
143