Skip to content

Commit

Permalink
Async RPC call of Android Binder (#1201)
Browse files Browse the repository at this point in the history
* Rearrange package for settings collector and stat callback of service.

* make async call

* Remove CoroutineScope

* Remove `convert` argument.

* Make RetryRemoteCall.getRemote suspend.

* Don't implement ConnectivityAware and RemoteCall for client object.

* use Mutex

* use MutableStateFlow.update

* Extract argument `transact` of function `callSuspendCancellable` to `RemoteContinuation`

* use RemoteException

* remove implementation ConnectivityAware of proxy

* rename `RemoteCall` to `RemoteObject`

* make `setRemote` thread-safe
  • Loading branch information
StageGuard authored Nov 16, 2024
1 parent ede0d23 commit 700bb3b
Show file tree
Hide file tree
Showing 32 changed files with 658 additions and 284 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
package me.him188.ani.app.domain.torrent;

import me.him188.ani.app.domain.torrent.IRemoteTorrentDownloader;
import me.him188.ani.app.domain.torrent.IAnitorrentConfigCollector;
import me.him188.ani.app.domain.torrent.IProxySettingsCollector;
import me.him188.ani.app.domain.torrent.ITorrentPeerConfigCollector;
import me.him188.ani.app.domain.torrent.collector.IAnitorrentConfigCollector;
import me.him188.ani.app.domain.torrent.collector.IProxySettingsCollector;
import me.him188.ani.app.domain.torrent.collector.ITorrentPeerConfigCollector;

// Declare any non-default types here with import statements

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// IRemoteTorrentDownloader.aidl
package me.him188.ani.app.domain.torrent;

import me.him188.ani.app.domain.torrent.ITorrentDownloaderStatsCallback;
import me.him188.ani.app.domain.torrent.callback.ITorrentDownloaderStatsCallback;
import me.him188.ani.app.domain.torrent.cont.ContTorrentDownloaderFetchTorrent;
import me.him188.ani.app.domain.torrent.cont.ContTorrentDownloaderStartDownload;
import me.him188.ani.app.domain.torrent.IRemoteTorrentSession;
import me.him188.ani.app.domain.torrent.IDisposableHandle;
import me.him188.ani.app.domain.torrent.parcel.PTorrentLibInfo;
Expand All @@ -14,9 +16,9 @@ interface IRemoteTorrentDownloader {

PTorrentLibInfo getVendor();

PEncodedTorrentInfo fetchTorrent(in String uri, int timeoutSeconds);
IDisposableHandle fetchTorrent(in String uri, int timeoutSeconds, in ContTorrentDownloaderFetchTorrent cont);

IRemoteTorrentSession startDownload(in PEncodedTorrentInfo data, in String overrideSaveDir);
IDisposableHandle startDownload(in PEncodedTorrentInfo data, in String overrideSaveDir, in ContTorrentDownloaderStartDownload cont);

String getSaveDirForTorrent(in PEncodedTorrentInfo data);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// IRemoteTorrentFileEntry.aidl
package me.him188.ani.app.domain.torrent;

import me.him188.ani.app.domain.torrent.ITorrentFileEntryStatsCallback;
import me.him188.ani.app.domain.torrent.callback.ITorrentFileEntryStatsCallback;
import me.him188.ani.app.domain.torrent.cont.ContTorrentFileEntryGetInputParams;
import me.him188.ani.app.domain.torrent.cont.ContTorrentFileEntryResolveFile;
import me.him188.ani.app.domain.torrent.IRemotePieceList;
import me.him188.ani.app.domain.torrent.IRemoteTorrentFileHandle;
import me.him188.ani.app.domain.torrent.IDisposableHandle;
Expand All @@ -22,11 +24,11 @@ interface IRemoteTorrentFileEntry {

IRemoteTorrentFileHandle createHandle();

String resolveFile();
IDisposableHandle resolveFile(in ContTorrentFileEntryResolveFile cont);

String resolveFileMaybeEmptyOrNull();

PTorrentInputParameter getTorrentInputParams();
IDisposableHandle getTorrentInputParams(in ContTorrentFileEntryGetInputParams cont);

void torrentInputOnWait(int pieceIndex);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// IRemoteTorrentSession.aidl
package me.him188.ani.app.domain.torrent;

import me.him188.ani.app.domain.torrent.ITorrentSessionStatsCallback;
import me.him188.ani.app.domain.torrent.callback.ITorrentSessionStatsCallback;
import me.him188.ani.app.domain.torrent.cont.ContTorrentSessionGetFiles;
import me.him188.ani.app.domain.torrent.IRemoteTorrentFileEntryList;
import me.him188.ani.app.domain.torrent.parcel.PPeerInfo;
import me.him188.ani.app.domain.torrent.IDisposableHandle;
Expand All @@ -13,7 +14,7 @@ interface IRemoteTorrentSession {

String getName();

IRemoteTorrentFileEntryList getFiles();
IDisposableHandle getFiles(in ContTorrentSessionGetFiles cont);

PPeerInfo[] getPeers();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ITorrentDownloaderStatsCallback.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.callback;

import me.him188.ani.app.domain.torrent.parcel.PTorrentDownloaderStats;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ITorrentFileEntryStatsCallback.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.callback;

import me.him188.ani.app.domain.torrent.parcel.PTorrentFileEntryStats;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ITorrentSessionStatsCallback.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.callback;

import me.him188.ani.app.domain.torrent.parcel.PTorrentSessionStats;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// IAnitorrentConfigCollector.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.collector;

import me.him188.ani.app.domain.torrent.parcel.PAnitorrentConfig;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// IProxySettingsCollector.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.collector;

import me.him188.ani.app.domain.torrent.parcel.PProxySettings;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ITorrentPeerConfigCollector.aidl
package me.him188.ani.app.domain.torrent;
package me.him188.ani.app.domain.torrent.collector;

import me.him188.ani.app.domain.torrent.parcel.PTorrentPeerConfig;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ContTorrentDownloaderFetchTorrent.aidl
package me.him188.ani.app.domain.torrent.cont;

import me.him188.ani.app.domain.torrent.parcel.PEncodedTorrentInfo;
import me.him188.ani.app.domain.torrent.parcel.RemoteContinuationException;

// Declare any non-default types here with import statements

interface ContTorrentDownloaderFetchTorrent {
void resume(in PEncodedTorrentInfo value);
void resumeWithException(in RemoteContinuationException exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ContTorrentDownloaderStartDownload.aidl
package me.him188.ani.app.domain.torrent.cont;

import me.him188.ani.app.domain.torrent.IRemoteTorrentSession;
import me.him188.ani.app.domain.torrent.parcel.RemoteContinuationException;

// Declare any non-default types here with import statements

interface ContTorrentDownloaderStartDownload {
void resume(in IRemoteTorrentSession value);
void resumeWithException(in RemoteContinuationException exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ContTorrentFileEntryGetInputParams.aidl
package me.him188.ani.app.domain.torrent.cont;

import me.him188.ani.app.domain.torrent.parcel.PTorrentInputParameter;
import me.him188.ani.app.domain.torrent.parcel.RemoteContinuationException;

// Declare any non-default types here with import statements

interface ContTorrentFileEntryGetInputParams {
void resume(in PTorrentInputParameter value);
void resumeWithException(in RemoteContinuationException exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ContTorrentFileEntryResolveFile.aidl
package me.him188.ani.app.domain.torrent.cont;

import me.him188.ani.app.domain.torrent.parcel.PTorrentInputParameter;
import me.him188.ani.app.domain.torrent.parcel.RemoteContinuationException;

// Declare any non-default types here with import statements

interface ContTorrentFileEntryResolveFile {
void resume(in String value);
void resumeWithException(in RemoteContinuationException exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ContTorrentSessionGetFiles.aidl
package me.him188.ani.app.domain.torrent.cont;

import me.him188.ani.app.domain.torrent.IRemoteTorrentFileEntryList;
import me.him188.ani.app.domain.torrent.parcel.RemoteContinuationException;

// Declare any non-default types here with import statements

interface ContTorrentSessionGetFiles {
void resume(in IRemoteTorrentFileEntryList value);
void resumeWithException(in RemoteContinuationException exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RemoteContinuationException.aidl
package me.him188.ani.app.domain.torrent.parcel;

parcelable RemoteContinuationException;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ package me.him188.ani.app.domain.torrent.client
import android.os.Build
import android.os.IInterface
import androidx.annotation.RequiresApi
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
Expand All @@ -20,7 +22,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.Json
import me.him188.ani.app.data.models.preference.AnitorrentConfig
import me.him188.ani.app.data.models.preference.ProxySettings
Expand All @@ -34,6 +35,7 @@ import me.him188.ani.app.domain.torrent.parcel.PTorrentPeerConfig
import me.him188.ani.app.domain.torrent.service.TorrentServiceConnection
import me.him188.ani.app.torrent.api.TorrentDownloader
import me.him188.ani.datasources.api.source.MediaSourceLocation
import me.him188.ani.utils.coroutines.IO_
import me.him188.ani.utils.coroutines.childScope
import me.him188.ani.utils.coroutines.onReplacement
import me.him188.ani.utils.io.SystemPath
Expand All @@ -50,8 +52,13 @@ class RemoteAnitorrentEngine(
saveDir: SystemPath,
parentCoroutineContext: CoroutineContext,
) : TorrentEngine {
private val childScope = parentCoroutineContext.childScope()
private val logger = logger<RemoteAnitorrentEngine>()

private val scope = parentCoroutineContext.childScope()
private val fetchRemoteScope = parentCoroutineContext.childScope(
CoroutineName("RemoteAnitorrentEngineFetchRemote") + Dispatchers.IO_,
)

private val connectivityAware = DefaultConnectivityAware(
parentCoroutineContext.childScope(),
connection.connected,
Expand Down Expand Up @@ -98,26 +105,29 @@ class RemoteAnitorrentEngine(
}

override suspend fun getDownloader(): TorrentDownloader {
return RemoteTorrentDownloader(connectivityAware) {
runBlocking { getBinderOrFail() }.downlaoder
}
return RemoteTorrentDownloader(
fetchRemoteScope,
RetryRemoteObject(fetchRemoteScope) { getBinderOrFail().downlaoder },
connectivityAware,
)
}

private suspend fun getBinderOrFail(): IRemoteAniTorrentEngine {
return connection.awaitBinder()
}

override fun close() {
childScope.cancel()
scope.cancel()
fetchRemoteScope.cancel()
}

private inline fun <I : IInterface> collectSettingsToRemote(
settingsFlow: Flow<String>,
noinline getBinder: suspend () -> I,
crossinline transact: I.(String) -> Unit
) = childScope.launch {
) = scope.launch {
val stateFlow = settingsFlow.stateIn(this)
val remoteCall = RetryRemoteCall { runBlocking { getBinder() } }
val remoteCall = RetryRemoteObject(fetchRemoteScope) { getBinder() }

connection.connected
.filter { it }
Expand Down

This file was deleted.

Loading

0 comments on commit 700bb3b

Please sign in to comment.