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 android.voiceinteraction.service; 18 19 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 20 21 import android.content.ComponentName; 22 import android.content.Intent; 23 import android.net.Uri; 24 import android.os.Bundle; 25 import android.service.voice.AlwaysOnHotwordDetector; 26 import android.service.voice.VoiceInteractionService; 27 import android.util.Log; 28 import android.voiceinteraction.common.Utils; 29 30 import java.util.Collections; 31 import java.util.Locale; 32 import java.util.Set; 33 34 public class MainInteractionService extends VoiceInteractionService { 35 static final String TAG = "MainInteractionService"; 36 private Intent mIntent; 37 private boolean mReady = false; 38 39 @Override onReady()40 public void onReady() { 41 super.onReady(); 42 mReady = true; 43 } 44 45 @Override onStartCommand(Intent intent, int flags, int startId)46 public int onStartCommand(Intent intent, int flags, int startId) { 47 Log.i(TAG, "onStartCommand received"); 48 mIntent = intent; 49 50 if (mIntent == null || !mReady) { 51 Log.wtf(TAG, "Can't start because either intent is null or onReady() " 52 + "is not called yet. mIntent = " + mIntent + ", mReady = " + mReady); 53 return START_NOT_STICKY; 54 } 55 56 final int testEvent = mIntent.getIntExtra(Utils.KEY_TEST_EVENT, -1); 57 if (testEvent == Utils.VIS_NORMAL_TEST) { 58 maybeStart(); 59 } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) { 60 runWithShellPermissionIdentity(() -> { 61 callCreateAlwaysOnHotwordDetector(); 62 }); 63 } 64 return START_NOT_STICKY; 65 } 66 maybeStart()67 private void maybeStart() { 68 Bundle args = mIntent.getExtras(); 69 final String className = (args != null) 70 ? args.getString(Utils.VOICE_INTERACTION_KEY_CLASS) : null; 71 if (className == null) { 72 Log.i(TAG, "Yay! about to start session with TestApp"); 73 if (isActiveService(this, new ComponentName(this, getClass()))) { 74 // Call to verify onGetSupportedVoiceActions is available. 75 onGetSupportedVoiceActions(Collections.emptySet()); 76 args = new Bundle(); 77 Intent intent = new Intent() 78 .setAction(Intent.ACTION_VIEW) 79 .addCategory(Intent.CATEGORY_VOICE) 80 .addCategory(Intent.CATEGORY_BROWSABLE) 81 .setData(Uri.parse("https://android.voiceinteraction.testapp" 82 + "/TestApp")); 83 args.putParcelable("intent", intent); 84 Log.v(TAG, "showSession(): " + args); 85 showSession(args, 0); 86 } else { 87 Log.wtf(TAG, "**** Not starting MainInteractionService because" + 88 " it is not set as the current voice interaction service"); 89 } 90 } else { 91 showSession(args, 0); 92 } 93 } 94 95 @Override onGetSupportedVoiceActions(Set<String> voiceActions)96 public Set<String> onGetSupportedVoiceActions(Set<String> voiceActions) { 97 Log.v(TAG, "onGetSupportedVoiceActions " + voiceActions); 98 return super.onGetSupportedVoiceActions(voiceActions); 99 } 100 callCreateAlwaysOnHotwordDetector()101 private void callCreateAlwaysOnHotwordDetector() { 102 Log.i(TAG, "callCreateAlwaysOnHotwordDetector()"); 103 try { 104 createAlwaysOnHotwordDetector(/* keyphrase */ "Hello Google", 105 Locale.forLanguageTag("en-US"), /* options */ null, /* sharedMemory */ null, 106 new AlwaysOnHotwordDetector.Callback() { 107 @Override 108 public void onAvailabilityChanged(int status) { 109 Log.i(TAG, "onAvailabilityChanged(" + status + ")"); 110 } 111 112 @Override 113 public void onDetected(AlwaysOnHotwordDetector.EventPayload eventPayload) { 114 Log.i(TAG, "onDetected"); 115 } 116 117 @Override 118 public void onError() { 119 Log.i(TAG, "onError"); 120 } 121 122 @Override 123 public void onRecognitionPaused() { 124 Log.i(TAG, "onRecognitionPaused"); 125 } 126 127 @Override 128 public void onRecognitionResumed() { 129 Log.i(TAG, "onRecognitionResumed"); 130 } 131 }); 132 } catch (IllegalStateException e) { 133 Log.w(TAG, "callCreateAlwaysOnHotwordDetector() exception: " + e); 134 broadcastIntentWithResult( 135 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT, 136 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_ILLEGAL_STATE_EXCEPTION); 137 } 138 } 139 broadcastIntentWithResult(String intentName, int result)140 private void broadcastIntentWithResult(String intentName, int result) { 141 Intent intent = new Intent(intentName) 142 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY) 143 .putExtra(Utils.KEY_TEST_RESULT, result); 144 Log.d(TAG, "broadcast intent = " + intent + ", result = " + result); 145 sendBroadcast(intent); 146 } 147 } 148