Steps toward following all the inconvenient, changing android rules:

* Set android:debuggable=false.
 * Call native code through JNI only.  Having a native executable on disk and exec-ing it no longer seems possible.
 * Do all the Tilde Friends things in one process, without a proper sandbox, until I can wire up a restricted service worker process.
 * Jam Android App Bundle (.aab) building into the makefile.
 * Yuck.
This commit is contained in:
Cory McWilliams 2024-06-30 13:32:17 -04:00
parent 568729ecd6
commit 71268636df
5 changed files with 166 additions and 27 deletions

View File

@ -3,12 +3,13 @@
MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-builtin-rules
VERSION_CODE := 21 VERSION_CODE := 22
VERSION_NUMBER := 0.0.21-wip VERSION_NUMBER := 0.0.21-wip
VERSION_NAME := Psst. Look behind you. VERSION_NAME := Psst. Look behind you.
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3460000.zip SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3460000.zip
LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
BUNDLETOOL_URL := https://github.com/google/bundletool/releases/download/1.17.0/bundletool-all-1.17.0.jar
PROJECT = tildefriends PROJECT = tildefriends
BUILD_DIR ?= out BUILD_DIR ?= out
@ -16,6 +17,7 @@ UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m) UNAME_M := $(shell uname -m)
ANDROID_SDK ?= ~/Android/Sdk ANDROID_SDK ?= ~/Android/Sdk
BUNDLETOOL = out/bundletool.jar
HAVE_WIN := 0 HAVE_WIN := 0
@ -150,9 +152,10 @@ ANDROID_RELEASE_TARGETS := $(filter-out $(DEBUG_TARGETS),$(ANDROID_TARGETS))
NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS)) NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS))
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS)) NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS)) NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
DEADSTRIP_TARGETS := $(filter-out $(ANDROID_TARGETS),$(NONMACOS_TARGETS))
$(NONANDROID_TARGETS): CFLAGS += -fno-omit-frame-pointer $(NONANDROID_TARGETS): CFLAGS += -fno-omit-frame-pointer
$(filter-out $(ANDROID_TARGETS) $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic $(filter-out $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic
$(ANDROID_TARGETS): CFLAGS += \ $(ANDROID_TARGETS): CFLAGS += \
--sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot \ --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-fPIC \ -fPIC \
@ -205,7 +208,7 @@ $(ANDROID_X86_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86/usr/local/lib
$(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/include $(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/include
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib $(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type $(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
$(NONMACOS_TARGETS): LDFLAGS += -Wl,--gc-sections $(DEADSTRIP_TARGETS): LDFLAGS += -Wl,--gc-sections
$(IOS_TARGETS): CFLAGS += -mios-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include $(IOS_TARGETS): CFLAGS += -mios-version-min=9.0 -Ideps/openssl/ios/ios64-xcrun/usr/local/include
$(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib $(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include $(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
@ -698,7 +701,7 @@ $(CLASS_FILES) &: $(JAVA_FILES)
out/apk/classes.dex: $(CLASS_FILES) out/apk/classes.dex: $(CLASS_FILES)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@echo "[d8] $@" @echo "[d8] $@"
@$(ANDROID_BUILD_TOOLS)/d8 --$(BUILD_TYPE) --lib $(ANDROID_PLATFORM)/android.jar --output $(dir $@) out/classes/com/unprompted/tildefriends/*.class @$(ANDROID_BUILD_TOOLS)/d8 --lib $(ANDROID_PLATFORM)/android.jar --output $(dir $@) out/classes/com/unprompted/tildefriends/*.class
PACKAGE_DIRS := \ PACKAGE_DIRS := \
apps/ \ apps/ \
@ -719,13 +722,51 @@ out/apk/TildeFriends-arm-release.unsigned.apk: out/apk/classes.dex out/androidre
out/apk/TildeFriends-x86-debug.unsigned.apk: out/apk/classes.dex out/androiddebug-x86_64/tildefriends out/androiddebug-x86/tildefriends $(RAW_FILES) out/apk/res.apk out/apk/TildeFriends-x86-debug.unsigned.apk: out/apk/classes.dex out/androiddebug-x86_64/tildefriends out/androiddebug-x86/tildefriends $(RAW_FILES) out/apk/res.apk
out/apk/TildeFriends-x86-release.unsigned.apk: out/apk/classes.dex out/androidrelease-x86_64/tildefriends out/androidrelease-x86/tildefriends $(RAW_FILES) out/apk/res.apk out/apk/TildeFriends-x86-release.unsigned.apk: out/apk/classes.dex out/androidrelease-x86_64/tildefriends out/androidrelease-x86/tildefriends $(RAW_FILES) out/apk/res.apk
$(BUNDLETOOL):
@echo [curl] $(BUNDLETOOL_URL) TO $@
@curl -q -L --create-dirs -o $@ $(BUNDLETOOL_URL)
out/TildeFriends.aab: out/apk/classes.dex $(filter-out %debug%, $(ANDROID_TARGETS)) $(RAW_FILES) out/apk/res.apk src/android/AndroidManifest.xml $(BUNDLETOOL)
@rm -rf out/aab/staging/
@mkdir -p out/aab/staging
@$(ANDROID_BUILD_TOOLS)/aapt2 link --proto-format -o out/aab/temporary.apk -I $(ANDROID_PLATFORM)/android.jar --manifest src/android/AndroidManifest.xml -R out/res/layout_activity_main.xml.flat -R out/res/drawable_icon.xml.flat --auto-add-overlay
@unzip out/aab/temporary.apk -d out/aab/staging/
@mkdir -p out/aab/staging/root/deps
@mkdir -p out/aab/staging/classes
@mkdir -p out/aab/staging/dex
@mkdir -p out/aab/staging/manifest
@mv out/aab/staging/AndroidManifest.xml out/aab/staging/manifest/AndroidManifest.xml
@cp out/apk/classes.dex out/aab/staging/dex/
@rm -fv out/base.zip
@cp -r out/apk-arm-release/lib/ out/aab/staging/
@cp -r out/apk-x86-release/lib/ out/aab/staging/
@cp -r apps/ out/aab/staging/root/
@rm -rf out/aab/staging/root/apps/welcome*
@cp -r core/ out/aab/staging/root/
@cp -r deps/prettier/ out/aab/staging/root/deps/
@cp -r deps/lit/ out/aab/staging/root/deps/
@cp -r deps/codemirror/ out/aab/staging/root/deps/
@cd out/aab/staging/; zip -r ../base.zip *; cd ../../../
@java -jar $(BUNDLETOOL) build-bundle --overwrite --config=src/android/BundleConfig.json --modules=out/aab/base.zip --output=$@
@jarsigner -keystore .keys/android.jks $@ androidKey -storepass android
aab: out/TildeFriends.aab
.PHONY: aab
out/TildeFriends.apks: out/TildeFriends.aab $(BUNDLETOOL)
@java -jar $(BUNDLETOOL) build-apks --bundle out/TildeFriends.aab --overwrite --output $@ --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android
aabgo: out/TildeFriends.apks $(BUNDLETOOL)
@java -jar $(BUNDLETOOL) install-apks --apks out/TildeFriends.apks
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
out/apk/TildeFriends-arm-%.unsigned.apk: out/apk/TildeFriends-arm-%.unsigned.apk:
@mkdir -p $(dir $@) out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/ @mkdir -p $(dir $@) out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/
@echo "[aapt] $@" @echo "[aapt] $@"
@cp out/android$(BUILD_TYPE)/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/tildefriends.so @cp out/android$(BUILD_TYPE)/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
@cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so @cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/tildefriends.so @$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/libtildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so @$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
@cp out/apk/res.apk $@.zip @cp out/apk/res.apk $@.zip
@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/ @cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/
@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ @cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
@ -735,10 +776,10 @@ out/apk/TildeFriends-arm-%.unsigned.apk:
out/apk/TildeFriends-x86-%.unsigned.apk: out/apk/TildeFriends-x86-%.unsigned.apk:
@mkdir -p $(dir $@) out/apk-x86-$(BUILD_TYPE)/lib/x86_64/ out/apk-x86-$(BUILD_TYPE)/lib/x86/ @mkdir -p $(dir $@) out/apk-x86-$(BUILD_TYPE)/lib/x86_64/ out/apk-x86-$(BUILD_TYPE)/lib/x86/
@echo "[aapt] $@" @echo "[aapt] $@"
@cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86_64/tildefriends.so @cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
@cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so @cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86/libtildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86_64/tildefriends.so @$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so @$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86/libtildefriends.so
@cp out/apk/res.apk $@.zip @cp out/apk/res.apk $@.zip
@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/ @cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/
@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ @cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
@ -757,6 +798,11 @@ out/%.zopfli.apk: out/%.apk
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk
.PHONY: release-apk .PHONY: release-apk
apkgo: out/TildeFriends-arm-debug.apk
@adb install -r $<
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
.PHONY: apkgo
releaseapkgo: out/TildeFriends-arm-release.apk releaseapkgo: out/TildeFriends-arm-release.apk
@adb install -r $< @adb install -r $<
@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity @adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity

View File

@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unprompted.tildefriends" package="com.unprompted.tildefriends"
android:versionCode="21" android:versionCode="22"
android:versionName="0.0.21-wip"> android:versionName="0.0.21-wip">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="34"/> <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="34"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:label="Tilde Friends" android:label="Tilde Friends"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
android:debuggable="true" android:debuggable="false">
android:extractNativeLibs="true">
<meta-data android:name="android.max_aspect" android:value="2.1"/> <meta-data android:name="android.max_aspect" android:value="2.1"/>
<activity <activity
android:name=".TildeFriendsActivity" android:name=".TildeFriendsActivity"

View File

@ -0,0 +1,5 @@
{
"optimizations" : {
"uncompress_native_libraries" : {}
}
}

View File

@ -53,13 +53,23 @@ import java.util.concurrent.TimeUnit;
public class TildeFriendsActivity extends Activity { public class TildeFriendsActivity extends Activity {
TildeFriendsWebView web_view; TildeFriendsWebView web_view;
String base_url; String base_url;
String port_file_path;
Process process; Process process;
Thread thread; Thread thread;
Thread server_thread;
private ValueCallback<Uri[]> upload_message; private ValueCallback<Uri[]> upload_message;
private final static int FILECHOOSER_RESULT = 1; private final static int FILECHOOSER_RESULT = 1;
private float touch_down_y; private float touch_down_y;
static {
Log.w("tildefriends", "Calling system.loadLibrary().");
System.loadLibrary("tildefriends");
Log.w("tildefriends", "system.loadLibrary() completed.");
}
static native int tf_server_main(String files_dir, String apk_path, String out_port_file_path);
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
@ -76,7 +86,7 @@ public class TildeFriendsActivity extends Activity {
Log.w("tildefriends", String.format("getPackageResourcePath() is %s", getPackageResourcePath().toString())); Log.w("tildefriends", String.format("getPackageResourcePath() is %s", getPackageResourcePath().toString()));
Log.w("tildefriends", String.format("nativeLibraryDir is %s", getApplicationInfo().nativeLibraryDir)); Log.w("tildefriends", String.format("nativeLibraryDir is %s", getApplicationInfo().nativeLibraryDir));
String port_file_path = getFilesDir().toString() + "/port.txt"; port_file_path = getFilesDir().toString() + "/port.txt";
new File(port_file_path).delete(); new File(port_file_path).delete();
base_url = "http://127.0.0.1:12345/"; base_url = "http://127.0.0.1:12345/";
@ -134,17 +144,15 @@ public class TildeFriendsActivity extends Activity {
thread.start(); thread.start();
set_status("Starting server..."); set_status("Starting server...");
String exe = getApplicationInfo().nativeLibraryDir + "/tildefriends.so"; server_thread = new Thread(new Runnable() {
ProcessBuilder builder = new ProcessBuilder(exe, "run", "-z", getPackageResourcePath().toString(), "-a", "out_http_port_file=" + port_file_path, "-p", "0"); @Override
Log.w("tildefriends", "files = " + getFilesDir().toString()); public void run() {
Log.w("tildefriends", "exe = " + exe); Log.w("tildefriends", "Calling tf_server_main.");
builder.directory(getFilesDir()); int result = tf_server_main(getFilesDir().toString(), getPackageResourcePath().toString(), port_file_path);
builder.inheritIO(); Log.w("tildefriends", "tf_server_main returned " + result + ".");
try { }
process = builder.start(); });
} catch (java.io.IOException e) { server_thread.start();
Log.w("tildefriends", "IOException starting process: " + e.toString());
}
web_view.getSettings().setJavaScriptEnabled(true); web_view.getSettings().setJavaScriptEnabled(true);
web_view.getSettings().setDatabaseEnabled(true); web_view.getSettings().setDatabaseEnabled(true);

View File

@ -34,6 +34,10 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#if defined(__ANDROID__)
#include "jni.h"
#endif
#if !defined(_countof) #if !defined(_countof)
#define _countof(a) ((int)(sizeof((a)) / sizeof(*(a)))) #define _countof(a) ((int)(sizeof((a)) / sizeof(*(a))))
#endif #endif
@ -726,6 +730,83 @@ static void _startup(int argc, char* argv[])
} }
#if defined(__ANDROID__) #if defined(__ANDROID__)
static jint _tf_server_main(JNIEnv* env, jobject this_object, jstring files_dir, jstring apk_path, jstring out_port_file_path)
{
tf_printf("This is tf_server_main main.\n");
_startup(0, (char*[]) { NULL });
tf_printf("That was startup.\n");
const char* files = (*env)->GetStringUTFChars(env, files_dir, NULL);
const char* apk = (*env)->GetStringUTFChars(env, apk_path, NULL);
const char* out_port_file = (*env)->GetStringUTFChars(env, out_port_file_path, NULL);
tf_printf("FILES = %s\n", files);
tf_printf("APK = %s\n", apk);
tf_printf("OUT_PORT = %s\n", out_port_file);
int result = uv_chdir(files);
if (result)
{
tf_printf("uv_chdir: %s\n", uv_strerror(result));
}
size_t port_file_arg_length = strlen(out_port_file) + strlen("out_http_port_file=") + 1;
char* port_file_arg = alloca(port_file_arg_length);
snprintf(port_file_arg, port_file_arg_length, "out_http_port_file=%s", out_port_file);
const char* args[] =
{
"-z",
apk,
"-a",
port_file_arg,
"-p",
"0",
"-o", /* HACK! FIXME! */
};
result = _tf_command_run(apk, _countof(args), (char**)args);
(*env)->ReleaseStringUTFChars(env, files_dir, files);
(*env)->ReleaseStringUTFChars(env, apk_path, apk);
(*env)->ReleaseStringUTFChars(env, out_port_file_path, out_port_file);
tf_printf("tf_server_main finished with %d.", result);
return result;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
tf_printf("JNI_Onload called.\n");
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
{
tf_printf("Failed to get JNI environment.\n");
return JNI_ERR;
}
tf_printf("Finding class.\n");
jclass c = (*env)->FindClass(env, "com/unprompted/tildefriends/TildeFriendsActivity");
if (!c)
{
tf_printf("Failed to find TildeFriendsActivity class.\n");
return JNI_ERR;
}
tf_printf("Registering method.\n");
static const JNINativeMethod methods[] = {
{ "tf_server_main", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", _tf_server_main },
};
int result = (*env)->RegisterNatives(env, c, methods, (int)_countof(methods));
if (result != JNI_OK)
{
return result;
}
tf_printf("Done.\n");
return JNI_VERSION_1_6;
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
_startup(argc, argv); _startup(argc, argv);