Use service instead of content provider to send binder
This commit is contained in:
parent
cb0c24deb4
commit
54cf7eed35
|
|
@ -26,12 +26,9 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name=".manager.ModuleProvider"
|
||||
android:authorities="org.lsposed.lspatch.provider"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedContentProvider" />
|
||||
<service
|
||||
android:name=".manager.ModuleService"
|
||||
android:exported="true" />
|
||||
|
||||
<provider
|
||||
android:name="rikka.shizuku.ShizukuProvider"
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
package org.lsposed.lspatch.manager
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import org.lsposed.lspatch.lspApp
|
||||
|
||||
class ModuleProvider : ContentProvider() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ModuleProvider"
|
||||
}
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle {
|
||||
val app = lspApp.packageManager.getNameForUid(Binder.getCallingUid())
|
||||
Log.d(TAG, "$app requests ModuleProvider")
|
||||
return when (method) {
|
||||
"getBinder" -> Bundle().apply {
|
||||
putBinder("binder", ManagerService.asBinder())
|
||||
}
|
||||
else -> throw IllegalArgumentException("Invalid method name")
|
||||
}
|
||||
}
|
||||
|
||||
override fun query(p0: Uri, p1: Array<out String>?, p2: String?, p3: Array<out String>?, p4: String?): Cursor? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getType(p0: Uri): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun insert(p0: Uri, p1: ContentValues?): Uri? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun delete(p0: Uri, p1: String?, p2: Array<out String>?): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun update(p0: Uri, p1: ContentValues?, p2: String?, p3: Array<out String>?): Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.lsposed.lspatch.manager
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
|
||||
class ModuleService : Service() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ModuleService"
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
val packageName = intent.getStringExtra("packageName") ?: return null
|
||||
// TODO: Authentication
|
||||
Log.i(TAG, "$packageName requests binder")
|
||||
return ManagerService.asBinder()
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import android.content.Context;
|
|||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ public class LSPApplication {
|
|||
return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID;
|
||||
}
|
||||
|
||||
public static void onLoad() {
|
||||
public static void onLoad() throws RemoteException, IOException {
|
||||
if (isIsolated()) {
|
||||
XLog.d(TAG, "Skip isolated process");
|
||||
return;
|
||||
|
|
@ -75,7 +76,6 @@ public class LSPApplication {
|
|||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Log.d(TAG, "Initialize service client");
|
||||
ILSPApplicationService service;
|
||||
if (config.useManager) {
|
||||
|
|
@ -96,9 +96,7 @@ public class LSPApplication {
|
|||
|
||||
switchAllClassLoader();
|
||||
SigBypass.doSigBypass(context, config.sigBypassLevel);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Do hook", e);
|
||||
}
|
||||
|
||||
Log.i(TAG, "LSPatch bootstrap completed");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,82 @@
|
|||
package org.lsposed.lspatch.service;
|
||||
|
||||
import static org.lsposed.lspatch.share.Constants.MANAGER_PACKAGE_NAME;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.lsposed.lspatch.share.Constants;
|
||||
import org.lsposed.lspd.models.Module;
|
||||
import org.lsposed.lspd.service.ILSPApplicationService;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class RemoteApplicationService implements ILSPApplicationService {
|
||||
|
||||
private static final Uri PROVIDER = Uri.parse("content://" + MANAGER_PACKAGE_NAME + ".provider");
|
||||
private static final String TAG = "LSPatch";
|
||||
private static final String MODULE_SERVICE = Constants.MANAGER_PACKAGE_NAME + ".manager.ModuleService";
|
||||
|
||||
private final ILSPApplicationService service;
|
||||
private ILSPApplicationService service;
|
||||
|
||||
@SuppressLint("DiscouragedPrivateApi")
|
||||
public RemoteApplicationService(Context context) throws RemoteException {
|
||||
try {
|
||||
Bundle back = context.getContentResolver().call(PROVIDER, "getBinder", null, null);
|
||||
service = ILSPApplicationService.Stub.asInterface(back.getBinder("binder"));
|
||||
} catch (IllegalArgumentException | NullPointerException e) {
|
||||
var intent = new Intent()
|
||||
.setComponent(new ComponentName(Constants.MANAGER_PACKAGE_NAME, MODULE_SERVICE))
|
||||
.putExtra("packageName", context.getPackageName());
|
||||
// TODO: Authentication
|
||||
var latch = new CountDownLatch(1);
|
||||
var conn = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
Log.i(TAG, "Manager binder received");
|
||||
latch.countDown();
|
||||
service = Stub.asInterface(binder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
Log.e(TAG, "Manager service died");
|
||||
service = null;
|
||||
}
|
||||
};
|
||||
Log.i(TAG, "Request manager binder");
|
||||
context.startService(intent);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
context.bindService(intent, Context.BIND_AUTO_CREATE, Executors.newSingleThreadExecutor(), conn);
|
||||
} else {
|
||||
var handlerThread = new HandlerThread("RemoteApplicationService");
|
||||
handlerThread.start();
|
||||
var handler = new Handler(handlerThread.getLooper());
|
||||
var contextImplClass = context.getClass();
|
||||
var getUserMethod = contextImplClass.getMethod("getUser");
|
||||
var bindServiceAsUserMethod = contextImplClass.getDeclaredMethod(
|
||||
"bindServiceAsUser", Intent.class, ServiceConnection.class, int.class, Handler.class, UserHandle.class);
|
||||
var userHandle = (UserHandle) getUserMethod.invoke(context);
|
||||
bindServiceAsUserMethod.invoke(context, intent, conn, Context.BIND_AUTO_CREATE, handler, userHandle);
|
||||
}
|
||||
boolean success = latch.await(5, TimeUnit.SECONDS);
|
||||
if (!success) throw new TimeoutException("Bind service timeout");
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InterruptedException | TimeoutException e) {
|
||||
Toast.makeText(context, "Manager died", Toast.LENGTH_SHORT).show();
|
||||
var r = new RemoteException("Failed to get manager binder");
|
||||
r.initCause(e);
|
||||
|
|
|
|||
Loading…
Reference in New Issue