fix profile edit & cleanup code

This commit is contained in:
Kr328 committed 2020-04-14 12:25:20 +08:00
1 parent d24617d842
commit 3db2e1c618
8 files changed
+51 -83

No files matched your search

@@ -98,7 +98,7 @@ class ProfileEditActivity : BaseActivity() {
override fun onDestroy() {
runBlocking {
withProfile {
cancel(intent.getLongExtra("id", -1))
release(intent.getLongExtra("id", -1))
}
}
@@ -1,16 +1,15 @@
package com.github.kr328.clash
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.kr328.clash.adapter.ProfileAdapter
import com.github.kr328.clash.common.util.intent
import com.github.kr328.clash.common.util.startForegroundServiceCompat
import com.github.kr328.clash.remote.withProfile
import com.github.kr328.clash.service.ProfileProvider
import com.github.kr328.clash.service.ProfileReceiver
import com.github.kr328.clash.service.model.Profile
import com.github.kr328.clash.service.util.sendBroadcastSelf
import com.github.kr328.clash.weight.ProfilesMenu
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_profiles.*
@@ -27,7 +26,6 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
private const val EDITOR_REQUEST_CODE = 30000
}
private val self = this
private var backgroundJob: Job? = null
private val reloadMutex = Mutex()
private val editorStack = Stack<Long>()
@@ -69,12 +67,7 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
val id = editorStack.pop()
withProfile {
if (resultCode == Activity.RESULT_OK)
commitAsync(id)
else
ProfileProvider.releaseTemp(self, id)
Unit
startUpdate(id)
}
}
@@ -132,13 +125,15 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
if (id < 0)
throw FileNotFoundException()
val uri = ProfileProvider.acquireTemp(self, id)
val uri = withProfile {
acquireTempUri(id)
} ?: throw FileNotFoundException()
editorStack.push(id)
startActivityForResult(
Intent(Intent.ACTION_VIEW)
.setDataAndType(uri, "text/plain")
.setDataAndType(Uri.parse(uri), "text/plain")
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION),
EDITOR_REQUEST_CODE
)
@@ -149,7 +144,7 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
}
private fun startUpdate(id: Long) {
startForegroundServiceCompat(ProfileReceiver.buildUpdateIntentForId(id))
sendBroadcastSelf(ProfileReceiver.buildUpdateIntentForId(id))
}
override fun onOpenEditor(entity: Profile) {
@@ -18,6 +18,10 @@ class ProfileClient(private val service: IProfileService) {
service.acquireCloned(id)
}
suspend fun acquireTempUri(id: Long): String? = withContext(Dispatchers.IO) {
service.acquireTempUri(id)
}
suspend fun updateMetadata(id: Long, metadata: Profile) = withContext(Dispatchers.IO) {
service.updateMetadata(id, metadata)
}
@@ -38,8 +42,8 @@ class ProfileClient(private val service: IProfileService) {
}
}
suspend fun cancel(id: Long) = withContext(Dispatchers.IO) {
service.cancel(id)
suspend fun release(id: Long) = withContext(Dispatchers.IO) {
service.release(id)
}
suspend fun delete(id: Long) = withContext(Dispatchers.IO) {
@@ -1,5 +1,3 @@
package com.github.kr328.clash.core.event;
parcelable LogEvent;
parcelable TrafficEvent;
parcelable BandwidthEvent;
parcelable LogEvent;
@@ -1,20 +1,21 @@
package com.github.kr328.clash.service;
import com.github.kr328.clash.service.transact.IStreamCallback;
import com.github.kr328.clash.service.model.ProfileMetadata;
import com.github.kr328.clash.service.model.Profile;
interface IProfileService {
long acquireUnused(String type);
long acquireCloned(long id);
void updateMetadata(long id, in ProfileMetadata metadata);
String acquireTempUri(long id);
void release(long id);
void updateMetadata(long id, in Profile metadata);
void commit(long id, in IStreamCallback callback);
void cancel(long id);
void delete(long id);
void clear(long id);
ProfileMetadata queryById(long id);
ProfileMetadata[] queryAll();
ProfileMetadata queryActive();
Profile queryById(long id);
Profile[] queryAll();
Profile queryActive();
void setActive(long id);
}
@@ -1,3 +1,3 @@
package com.github.kr328.clash.service.model;
parcelable ProfileMetadata;
parcelable Profile;
@@ -2,22 +2,11 @@ package com.github.kr328.clash.service
import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.core.content.FileProvider
import androidx.core.os.bundleOf
import com.github.kr328.clash.service.util.resolveProfileFile
import com.github.kr328.clash.service.util.resolveTempProfileFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileNotFoundException
class ProfileProvider : FileProvider() {
companion object {
private const val METHOD_ACQUIRE_TEMP = "acquireTemp"
private const val METHOD_RELEASE_TEMP = "releaseTemp"
// service side functions
fun resolveUri(context: Context, file: File): Uri {
return getUriForFile(
context,
@@ -25,45 +14,5 @@ class ProfileProvider : FileProvider() {
file
)
}
// client side functions
suspend fun acquireTemp(context: Context, id: Long): Uri = withContext(Dispatchers.IO) {
val uri = Uri.parse(context.packageName + Constants.PROFILE_PROVIDER_SUFFIX)
context.contentResolver
.call(uri, METHOD_ACQUIRE_TEMP, id.toString(), null)?.getParcelable<Uri>("uri")
?: throw FileNotFoundException("No such profile")
}
suspend fun releaseTemp(context: Context, id: Long) = withContext(Dispatchers.IO) {
val uri = Uri.parse(context.packageName + Constants.PROFILE_PROVIDER_SUFFIX)
context.contentResolver
.call(uri, METHOD_RELEASE_TEMP, id.toString(), null)
}
}
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
when (method) {
METHOD_ACQUIRE_TEMP -> {
val id = arg?.toLongOrNull() ?: return null
val file = context!!.resolveProfileFile(id)
if (!file.exists())
return null
val temp = context!!.resolveTempProfileFile(id)
if (!temp.exists())
file.copyTo(context!!.resolveTempProfileFile(id))
return bundleOf("uri" to resolveUri(context!!, temp))
}
METHOD_RELEASE_TEMP -> {
val id = arg?.toLongOrNull() ?: return null
context!!.resolveTempProfileFile(id).delete()
}
}
return super.call(method, arg, extras)
}
}
@@ -44,7 +44,7 @@ class ProfileService : BaseService() {
}
}
override fun cancel(id: Long) {
override fun release(id: Long) {
launch {
lock.withLock {
pending.remove(id)
@@ -138,6 +138,26 @@ class ProfileService : BaseService() {
}
}
override fun acquireTempUri(id: Long): String? {
val file = service.resolveProfileFile(id)
if ( !file.exists() )
return null
val tempFile = service.resolveTempProfileFile(id)
file.copyTo(tempFile)
val uri = ProfileProvider.resolveUri(service, tempFile)
return runBlocking {
lock.withLock {
pending[id] = queryMetadataById(id)?.copy(uri = uri) ?: return@withLock
}
uri.toString()
}
}
override fun updateMetadata(id: Long, metadata: Profile?) {
launch {
lock.withLock {
@@ -164,7 +184,7 @@ class ProfileService : BaseService() {
val ctx = lock.withLock {
tasks.entries.firstOrNull()?.also {
tasks.remove(it.key)
tasks[it.key]
}
} ?: continue
@@ -172,10 +192,6 @@ class ProfileService : BaseService() {
val metadata = queryMetadataById(ctx.key)
?: throw RemoteException("No such profile")
lock.withLock {
pending.remove(metadata.id)
}
ProfileProcessor.createOrUpdate(service, metadata)
ctx.value?.complete()
@@ -184,6 +200,11 @@ class ProfileService : BaseService() {
} catch (e: Exception) {
ctx.value?.completeExceptionally(e.message)
}
finally {
lock.withLock {
tasks.remove(ctx.key)
}
}
request.offer(Unit)
}