Skip to content

Commit

Permalink
Improve multithreaded error reporting
Browse files Browse the repository at this point in the history
Kill switch now properly integrated with Java and C, and some error
reporting/disconnect bugs fixed
  • Loading branch information
petabyt committed Jan 10, 2024
1 parent 33eb8ac commit 05364f4
Show file tree
Hide file tree
Showing 16 changed files with 132 additions and 91 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ app/.cxx
local.properties
*.aab
*.o
*.out
23 changes: 17 additions & 6 deletions app/src/main/java/dev/danielc/fujiapp/Backend.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.io.File;
import org.json.JSONObject;
import java.util.Arrays;
import android.content.Context;
import android.content.Intent;
import camlib.*;

public class Backend extends CamlibBackend {
Expand All @@ -25,12 +27,13 @@ public static void fujiConnectToCmd() throws Exception {

try {
cmdSocket.connectWiFi(Backend.FUJI_IP, Backend.FUJI_CMD_PORT);
cClearKillSwitch();
} catch (Exception e) {

if (BuildConfig.DEBUG) {
Backend.print("Trying emulator IP");
try {
cmdSocket.connectWiFi(Backend.FUJI_EMU_IP, Backend.FUJI_CMD_PORT);
cClearKillSwitch();
} catch (Exception e2) {
throw e2;
}
Expand Down Expand Up @@ -63,6 +66,13 @@ public static void fujiConnectEventAndVideo() throws Exception {
public static void reportError(int code, String reason) {
cReportError(code, reason);
}
public static void exitToMain(Context ctx) {
// Kill switch is operated by camlib, so checking socket kill switch will do for now
if (!Backend.cmdSocket.alive) return;

Intent intent = new Intent(ctx, MainActivity.class);
ctx.startActivity(intent);
}

// In order to give the backend access to the static methods, new objects must be made
private static boolean haveInited = false;
Expand All @@ -86,6 +96,9 @@ public static void clear() {
public static final int FUJI_VIDEO_PORT = 55742;
public static final int OPEN_TIMEOUT = 1000;

// IO kill switch is in C/camlib, so we must set it when a connection is established
public native static void cClearKillSwitch();

// Note: 'synchronized' means only one of these methods can be used at time -
// java's version of a mutex
public native synchronized static void cInit(Backend b, SimpleSocket c);
Expand Down Expand Up @@ -123,8 +136,6 @@ public static void clear() {
public native synchronized static int cRouteLogs(String filename);
public native synchronized static String cEndLogs();

//public native static boolean cIsUsingEmulator();

public native static int cFujiScriptsScreen(Context ctx);

public native static int cSetProgressBar(Object progressBar);
Expand Down Expand Up @@ -170,7 +181,6 @@ public static JSONObject fujiGetUncompressedObjectInfo(int handle) throws Except
}

// C/Java -> async UI logging
public static String logLocation = "main";
final static int MAX_LOG_LINES = 5;

public static void clearPrint() {
Expand All @@ -194,9 +204,10 @@ public static void print(String arg) {
}

public static void updateLog() {
if (logLocation == "main") {
if (MainActivity.instance != null) {
MainActivity.instance.setLogText(basicLog);
} else if (logLocation == "gallery") {
}
if (Gallery.instance != null) {
Gallery.instance.setLogText(basicLog);
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/dev/danielc/fujiapp/Bluetooth.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public Intent getIntent() throws Exception {
@SuppressLint("MissingPermission")
public BluetoothDevice getConnectedDevice() {
Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();
if (bondedDevices!=null) {
if (bondedDevices != null) {
for (BluetoothDevice device : bondedDevices) {
Backend.print("Currently connected to " + device.getName());
}
Expand Down
11 changes: 2 additions & 9 deletions app/src/main/java/dev/danielc/fujiapp/Gallery.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public void run() {
}

if (Backend.cIsUntestedMode()) {
showWarning("This camera is untested, support is under development.");
showWarning("Support for this camera is under development.");
}

Backend.print("Configuring versions and stuff..");
Expand Down Expand Up @@ -211,12 +211,7 @@ public void run() {
handler.post(new Runnable() {
@Override
public void run() {
// Do nothing if connection doesn't exist anymore
if (!Backend.cmdSocket.alive) return;

Intent intent = new Intent(Gallery.this, MainActivity.class);
startActivity(intent);
Backend.logLocation = "main";
Backend.exitToMain(Gallery.this);
Backend.reportError(Backend.PTP_IO_ERR, "Failed to ping camera");
}
});
Expand All @@ -232,15 +227,13 @@ public void run() {
@Override
public void onBackPressed() {
// TODO: Press again to terminate connection
//Backend.logLocation = "main";
//finish();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Backend.logLocation = "main";
Backend.reportError(Backend.PTP_OK, "Graceful disconnect");
finish();
return true;
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/dev/danielc/fujiapp/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public void run() {
try {
Backend.fujiConnectToCmd();
Backend.print("Connected to the camera");
Backend.logLocation = "gallery";
Intent intent = new Intent(MainActivity.this, Gallery.class);
startActivity(intent);
} catch (Exception e) {
Expand Down
43 changes: 22 additions & 21 deletions app/src/main/java/libui/LibUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ public static View form(String name) {
layout.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
layout.setPadding(5, 5, 5, 5);

TextView title = new TextView(ctx);
title.setPadding(5, 5, 5, 5);
Expand All @@ -164,10 +163,9 @@ public static void formAppend(View form, String name, View child) {
entry.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
entry.setPadding(5, 5, 5, 5);

TextView entryName = new TextView(ctx);
entryName.setPadding(40, 20, 20, 20);
entryName.setPadding(20, 10, 20, 10);
entryName.setText(name);
entryName.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
Expand Down Expand Up @@ -209,9 +207,11 @@ public static View label(String text) {
public static View tabLayout() {
LinearLayout layout = new LinearLayout(ctx);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
layout.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT,
1.0f
));

TabLayout tl = new TabLayout(ctx);
tl.setLayoutParams(new ViewGroup.LayoutParams(
Expand Down Expand Up @@ -288,9 +288,7 @@ public static void switchScreen(View view, String title) {
Boolean delay = true;

if (delay) {
try {
Thread.sleep(100);
} catch (Exception e) {}
userSleep();
}

ActionBar actionBar = ((AppCompatActivity)ctx).getSupportActionBar();
Expand Down Expand Up @@ -359,6 +357,13 @@ public static boolean handleOptions(MenuItem item, boolean allowBack) {
return ((Activity)ctx).onOptionsItemSelected(item);
}

// Being too fast doesn't feel right, brain need delay
public static void userSleep() {
try {
Thread.sleep(100);
} catch (Exception e) {}
}

public static class Popup {
PopupWindow popupWindow;
public void dismiss() {
Expand All @@ -371,7 +376,7 @@ public void setChild(View v) {
LinearLayout rel = new LinearLayout(ctx);

actionBar = ((AppCompatActivity)ctx).getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(title);

LinearLayout bar = new LinearLayout(ctx);
Expand All @@ -392,9 +397,7 @@ public void setChild(View v) {
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Thread.sleep(100);
} catch (Exception e) {}
userSleep();
dismiss();
}
});
Expand Down Expand Up @@ -440,19 +443,16 @@ public void onClick(View v) {
}

Popup(String title, int options) {
try {
Thread.sleep(100);
} catch (Exception e) {}

userSleep();
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity)ctx).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
this.title = title;

this.popupWindow = new PopupWindow(
(int)(width / 1.5),
(int)(height / 2.0)
(int)(width / 1.2),
(int)(height / 1.2)
);

this.popupWindow.setOutsideTouchable(false);
Expand Down Expand Up @@ -486,9 +486,10 @@ private static String getString(String name) {
return res.getString(res.getIdentifier(name, "string", ctx.getPackageName()));
}

private static int getView(String name) {
private static View getView(String name) {
Resources res = ctx.getResources();
return res.getIdentifier(name, "id", ctx.getPackageName());
int id = res.getIdentifier(name, "id", ctx.getPackageName());
return ((Activity)ctx).findViewById(id);
}

private static void toast(String text) {
Expand Down
File renamed without changes.
3 changes: 0 additions & 3 deletions test/main.c → desktop/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
int fuji_test_filesystem(struct PtpRuntime *r);
int fuji_test_setup(struct PtpRuntime *r);

void android_err() {}

void tester_log(char *fmt, ...) {
char buffer[512];
va_list args;
Expand All @@ -31,7 +29,6 @@ void tester_fail(char *fmt, ...) {
printf("FAIL: %s\n", buffer);
}


int main() {
int rc = 0;
char *ip_addr = "192.168.1.33";
Expand Down
18 changes: 8 additions & 10 deletions lib/fuji.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int fuji_wait_for_access(struct PtpRuntime *r) {
return 0;
} else {
if (fuji_known.num_objects == -1) {
android_err("Failed to get num_objects from first event\n");
ptp_verbose_log("Failed to get num_objects from first event\n");
return PTP_RUNTIME_ERR;
}
}
Expand All @@ -141,24 +141,24 @@ int fuji_config_init_mode(struct PtpRuntime *r) {
int rc = ptp_get_prop_value(r, PTP_PC_FUJI_ImageExploreVersion);
if (rc) return rc;
fuji_known.image_explore_version = ptp_parse_prop_value(r);
tester_log("ImageExploreVersion: 0x%X", fuji_known.image_explore_version);
ptp_verbose_log("ImageExploreVersion: 0x%X", fuji_known.image_explore_version);

rc = ptp_get_prop_value(r, PTP_PC_FUJI_RemoteImageExploreVersion);
if (rc) return rc;
fuji_known.remote_image_view_version = ptp_parse_prop_value(r);
tester_log("RemoteImageExploreVersion: 0x%X", fuji_known.remote_image_view_version);
ptp_verbose_log("RemoteImageExploreVersion: 0x%X", fuji_known.remote_image_view_version);

rc = ptp_get_prop_value(r, PTP_PC_FUJI_ImageGetVersion);
if (rc) return rc;
fuji_known.image_get_version = ptp_parse_prop_value(r);
tester_log("ImageGetVersion: 0x%X", fuji_known.image_get_version);
ptp_verbose_log("ImageGetVersion: 0x%X", fuji_known.image_get_version);

rc = ptp_get_prop_value(r, PTP_PC_FUJI_RemoteVersion);
if (rc) return rc;
fuji_known.remote_version = ptp_parse_prop_value(r);
tester_log("RemoteVersion: 0x%X", fuji_known.remote_version);
ptp_verbose_log("RemoteVersion: 0x%X", fuji_known.remote_version);

tester_log("CameraState is %d", fuji_known.camera_state);
ptp_verbose_log("CameraState is %d", fuji_known.camera_state);

// Determine preferred mode from state and version info
int mode = 0;
Expand All @@ -174,7 +174,7 @@ int fuji_config_init_mode(struct PtpRuntime *r) {
}
}

tester_log("Setting mode to %d", mode);
ptp_verbose_log("Setting mode to %d", mode);

rc = ptp_set_prop_value16(r, PTP_PC_FUJI_FunctionMode, mode);
if (rc) return rc;
Expand Down Expand Up @@ -303,13 +303,11 @@ int ptp_get_thumbnail_smart_cache(struct PtpRuntime *r, int handle, void **ptr,
};

// Shouldn't exceed 1mb
#if 1
int total = 0;
for (int i = 0; i < cache.length; i++) {
total += cache.entries[i].length;
}
android_err("Totaling %d bytes of cache\n", total);
#endif
ptp_verbose_log("Totaling %d bytes of cache\n", total);

// Search for cached thumb
for (int i = 0; i < cache.length; i++) {
Expand Down
10 changes: 9 additions & 1 deletion lib/fuji.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@

#include "models.h"

// (Not a part of camlib)
void ptp_report_error(struct PtpRuntime *r, char *reason, int code);

// Test suite stuff
int fuji_test_setup(struct PtpRuntime *r);
int fuji_test_filesystem(struct PtpRuntime *r);

// Send init packet, recieve response
int ptpip_fuji_init_req(struct PtpRuntime *r, char *device_name);

int fuji_config_version(struct PtpRuntime *r);
Expand All @@ -18,12 +24,14 @@ int fuji_remote_mode_end(struct PtpRuntime *r);

int fuji_wait_for_access(struct PtpRuntime *r);

// Recieves events once, and updates info struct with changes
int fuji_get_events(struct PtpRuntime *r);

// Enable/disable compression prop for downloading photos
int fuji_disable_compression(struct PtpRuntime *r);
int fuji_enable_compression(struct PtpRuntime *r);

// Holds vital info about the camera
// Holds runtime info about the camera
struct FujiDeviceKnowledge {
struct FujiCameraInfo *info;
int camera_state;
Expand Down
6 changes: 3 additions & 3 deletions lib/jni.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
JNI_FUNC(jint, cPtpFujiInit)(JNIEnv *env, jobject thiz) {
backend.env = env;

// Take this as an opportunity to reset all the structures for a new connection
reset_connection();

int rc = ptpip_fuji_init_req(&backend.r, "fudge");
if (rc) return rc;

Expand Down Expand Up @@ -244,15 +241,18 @@ JNI_FUNC(jboolean, cIsMultipleMode)(JNIEnv *env, jobject thiz) {
return fuji_known.camera_state == FUJI_MULTIPLE_TRANSFER;
}

#if 0
JNI_FUNC(jint, cTestStuff)(JNIEnv *env, jobject thiz) {
backend.env = env;
return 0;
}

// TODO: Idea: when activity changes, notify C so we don't run tester_log in gallery?
JNI_FUNC(void, cNotifyScreenStart)(JNIEnv *env, jobject thiz, jstring string) {
backend.env = env;
const char *name = (*env)->GetStringUTFChars(env, string, 0);
}
#endif

JNI_FUNC(jintArray, cGetObjectHandles)(JNIEnv *env, jobject thiz) {
backend.env = env;
Expand Down
Loading

0 comments on commit 05364f4

Please sign in to comment.