Skip to content

Commit b0d29e6

Browse files
committed
stability: shrink chooser result payloads
1 parent bfc1ce4 commit b0d29e6

4 files changed

Lines changed: 112 additions & 13 deletions

File tree

app/src/main/java/com/kyhsgeekcode/disassembler/viewmodel/MainViewModel.kt

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.kyhsgeekcode.disassembler.ui.TabKind
3030
import com.kyhsgeekcode.disassembler.ui.tabs.*
3131
import com.kyhsgeekcode.filechooser.model.FileItem
3232
import com.kyhsgeekcode.filechooser.model.FileItemApp
33+
import com.kyhsgeekcode.filechooser.NewFileChooserActivity
3334
import kotlinx.coroutines.CoroutineScope
3435
import kotlinx.coroutines.Dispatchers
3536
import kotlinx.coroutines.channels.Channel
@@ -117,6 +118,11 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
117118
fun onSelectIntent(intent: Intent) {
118119
Timber.d("onActivityResultOk")
119120
_openAsProject.value = intent.getBooleanExtra("openProject", false)
121+
val selectedFilePayload = selectedFileIntentPayload(intent)
122+
if (selectedFilePayload != null) {
123+
onSelectFilePayload(selectedFilePayload)
124+
return
125+
}
120126
val fi = intent.serializableExtraCompat<FileItem>("fileItem")
121127
if (fi != null) {
122128
onSelectFileItem(fi)
@@ -130,16 +136,23 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
130136
}
131137

132138
private fun onSelectFileItem(fileItem: FileItem) {
133-
_file.value = fileItem.file ?: run {
139+
val file = fileItem.file ?: run {
134140
Logger.e(TAG, "Failed to load fileItem: $fileItem")
135141
return@onSelectFileItem
136142
}
137-
_nativeFile.value = if (fileItem is FileItemApp) {
138-
fileItem.nativeFile
139-
} else {
140-
null
141-
}
142-
_projectType.value = fileItemTypeToProjectType(fileItem)
143+
onSelectFilePayload(
144+
SelectedFileIntentPayload(
145+
filePath = file.absolutePath,
146+
nativeFilePath = (fileItem as? FileItemApp)?.nativeFile?.absolutePath,
147+
projectType = fileItemTypeToProjectType(fileItem)
148+
)
149+
)
150+
}
151+
152+
private fun onSelectFilePayload(payload: SelectedFileIntentPayload) {
153+
_file.value = File(payload.filePath)
154+
_nativeFile.value = payload.nativeFilePath?.let(::File)
155+
_projectType.value = payload.projectType
143156
_askCopy.value = true
144157
}
145158

@@ -415,6 +428,33 @@ private inline fun <reified T : java.io.Serializable> Intent.serializableExtraCo
415428
}
416429
}
417430

431+
internal data class SelectedFileIntentPayload(
432+
val filePath: String,
433+
val nativeFilePath: String?,
434+
val projectType: String
435+
)
436+
437+
internal fun selectedFileIntentPayload(intent: Intent): SelectedFileIntentPayload? {
438+
return selectedFileIntentPayload(
439+
filePath = intent.getStringExtra(NewFileChooserActivity.EXTRA_FILE_PATH),
440+
nativeFilePath = intent.getStringExtra(NewFileChooserActivity.EXTRA_NATIVE_FILE_PATH),
441+
projectType = intent.getStringExtra(NewFileChooserActivity.EXTRA_PROJECT_TYPE)
442+
)
443+
}
444+
445+
internal fun selectedFileIntentPayload(
446+
filePath: String?,
447+
nativeFilePath: String?,
448+
projectType: String?
449+
): SelectedFileIntentPayload? {
450+
val resolvedFilePath = filePath ?: return null
451+
return SelectedFileIntentPayload(
452+
filePath = resolvedFilePath,
453+
nativeFilePath = nativeFilePath,
454+
projectType = projectType ?: ProjectType.UNKNOWN
455+
)
456+
}
457+
418458

