Skip to content

Commit 904c667

Browse files
authored
Android: add @DoNotStrip and consumer ProGuard rules for JNI classes (#19169)
Add @DoNotStrip to ExecutorchRuntimeException constructor, factory method, and subclass to prevent R8 from stripping them in internal Meta app builds where these are only called from native code. Add consumer-proguard-rules.pro to the AAR for external apps that don't have app-level @DoNotStrip handling. The rules protect all JNI-called classes, native methods, HybridData fields, and callback interfaces from R8 stripping. This commit was authored with the help of Claude.
1 parent 77e63ee commit 904c667

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

extension/android/executorch_android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ android {
3333
minSdk = 23
3434

3535
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
36+
consumerProguardFiles 'consumer-proguard-rules.pro'
3637
}
3738

3839
compileOptions {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# ExecuTorch Android AAR — Consumer ProGuard/R8 Rules
2+
#
3+
# These rules are automatically applied to any app that depends on the
4+
# ExecuTorch AAR. They prevent R8/ProGuard from stripping classes and
5+
# methods that are called from native (JNI) code.
6+
7+
# Keep ExecuTorch classes and members annotated with @DoNotStrip.
8+
# Scoped to org.pytorch.executorch to avoid affecting unrelated libraries.
9+
-keep @com.facebook.jni.annotations.DoNotStrip class org.pytorch.executorch.** { *; }
10+
-keepclassmembers class org.pytorch.executorch.** {
11+
@com.facebook.jni.annotations.DoNotStrip *;
12+
}
13+
14+
# Keep all native methods across ExecuTorch packages.
15+
# Use -keepclasseswithmembers (not -keepclasseswithmembernames) to prevent
16+
# both shrinking and obfuscation of JNI entry points.
17+
-keepclasseswithmembers class org.pytorch.executorch.** {
18+
native <methods>;
19+
}
20+
21+
# Keep HybridData fields (accessed by fbjni via reflection).
22+
-keepclassmembers class org.pytorch.executorch.** {
23+
com.facebook.jni.HybridData *;
24+
}
25+
26+
# Keep ExecutorchRuntimeException and its factory/subclasses.
27+
# These are instantiated from JNI via jni_helper.cpp.
28+
-keep class org.pytorch.executorch.ExecutorchRuntimeException { *; }
29+
-keep class org.pytorch.executorch.ExecutorchRuntimeException$* { *; }
30+
31+
# Keep EValue (fields and type codes accessed from native code).
32+
-keep class org.pytorch.executorch.EValue { *; }
33+
34+
# Keep Tensor and its inner classes. The Tensor class has methods and fields
35+
# accessed from JNI (dtypeJniCode, shape, getRawDataBuffer, nativeNewTensor).
36+
-keep class org.pytorch.executorch.Tensor { *; }
37+
-keep class org.pytorch.executorch.Tensor$* { *; }
38+
39+
# Keep LlmCallback interface methods (invoked from native code).
40+
-keep interface org.pytorch.executorch.extension.llm.LlmCallback { *; }
41+
42+
# Keep AsrCallback interface methods (invoked from native code).
43+
-keep interface org.pytorch.executorch.extension.asr.AsrCallback { *; }

extension/android/executorch_android/src/main/java/org/pytorch/executorch/ExecutorchRuntimeException.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.pytorch.executorch;
1010

11+
import com.facebook.jni.annotations.DoNotStrip;
1112
import java.util.Collections;
1213
import java.util.HashMap;
1314
import java.util.Map;
@@ -156,6 +157,7 @@ static String getDetailedErrorLogs() {
156157

157158
private final int errorCode;
158159

160+
@DoNotStrip
159161
public ExecutorchRuntimeException(int errorCode, String details) {
160162
super(ErrorHelper.formatMessage(errorCode, details));
161163
this.errorCode = errorCode;
@@ -171,14 +173,15 @@ public String getDetailedError() {
171173
return ErrorHelper.getDetailedErrorLogs();
172174
}
173175

174-
// Idiomatic Java exception for invalid arguments - extends ExecutorchRuntimeException
176+
@DoNotStrip
175177
public static class ExecutorchInvalidArgumentException extends ExecutorchRuntimeException {
178+
@DoNotStrip
176179
public ExecutorchInvalidArgumentException(String details) {
177180
super(INVALID_ARGUMENT, details);
178181
}
179182
}
180183

181-
// Factory method to create an exception of the appropriate subclass.
184+
@DoNotStrip
182185
public static RuntimeException makeExecutorchException(int errorCode, String details) {
183186
switch (errorCode) {
184187
case INVALID_ARGUMENT:

0 commit comments

Comments
 (0)