1 /*
2  * Copyright (C) 2023 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.cts.verifier.vibrations;
18 
19 import android.os.Bundle;
20 import android.os.CountDownTimer;
21 import android.os.VibrationEffect;
22 import android.os.Vibrator;
23 import android.os.VibratorManager;
24 import android.view.View;
25 import android.view.animation.Animation;
26 import android.view.animation.AnimationUtils;
27 import android.widget.Button;
28 import android.widget.LinearLayout;
29 import android.widget.TextView;
30 
31 import com.android.compatibility.common.util.ApiTest;
32 import com.android.cts.verifier.PassFailButtons;
33 import com.android.cts.verifier.R;
34 
35 import java.util.Locale;
36 
37 /**
38  * This activity validates the result of {@link Vibrator#hasVibrator} API.
39  *
40  * A test is considered a positive scenario when hasVibrator returns true, otherwise the test is
41  * a negative scenario.
42  */
43 @ApiTest(apis = {"android.os.Vibrator#hasVibrator"})
44 public class HasVibratorVerifierActivity extends PassFailButtons.Activity {
45 
46     private static final int TEST_DURATION = 4_000;
47     private static final int COUNT_DOWN_INTERVAL = 1_000;
48 
49     private boolean mHasVibrator = false;
50     private int mCounter = TEST_DURATION / COUNT_DOWN_INTERVAL;
51     private Vibrator mVibrator;
52     private Animation mShakeAnimation;
53     private TextView mVibrateCountdownTextView;
54     private TextView mTestResultTextView;
55     private TextView mDidDeviceVibrateTextView;
56     private LinearLayout mResultButtonsLayout;
57     private Button mVibrateButton;
58 
59     @Override
onCreate(Bundle savedInstanceState)60     protected void onCreate(Bundle savedInstanceState) {
61         super.onCreate(savedInstanceState);
62 
63         setContentView(R.layout.activity_has_vibrator);
64 
65         setPassFailButtonClickListeners();
66         getPassButton().setEnabled(false);
67 
68         mVibrateCountdownTextView = findViewById(R.id.vibrate_countdown_textview);
69         mTestResultTextView = findViewById(R.id.test_result_textview);
70         mDidDeviceVibrateTextView = findViewById(R.id.did_device_vibrate_textview);
71         mResultButtonsLayout = findViewById(R.id.layout_result_buttons);
72         mVibrateButton = findViewById(R.id.vibrate_button);
73         TextView hasVibratorApiResultTextView = findViewById(R.id.has_vibrator_api_result_textview);
74         Button yesButton = findViewById(R.id.yes_button);
75         Button noButton = findViewById(R.id.no_button);
76 
77         mShakeAnimation = AnimationUtils.loadAnimation(this, R.anim.horizontal_shake);
78 
79         VibratorManager vibratorManager = getSystemService(VibratorManager.class);
80         if (vibratorManager == null) {
81             throw new IllegalStateException(
82                     "Something went wrong while creating the VibratorManager");
83         }
84         mVibrator = vibratorManager.getDefaultVibrator();
85         mHasVibrator = mVibrator.hasVibrator();
86 
87         hasVibratorApiResultTextView.setText(
88                 mHasVibrator ? R.string.yes_string : R.string.no_string);
89 
90         mVibrateButton.setOnClickListener(v -> {
91             startVibrating();
92             updateScreenStateToStartedTesting();
93             startAnimationIfRequired();
94             startTestCountdown();
95         });
96 
97         yesButton.setOnClickListener(v -> onYesButtonClicked());
98         noButton.setOnClickListener(v -> onNoButtonClicked());
99     }
100 
startVibrating()101     private void startVibrating() {
102         mVibrator.vibrate(
103                 VibrationEffect.createOneShot(TEST_DURATION, VibrationEffect.MAX_AMPLITUDE));
104     }
105 
startTestCountdown()106     private void startTestCountdown() {
107         new CountDownTimer(TEST_DURATION, COUNT_DOWN_INTERVAL) {
108             public void onTick(long millisUntilFinished) {
109                 mVibrateCountdownTextView.setText(
110                         String.format(Locale.getDefault(),
111                                 getString(R.string.has_vibrator_test_running_text), mCounter));
112                 mCounter--;
113             }
114 
115             public void onFinish() {
116                 updateScreenStateToFinishedTesting();
117                 mCounter = TEST_DURATION / COUNT_DOWN_INTERVAL;
118                 mVibrateCountdownTextView.clearAnimation();
119             }
120         }.start();
121     }
122 
123     /**
124      * If Vibrator#hasVibrator API indicated the device has a vibrator, and the device vibrated,
125      * then the test passed. Otherwise, if the device vibrated despite the API indicating the device
126      * has no vibrator then the test failed.
127      */
onYesButtonClicked()128     private void onYesButtonClicked() {
129         mTestResultTextView.setVisibility(View.VISIBLE);
130         getPassButton().setEnabled(mHasVibrator);
131         if (mHasVibrator) {
132             mTestResultTextView.setText(R.string.has_vibrator_test_vibrate_and_pass_message);
133         } else {
134             mTestResultTextView.setText(R.string.has_vibrator_test_no_vibrate_and_fail_message);
135         }
136     }
137 
138     /**
139      * If Vibrator#hasVibrator API indicated the device has no vibrator, and the device did not
140      * vibrate, then the test passed. Otherwise, if the device did vibrate despite the API
141      * indicating the device has no vibrator then the test failed.
142      */
onNoButtonClicked()143     private void onNoButtonClicked() {
144         mTestResultTextView.setVisibility(View.VISIBLE);
145         getPassButton().setEnabled(!mHasVibrator);
146         if (!mHasVibrator) {
147             mTestResultTextView.setText(R.string.has_vibrator_test_no_vibrate_and_pass_message);
148         } else {
149             mTestResultTextView.setText(R.string.has_vibrator_test_vibrate_and_fail_message);
150         }
151     }
152 
updateScreenStateToStartedTesting()153     private void updateScreenStateToStartedTesting() {
154         mTestResultTextView.setVisibility(View.GONE);
155         mVibrateButton.setVisibility(View.GONE);
156         mDidDeviceVibrateTextView.setVisibility(View.GONE);
157         mResultButtonsLayout.setVisibility(View.GONE);
158         mVibrateCountdownTextView.setVisibility(View.VISIBLE);
159     }
160 
updateScreenStateToFinishedTesting()161     private void updateScreenStateToFinishedTesting() {
162         mVibrateButton.setVisibility(View.VISIBLE);
163         mDidDeviceVibrateTextView.setVisibility(View.VISIBLE);
164         mResultButtonsLayout.setVisibility(View.VISIBLE);
165         mVibrateCountdownTextView.setVisibility(View.GONE);
166     }
167 
startAnimationIfRequired()168     private void startAnimationIfRequired() {
169         if (mHasVibrator) {
170             mVibrateCountdownTextView.clearAnimation();
171             mVibrateCountdownTextView.startAnimation(mShakeAnimation);
172         }
173     }
174 }
175