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