@@ -27,8 +27,18 @@ public class MobileHarnessException extends Exception implements ErrorIdProvider
2727
2828 private final ErrorId errorId ;
2929
30+ /**
31+ * An error message that is safe to display to external users or in environments with PII
32+ * restrictions.
33+ *
34+ * <p><b>WARNING:</b> This message MUST NOT contain any Personally Identifiable Information (PII),
35+ * user data, or Google-internal sensitive information, code names, or internal system details.
36+ * Treat this message as if it will be publicly visible.
37+ */
38+ @ Nullable private final String externalErrorMessage ;
39+
3040 public MobileHarnessException (ErrorId errorId , String message ) {
31- this (errorId , message , /* cause= */ null );
41+ this (errorId , message , /* cause= */ ( Throwable ) null );
3242 }
3343
3444 public MobileHarnessException (ErrorId errorId , String message , @ Nullable Throwable cause ) {
@@ -37,7 +47,39 @@ public MobileHarnessException(ErrorId errorId, String message, @Nullable Throwab
3747 message ,
3848 cause ,
3949 !message .endsWith (getMessageSuffix (errorId )),
40- /* clearStackTrace= */ false );
50+ /* clearStackTrace= */ false ,
51+ /* externalErrorMessage= */ null );
52+ }
53+
54+ /**
55+ * Constructs a new MobileHarnessException.
56+ *
57+ * @param externalErrorMessage An error message safe for external display. MUST NOT contain PII or
58+ * Google-sensitive information. See warning on the {@link #externalErrorMessage} field.
59+ */
60+ private MobileHarnessException (
61+ ErrorId errorId , String message , @ Nullable String externalErrorMessage ) {
62+ this (errorId , message , /* cause= */ null , externalErrorMessage );
63+ }
64+
65+ /**
66+ * Constructs a new MobileHarnessException.
67+ *
68+ * @param externalErrorMessage An error message safe for external display. MUST NOT contain PII or
69+ * Google-sensitive information. See warning on the {@link #externalErrorMessage} field.
70+ */
71+ private MobileHarnessException (
72+ ErrorId errorId ,
73+ String message ,
74+ @ Nullable Throwable cause ,
75+ @ Nullable String externalErrorMessage ) {
76+ this (
77+ errorId ,
78+ message ,
79+ cause ,
80+ !message .endsWith (getMessageSuffix (errorId )),
81+ /* clearStackTrace= */ false ,
82+ externalErrorMessage );
4183 }
4284
4385 /** Do NOT make it public. */
@@ -46,19 +88,57 @@ public MobileHarnessException(ErrorId errorId, String message, @Nullable Throwab
4688 String message ,
4789 @ Nullable Throwable cause ,
4890 boolean addErrorIdToMessage ,
49- boolean clearStackTrace ) {
91+ boolean clearStackTrace ,
92+ @ Nullable String externalErrorMessage ) {
5093 super (addErrorIdToMessage ? message + getMessageSuffix (errorId ) : message , cause );
5194 this .errorId = errorId ;
95+ this .externalErrorMessage = externalErrorMessage ;
5296 if (clearStackTrace ) {
5397 setStackTrace (EMPTY_STACK_TRACE );
5498 }
5599 }
56100
101+ /**
102+ * Creates a new MobileHarnessException with an error message safe for external display.
103+ *
104+ * <p><b>WARNING:</b> The {@code externalErrorMessage} MUST NOT contain PII or Google-sensitive
105+ * information. See warning on the {@link #externalErrorMessage} field.
106+ */
107+ public static MobileHarnessException createWithExternalMessage (
108+ ErrorId errorId , String message , @ Nullable String externalErrorMessage ) {
109+ return new MobileHarnessException (errorId , message , externalErrorMessage );
110+ }
111+
112+ /**
113+ * Creates a new MobileHarnessException with an error message safe for external display.
114+ *
115+ * <p><b>WARNING:</b> The {@code externalErrorMessage} MUST NOT contain PII or Google-sensitive
116+ * information. See warning on the {@link #externalErrorMessage} field.
117+ */
118+ public static MobileHarnessException createWithExternalMessage (
119+ ErrorId errorId ,
120+ String message ,
121+ @ Nullable Throwable cause ,
122+ @ Nullable String externalErrorMessage ) {
123+ return new MobileHarnessException (errorId , message , cause , externalErrorMessage );
124+ }
125+
57126 @ Override
58127 public ErrorId getErrorId () {
59128 return errorId ;
60129 }
61130
131+ /**
132+ * Returns the error message that is safe to display to external users.
133+ *
134+ * <p><b>WARNING:</b> Ensure that the creation of this message adheres to the restrictions
135+ * outlined on the {@link #externalErrorMessage} field.
136+ */
137+ @ Nullable
138+ public String getExternalErrorMessage () {
139+ return externalErrorMessage ;
140+ }
141+
62142 @ Override
63143 public String toString () {
64144 String classSimpleName = getClass ().getSimpleName ();
0 commit comments