419459
private fun createTabData(item: FileDrawerTreeItem): TabData {
420460
var title = "${item.caption} as ${item.type}"

app/src/main/java/com/kyhsgeekcode/filechooser/NewFileChooserActivity.kt

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
1414
import com.kyhsgeekcode.disassembler.ProgressHandler
1515
import com.kyhsgeekcode.disassembler.databinding.ActivityNewFileChooserBinding
1616
import com.kyhsgeekcode.disassembler.preference.PowerUserModeSettings
17+
import com.kyhsgeekcode.disassembler.project.models.ProjectType
1718
import com.kyhsgeekcode.disassembler.showYesNoDialog
1819
import com.kyhsgeekcode.download
1920
import com.kyhsgeekcode.filechooser.model.FileItem
21+
import com.kyhsgeekcode.filechooser.model.FileItemApp
2022
import com.tingyik90.snackprogressbar.SnackProgressBar
2123
import com.tingyik90.snackprogressbar.SnackProgressBarManager
2224
import kotlinx.coroutines.CoroutineScope
@@ -31,6 +33,9 @@ import java.net.URL
3133
class NewFileChooserActivity : AppCompatActivity(), ProgressHandler {
3234
companion object {
3335
const val EXTRA_POWER_USER_MODE = "power_user_mode"
36+
const val EXTRA_FILE_PATH = "selected_file_path"
37+
const val EXTRA_NATIVE_FILE_PATH = "selected_native_file_path"
38+
const val EXTRA_PROJECT_TYPE = "selected_project_type"
3439
}
3540

3641
private var _binding: ActivityNewFileChooserBinding? = null
@@ -88,17 +93,17 @@ class NewFileChooserActivity : AppCompatActivity(), ProgressHandler {
8893
}
8994

9095
fun openAsProject(item: FileItem) {
91-
val resultIntent = Intent()
92-
resultIntent.putExtra("fileItem", item)
93-
resultIntent.putExtra("openProject", true)
96+
val resultIntent = selectedFileResultIntent(item).apply {
97+
putExtra("openProject", true)
98+
}
9499
setResult(Activity.RESULT_OK, resultIntent)
95100
finish()
96101
}
97102

98103
fun openRaw(item: FileItem) {
99-
val resultIntent = Intent()
100-
resultIntent.putExtra("fileItem", item)
101-
resultIntent.putExtra("openProject", false)
104+
val resultIntent = selectedFileResultIntent(item).apply {
105+
putExtra("openProject", false)
106+
}
102107
setResult(Activity.RESULT_OK, resultIntent)
103108
finish()
104109
}
@@ -224,4 +229,23 @@ class NewFileChooserActivity : AppCompatActivity(), ProgressHandler {
224229
return null
225230
}
226231

232+
private fun selectedFileResultIntent(item: FileItem): Intent {
233+
val file = requireNotNull(item.file) { "Cannot return chooser result without a backing file" }
234+
return Intent().apply {
235+
putExtra(EXTRA_FILE_PATH, file.absolutePath)
236+
putExtra(EXTRA_PROJECT_TYPE, projectTypeFor(item))
237+
if (item is FileItemApp) {
238+
putExtra(EXTRA_NATIVE_FILE_PATH, item.nativeFile.absolutePath)
239+
}
240+
}
241+
}
242+
243+
private fun projectTypeFor(item: FileItem): String {
244+
return if (item is FileItemApp) {
245+
ProjectType.APK
246+
} else {
247+
ProjectType.UNKNOWN
248+
}
249+
}
250+
227251
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.kyhsgeekcode.disassembler
2+
3+
import com.kyhsgeekcode.disassembler.project.models.ProjectType
4+
import com.kyhsgeekcode.disassembler.viewmodel.selectedFileIntentPayload
5+
import org.junit.jupiter.api.Assertions.assertEquals
6+
import org.junit.jupiter.api.Assertions.assertNull
7+
import org.junit.jupiter.api.Test
8+
9+
class FileSelectionIntentPayloadTest {
10+
@Test
11+
fun `selectedFileIntentPayload reads compact chooser extras`() {
12+
val payload = selectedFileIntentPayload(
13+
filePath = "/tmp/sample.apk",
14+
nativeFilePath = "/tmp/lib",
15+
projectType = ProjectType.APK
16+
)
17+
18+
requireNotNull(payload)
19+
assertEquals("/tmp/sample.apk", payload.filePath)
20+
assertEquals("/tmp/lib", payload.nativeFilePath)
21+
assertEquals(ProjectType.APK, payload.projectType)
22+
}
23+
24+
@Test
25+
fun `selectedFileIntentPayload returns null when chooser file path is missing`() {
26+
assertNull(
27+
selectedFileIntentPayload(
28+
filePath = null,
29+
nativeFilePath = null,
30+
projectType = ProjectType.UNKNOWN
31+
)
32+
)
33+
}
34+
}

docs/maintenance/implementation-log.ko.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
| instrumentation test 기반 부재 | AndroidX instrumentation runner를 설정하고 `MainActivity`가 emulator에서 `RESUMED` 상태까지 올라오는 smoke test와 CI emulator job을 추가 | unit test만으로는 잡히지 않는 startup/regression을 GitHub Actions emulator에서 자동 확인할 수 있는 최소 기반을 만들었다 | `app/build.gradle`, `app/src/androidTest/java/com/kyhsgeekcode/disassembler/MainActivitySmokeTest.kt`, `.github/workflows/ci.yml` | 완료 |
3131
| PR 회귀를 잡는 instrumentation 범위 부족 | Compose UI test 의존성, import entry-point test tag, 회전 재생성 smoke test, standard/power-user mode UI 검증 테스트를 추가 | 현재 PR의 핵심 변경인 회전 재생성 경계와 `Select file`/`Advanced import` 노출 규칙을 emulator에서 직접 검증할 수 있게 했다 | `app/build.gradle`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/MainTab.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/MainTestTags.kt`, `app/src/androidTest/java/com/kyhsgeekcode/disassembler/MainActivitySmokeTest.kt`, `app/src/androidTest/java/com/kyhsgeekcode/disassembler/MainActivityImportEntryPointStandardModeTest.kt`, `app/src/androidTest/java/com/kyhsgeekcode/disassembler/MainActivityImportEntryPointPowerUserModeTest.kt`, `app/src/androidTest/java/com/kyhsgeekcode/disassembler/PowerUserModePreferenceRule.kt` | 완료 |
3232
| 이슈 `#523`, `#442`, `#235` 대용량 파일/리스트 경계 | 큰 파일은 `ProjectDataStorage` 메모리 캐시에서 제외하고, 문자열 검색 결과는 5,000개로 상한을 두고 stable key로 렌더링하도록 바꿨다 | 150MB 같은 큰 파일을 한 번 열 때 캐시 맵이 오래 붙잡는 메모리 압박을 줄이고, 문자열 탭의 대형 리스트가 계속 불어나면서 Recycler/Lazy list가 불안정해지는 경로를 완화했다 | `app/src/main/java/com/kyhsgeekcode/disassembler/project/ProjectDataStorage.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/components/TableView.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/StringTab.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/project/ProjectDataStorageCachePolicyTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ui/tabs/StringSearchResultAccumulatorTest.kt` | 완료 |
33+
| 이슈 `#235` binder payload 과대 가능성 | file chooser 결과가 `Serializable FileItem` 전체를 넘기지 않고 `filePath/nativeFilePath/projectType`만 넘기도록 축소 | chooser 결과 인텐트의 binder payload를 줄여 `TransactionTooLarge`류 상태 전송 압박을 완화하고, 결과 복원 경계도 pure helper 테스트로 고정했다 | `app/src/main/java/com/kyhsgeekcode/filechooser/NewFileChooserActivity.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/viewmodel/MainViewModel.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/FileSelectionIntentPayloadTest.kt` | 완료 |
3334
| 이슈 `#514`, `#543`, `#576` `.so`/ELF 아키텍처와 override autosetup | `x86_64`, `PPC64` ELF machine type을 64-bit disassembly mode로 매핑하고, binary overview에서 수동 설정을 적용하면 disassembly handle을 다시 열도록 바꿨다 | 일부 `.so`가 32-bit mode로 잘못 열리던 경로를 줄이고, `Override autosetup`이 값만 바꾸고 실제 disassembly는 안 바뀌던 문제를 수정했다 | `app/src/main/java/com/kyhsgeekcode/disassembler/models/Architecture.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/BinaryOverviewTab.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/BinaryTab.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/models/ArchitectureTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ui/tabs/BinaryManualSetupConfigTest.kt` | 완료 |
3435
| 이슈 `#123`, `#720` 프로젝트 export와 details 저장 부재 | ZIP 생성기를 재귀 상대경로 방식으로 고치고, 프로젝트 overview에 SAF `CreateDocument` 기반 `Export project` 버튼을 추가했으며, binary detail 탭에는 `Save Details to file` 버튼을 구현했다 | 깨져 있던 project ZIP export 경로를 실제로 복구하고, 최신 Android 저장소 모델에 맞게 상세 정보 텍스트를 `.txt` 문서로 저장할 수 있게 했다 | `app/src/main/java/com/kyhsgeekcode/Util.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/exporting/ExportDocuments.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/project/ProjectManager.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/viewmodel/MainViewModel.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/MainTab.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/BinaryDetailTab.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ProjectExportArchiveTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/exporting/BinaryDetailsExportTest.kt` | 완료 |
3536
| 이슈 `#129` `.ar` archive 지원 | 공용 archive extractor를 추가하고, Compose/legacy drawer의 archive 확장 경로를 ZIP 전용 구현에서 generic archive extractor로 교체했다 | archive 판정은 되는데 실제 확장은 ZIP만 되던 불일치를 제거해서 `.ar` 같은 지원 가능한 archive도 실제로 탐색 가능하게 만들었다 | `app/src/main/java/com/kyhsgeekcode/Util.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/FileDrawerTree.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/FileDrawerListItem.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/FileDrawerListAdapter.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ArchiveExtractionTest.kt` | 완료 |

0 commit comments

Comments
 (0)