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 android.service.voice; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.annotation.TestApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.text.TextUtils; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * This class is used by the assistant application to know what went wrong during using the 32 * {@link HotwordDetector} and which action that the application should take. When an error occurs 33 * from Dsp hotword detection, software hotword detection and {@link HotwordDetectionService}, the 34 * system will send {@link HotwordDetectionServiceFailure} which contains the error code, error 35 * message and the suggested action to help the assistant application to take the next action. 36 * 37 * @hide 38 */ 39 @SystemApi 40 public final class HotwordDetectionServiceFailure implements Parcelable { 41 42 /** 43 * An error code which means an unknown error occurs. 44 */ 45 public static final int ERROR_CODE_UNKNOWN = 0; 46 47 /** 48 * Indicates that the system server binds hotword detection service failure. 49 */ 50 public static final int ERROR_CODE_BIND_FAILURE = 1; 51 52 /** 53 * Indicates that the hotword detection service is dead. 54 */ 55 public static final int ERROR_CODE_BINDING_DIED = 2; 56 57 /** 58 * Indicates to copy audio data failure for external source detection. 59 */ 60 public static final int ERROR_CODE_COPY_AUDIO_DATA_FAILURE = 3; 61 62 /** 63 * Indicates that the detection service doesn’t respond to the detection result before timeout. 64 */ 65 public static final int ERROR_CODE_DETECT_TIMEOUT = 4; 66 67 /** 68 * Indicates that the security exception occurs in #onDetected method. 69 */ 70 public static final int ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION = 5; 71 72 /** 73 * Indicates to copy the audio stream failure in #onDetected method. 74 */ 75 public static final int ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE = 6; 76 77 /** 78 * Indicates that the remote exception occurs when calling callback method. 79 */ 80 public static final int ERROR_CODE_REMOTE_EXCEPTION = 7; 81 82 /** 83 * @hide 84 */ 85 @IntDef(prefix = {"ERROR_CODE_"}, value = { 86 ERROR_CODE_UNKNOWN, 87 ERROR_CODE_BIND_FAILURE, 88 ERROR_CODE_BINDING_DIED, 89 ERROR_CODE_COPY_AUDIO_DATA_FAILURE, 90 ERROR_CODE_DETECT_TIMEOUT, 91 ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION, 92 ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE, 93 ERROR_CODE_REMOTE_EXCEPTION 94 }) 95 @Retention(RetentionPolicy.SOURCE) 96 public @interface HotwordDetectionServiceErrorCode {} 97 98 private int mErrorCode = ERROR_CODE_UNKNOWN; 99 private String mErrorMessage = "Unknown"; 100 101 /** 102 * @hide 103 */ 104 @TestApi HotwordDetectionServiceFailure(int errorCode, @NonNull String errorMessage)105 public HotwordDetectionServiceFailure(int errorCode, @NonNull String errorMessage) { 106 if (TextUtils.isEmpty(errorMessage)) { 107 throw new IllegalArgumentException("errorMessage is empty or null."); 108 } 109 mErrorCode = errorCode; 110 mErrorMessage = errorMessage; 111 } 112 113 /** 114 * Returns the error code. 115 */ 116 @HotwordDetectionServiceErrorCode getErrorCode()117 public int getErrorCode() { 118 return mErrorCode; 119 } 120 121 /** 122 * Returns the error message. 123 */ 124 @NonNull getErrorMessage()125 public String getErrorMessage() { 126 return mErrorMessage; 127 } 128 129 /** 130 * Returns the suggested action. 131 */ 132 @FailureSuggestedAction.FailureSuggestedActionDef getSuggestedAction()133 public int getSuggestedAction() { 134 switch (mErrorCode) { 135 case ERROR_CODE_BIND_FAILURE: 136 case ERROR_CODE_BINDING_DIED: 137 case ERROR_CODE_REMOTE_EXCEPTION: 138 return FailureSuggestedAction.RECREATE_DETECTOR; 139 case ERROR_CODE_DETECT_TIMEOUT: 140 case ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION: 141 case ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE: 142 return FailureSuggestedAction.RESTART_RECOGNITION; 143 default: 144 return FailureSuggestedAction.NONE; 145 } 146 } 147 148 @Override describeContents()149 public int describeContents() { 150 return 0; 151 } 152 153 @Override writeToParcel(@onNull Parcel dest, int flags)154 public void writeToParcel(@NonNull Parcel dest, int flags) { 155 dest.writeInt(mErrorCode); 156 dest.writeString8(mErrorMessage); 157 } 158 159 @Override toString()160 public String toString() { 161 return "HotwordDetectionServiceFailure { errorCode = " + mErrorCode + ", errorMessage = " 162 + mErrorMessage + " }"; 163 } 164 165 public static final @NonNull Parcelable.Creator<HotwordDetectionServiceFailure> CREATOR = 166 new Parcelable.Creator<HotwordDetectionServiceFailure>() { 167 @Override 168 public HotwordDetectionServiceFailure[] newArray(int size) { 169 return new HotwordDetectionServiceFailure[size]; 170 } 171 172 @Override 173 public HotwordDetectionServiceFailure createFromParcel(@NonNull Parcel in) { 174 return new HotwordDetectionServiceFailure(in.readInt(), in.readString8()); 175 } 176 }; 177 } 178