Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2025-05-14 - [Visual Feedback for Native Operations]
**Learning:** In debug/sample apps performing native operations (like hooking), silent execution leads to user uncertainty. Immediate visual feedback via Toasts and button state changes significantly improves the developer experience by confirming action success.
**Action:** For buttons triggering library loading or native states, disable the button and update its text (e.g., 'lib... loaded') immediately upon success to provide clear state feedback and prevent redundant interactions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.bytedance.shadowhook.ShadowHook;
import com.bytedance.shadowhook.systest.SysTest;
Expand All @@ -50,41 +52,55 @@ protected void onCreate(Bundle savedInstanceState) {

public void onUnitTestHookSymAddrClick(View view) {
NativeHandler.nativeHookSymAddr(Build.VERSION.SDK_INT);
Toast.makeText(this, R.string.toast_hook_sym_addr, Toast.LENGTH_SHORT).show();
}

public void onUnitTestHookSymNameClick(View view) {
NativeHandler.nativeHookSymName(Build.VERSION.SDK_INT);
Toast.makeText(this, R.string.toast_hook_sym_name, Toast.LENGTH_SHORT).show();
}

public void onUnitTestUnhookClick(View view) {
NativeHandler.nativeUnhook();
Toast.makeText(this, R.string.toast_unhooked, Toast.LENGTH_SHORT).show();
}

public void onUnitTestLoadClick(View view) {
if(!hookee2Loaded) {
hookee2Loaded = true;
System.loadLibrary("hookee2");
if (view instanceof Button) {
Button button = (Button) view;
button.setEnabled(false);
button.setText(R.string.btn_lib_loaded);
}
Toast.makeText(this, R.string.toast_lib_loaded, Toast.LENGTH_SHORT).show();
}
}

public void onUnitTestRunClick(View view) {
NativeHandler.nativeRun(hookee2Loaded);
Toast.makeText(this, R.string.toast_running_unit_test, Toast.LENGTH_SHORT).show();
}

public void onSystemTestHookClick(View view) {
SysTest.hook();
Toast.makeText(this, R.string.toast_system_hook, Toast.LENGTH_SHORT).show();
}

public void onSystemTestUnhookClick(View view) {
SysTest.unhook();
Toast.makeText(this, R.string.toast_system_unhook, Toast.LENGTH_SHORT).show();
}

public void onSystemTestRunClick(View view) {
SysTest.run();
Toast.makeText(this, R.string.toast_running_system_test, Toast.LENGTH_SHORT).show();
}

public void onGetRecordsClick(View view) {
String records = ShadowHook.getRecords();
Toast.makeText(this, R.string.toast_records_logcat, Toast.LENGTH_SHORT).show();
// String records = ShadowHook.getRecords(ShadowHook.RecordItem.CALLER_LIB_NAME, ShadowHook.RecordItem.OP, ShadowHook.RecordItem.LIB_NAME, ShadowHook.RecordItem.SYM_NAME, ShadowHook.RecordItem.ERRNO, ShadowHook.RecordItem.STUB);
if (records != null) {
for (String line : records.split("\n")) {
Expand All @@ -96,6 +112,7 @@ public void onGetRecordsClick(View view) {
public void onDumpRecordsClick(View view) {
String pathname = getApplicationContext().getFilesDir() + "/shadowhook_records.txt";
NativeHandler.nativeDumpRecords(pathname);
Toast.makeText(this, R.string.toast_records_dumped, Toast.LENGTH_SHORT).show();

BufferedReader br = null;
try {
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
<resources>
<string name="app_name">shadowhook</string>
<string name="toast_hook_sym_addr">Hook by symbol address...</string>
<string name="toast_hook_sym_name">Hook by symbol name...</string>
<string name="toast_unhooked">Unhooked</string>
<string name="toast_lib_loaded">libhookee2.so loaded</string>
<string name="btn_lib_loaded">libhookee2.so loaded</string>
<string name="toast_running_unit_test">Running unit test...</string>
<string name="toast_system_hook">System hook...</string>
<string name="toast_system_unhook">System unhook...</string>
<string name="toast_running_system_test">Running system test...</string>
<string name="toast_records_logcat">Records sent to logcat</string>
<string name="toast_records_dumped">Records dumped to file and logcat</string>
</resources>