1 /* 2 * Copyright 2020 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 android.hardware.input.cts.tests; 18 19 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 20 21 import static org.junit.Assume.assumeFalse; 22 23 import android.app.UiAutomation; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.res.Resources; 30 import android.hardware.cts.R; 31 import android.hardware.input.cts.InputAssistantActivity; 32 import android.server.wm.WindowManagerStateHelper; 33 import android.speech.RecognizerIntent; 34 35 import androidx.test.InstrumentationRegistry; 36 import androidx.test.ext.junit.runners.AndroidJUnit4; 37 import androidx.test.filters.SmallTest; 38 39 import com.android.compatibility.common.util.UserHelper; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 46 import java.util.ArrayList; 47 import java.util.List; 48 49 @SmallTest 50 @RunWith(AndroidJUnit4.class) 51 public class UsbVoiceCommandTest extends InputHidTestCase { 52 private static final String TAG = "UsbVoiceCommandTest"; 53 54 private final UiAutomation mUiAutomation = 55 InstrumentationRegistry.getInstrumentation().getUiAutomation(); 56 private final PackageManager mPackageManager = 57 InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(); 58 private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); 59 private final Intent mVoiceIntent; 60 private final Intent mWebIntent; 61 private final List<String> mExcludedPackages = new ArrayList<String>(); 62 63 // Simulates the behavior of Google Gamepad with Voice Command buttons. UsbVoiceCommandTest()64 public UsbVoiceCommandTest() { 65 super(R.raw.google_gamepad_usb_register); 66 mVoiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 67 mVoiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 68 mWebIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 69 addDelayAfterSetup(); 70 } 71 setPackageState(boolean enabled)72 private void setPackageState(boolean enabled) throws Exception { 73 runWithShellPermissionIdentity(mUiAutomation, () -> { 74 for (int i = 0; i < mExcludedPackages.size(); i++) { 75 if (enabled) { 76 mPackageManager.setApplicationEnabledSetting( 77 mExcludedPackages.get(i), 78 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 79 PackageManager.DONT_KILL_APP); 80 } else { 81 mPackageManager.setApplicationEnabledSetting( 82 mExcludedPackages.get(i), 83 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 84 PackageManager.DONT_KILL_APP); 85 } 86 } 87 }); 88 } 89 addExcludedPackages(Intent intent)90 private void addExcludedPackages(Intent intent) { 91 final List<ResolveInfo> list = mPackageManager.queryIntentActivities(intent, 92 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA); 93 94 for (int i = 0; i < list.size(); i++) { 95 ResolveInfo info = list.get(i); 96 if (!info.activityInfo.packageName.equals(mTestActivity.getPackageName())) { 97 mExcludedPackages.add(info.activityInfo.packageName); 98 } 99 } 100 } 101 102 @Before setUp()103 public void setUp() throws Exception { 104 assumeFalse("Voice interaction framework currently does not support " 105 + "visible background users", new UserHelper().isVisibleBackgroundUser()); 106 107 super.setUp(); 108 // Exclude packages for voice intent 109 addExcludedPackages(mVoiceIntent); 110 // Exclude packages for web intent 111 addExcludedPackages(mWebIntent); 112 // Set packages state to be disabled. 113 setPackageState(false); 114 } 115 116 @After tearDown()117 public void tearDown() throws Exception { 118 // Enable the packages. 119 setPackageState(true); 120 mExcludedPackages.clear(); 121 super.tearDown(); 122 } 123 124 @Test testMediaKeys()125 public void testMediaKeys() { 126 testInputEvents(R.raw.google_gamepad_keyevent_media_tests); 127 } 128 129 @Test testVolumeKeys()130 public void testVolumeKeys() { 131 // {@link PhoneWindowManager} in interceptKeyBeforeDispatching, on TVs platform, 132 // volume keys never go to the foreground app. 133 // Skip the key test for TV platform. 134 assumeFalse("TV platform and devices handling key events outside window manager " 135 + "don't send volume keys to app, test should be skipped", shouldSkipVolumeTest()); 136 testInputEvents(R.raw.google_gamepad_keyevent_volume_tests); 137 } 138 139 /** 140 * Assistant keyevent is not sent to apps, verify InputAssistantActivity launched and visible. 141 */ 142 @Test testVoiceAssistantKey()143 public void testVoiceAssistantKey() throws Exception { 144 /* Inject assistant key from hid device */ 145 testInputEvents(R.raw.google_gamepad_assistkey); 146 147 WindowManagerStateHelper wmStateHelper = new WindowManagerStateHelper(); 148 149 /* InputAssistantActivity should be visible */ 150 final ComponentName inputAssistant = 151 new ComponentName(mTestActivity.getPackageName(), 152 InputAssistantActivity.class.getName()); 153 wmStateHelper.waitForValidState(inputAssistant); 154 wmStateHelper.assertActivityDisplayed(inputAssistant); 155 } 156 shouldSkipVolumeTest()157 private boolean shouldSkipVolumeTest() { 158 return mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) 159 || mContext.getResources().getBoolean(Resources.getSystem().getIdentifier( 160 "config_handleVolumeKeysInWindowManager", 161 "bool", "android")); 162 } 163 } 164