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