227 lines
9.9 KiB
Java
227 lines
9.9 KiB
Java
|
package com.termux.x11.starter;
|
||
|
|
||
|
import android.annotation.SuppressLint;
|
||
|
import android.app.PendingIntent;
|
||
|
import android.content.ComponentName;
|
||
|
import android.content.IIntentReceiver;
|
||
|
import android.content.Intent;
|
||
|
import android.net.Uri;
|
||
|
import android.os.Bundle;
|
||
|
import android.os.IBinder;
|
||
|
|
||
|
import java.lang.reflect.InvocationTargetException;
|
||
|
|
||
|
/**
|
||
|
* Wrapper around android.app.IActivityManager internal interface
|
||
|
*/
|
||
|
@SuppressLint("PrivateApi")
|
||
|
class IActivityManager {
|
||
|
|
||
|
private Object mAm;
|
||
|
private CrossVersionReflectedMethod mGetProviderMimeType;
|
||
|
private CrossVersionReflectedMethod mStartActivity;
|
||
|
/*
|
||
|
private CrossVersionReflectedMethod mBroadcastIntent;
|
||
|
*/
|
||
|
private CrossVersionReflectedMethod mStartServiceMethod;
|
||
|
private CrossVersionReflectedMethod mStopServiceMethod;
|
||
|
private CrossVersionReflectedMethod mGetIntentSenderMethod;
|
||
|
private CrossVersionReflectedMethod mIntentSenderSendMethod;
|
||
|
|
||
|
IActivityManager() throws Exception {
|
||
|
this("com.termux");
|
||
|
}
|
||
|
|
||
|
IActivityManager(String callingAppName) throws Exception {
|
||
|
try {
|
||
|
try {
|
||
|
mAm = android.app.ActivityManager.class
|
||
|
.getMethod("getService")
|
||
|
.invoke(null);
|
||
|
} catch (Exception e) {
|
||
|
mAm = Class.forName("android.app.ActivityManagerNative")
|
||
|
.getMethod("getDefault")
|
||
|
.invoke(null);
|
||
|
}
|
||
|
Class<?> amClass = mAm.getClass();
|
||
|
mGetProviderMimeType =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"getProviderMimeType",
|
||
|
Uri.class, "uri",
|
||
|
int.class, "userId"
|
||
|
);
|
||
|
mStartActivity =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"startActivityAsUser",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
String.class, "callingPackage", callingAppName,
|
||
|
Intent.class, "intent", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
IBinder.class, "resultTo", null,
|
||
|
String.class, "resultWho", null,
|
||
|
int.class, "requestCode", -1,
|
||
|
int.class, "flags", 0,
|
||
|
//ProfilerInfo profilerInfo, - let's autodetect
|
||
|
Bundle.class, "options", null,
|
||
|
int.class, "userId", 0
|
||
|
);
|
||
|
/*
|
||
|
mBroadcastIntent =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"broadcastIntent",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
Intent.class, "intent", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
IIntentReceiver.class, "resultTo", null,
|
||
|
int.class, "resultCode", -1,
|
||
|
String.class, "resultData", null,
|
||
|
Bundle.class, "map", null,
|
||
|
String[].class, "requiredPermissions", null,
|
||
|
int.class, "appOp", 0,
|
||
|
Bundle.class, "options", null,
|
||
|
boolean.class, "serialized", false,
|
||
|
boolean.class, "sticky", false,
|
||
|
int.class, "userId", 0
|
||
|
);
|
||
|
*/
|
||
|
mStartServiceMethod =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"startService",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
Intent.class, "service", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
boolean.class, "requireForeground", false,
|
||
|
String.class, "callingPackage", callingAppName,
|
||
|
int.class, "userId", 0
|
||
|
).tryMethodVariantInexact(
|
||
|
"startService",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
Intent.class, "service", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
String.class, "callingPackage", callingAppName,
|
||
|
int.class, "userId", 0
|
||
|
).tryMethodVariantInexact( // Pre frameworks/base 99b6043
|
||
|
"startService",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
Intent.class, "service", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
int.class, "userId", 0
|
||
|
);
|
||
|
mStopServiceMethod =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"stopService",
|
||
|
"android.app.IApplicationThread", "caller", null,
|
||
|
Intent.class, "service", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
int.class, "userId", 0
|
||
|
);
|
||
|
mGetIntentSenderMethod =
|
||
|
new CrossVersionReflectedMethod(amClass)
|
||
|
.tryMethodVariantInexact(
|
||
|
"getIntentSender",
|
||
|
int.class, "type", 0,
|
||
|
String.class, "packageName", callingAppName,
|
||
|
IBinder.class, "token", null,
|
||
|
String.class, "resultWho", null,
|
||
|
int.class, "requestCode", 0,
|
||
|
Intent[].class, "intents", null,
|
||
|
String[].class, "resolvedTypes", null,
|
||
|
int.class, "flags", 0,
|
||
|
Bundle.class, "options", null,
|
||
|
int.class, "userId", 0
|
||
|
);
|
||
|
mIntentSenderSendMethod =
|
||
|
new CrossVersionReflectedMethod(Class.forName("android.content.IIntentSender"))
|
||
|
.tryMethodVariantInexact(
|
||
|
"send",
|
||
|
int.class, "code", 0,
|
||
|
Intent.class, "intent", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
//IBinder.class, "android.os.IBinder whitelistToken", null,
|
||
|
"android.content.IIntentReceiver", "finishedReceiver", null,
|
||
|
String.class, "requiredPermission", null,
|
||
|
Bundle.class, "options", null
|
||
|
).tryMethodVariantInexact( // Pre frameworks/base a750a63
|
||
|
"send",
|
||
|
int.class, "code", 0,
|
||
|
Intent.class, "intent", null,
|
||
|
String.class, "resolvedType", null,
|
||
|
"android.content.IIntentReceiver", "finishedReceiver", null,
|
||
|
String.class, "requiredPermission", null
|
||
|
);
|
||
|
|
||
|
|
||
|
} catch (Exception e) {
|
||
|
throw new RuntimeException(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int startActivityAsUser(Intent intent, String resolvedType, int flags, Bundle options, int userId) throws InvocationTargetException {
|
||
|
return (Integer) mStartActivity.invoke(
|
||
|
mAm,
|
||
|
"intent", intent,
|
||
|
"resolvedType", resolvedType,
|
||
|
"flags", flags,
|
||
|
"options", options,
|
||
|
"userId", userId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
void broadcastIntent(Intent intent, IIntentReceiver resultTo, String[] requiredPermissions, boolean serialized, boolean sticky, int userId) throws InvocationTargetException {
|
||
|
/*
|
||
|
mBroadcastIntent.invoke(
|
||
|
mAm,
|
||
|
"intent", intent,
|
||
|
"resultTo", resultTo,
|
||
|
"requiredPermissions", requiredPermissions,
|
||
|
"serialized", serialized,
|
||
|
"sticky", sticky,
|
||
|
"userId", userId
|
||
|
);
|
||
|
*/
|
||
|
Object pendingIntent = mGetIntentSenderMethod.invoke(
|
||
|
mAm,
|
||
|
"type", 1 /*ActivityManager.INTENT_SENDER_BROADCAST*/,
|
||
|
"intents", new Intent[] { intent },
|
||
|
"flags", PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT,
|
||
|
"userId", userId
|
||
|
);
|
||
|
mIntentSenderSendMethod.invoke(
|
||
|
pendingIntent,
|
||
|
"requiredPermission", (requiredPermissions == null || requiredPermissions.length == 0) ? null : requiredPermissions[0],
|
||
|
"finishedReceiver", resultTo
|
||
|
);
|
||
|
}
|
||
|
|
||
|
String getProviderMimeType(Uri uri, int userId) throws InvocationTargetException {
|
||
|
return (String) mGetProviderMimeType.invoke(
|
||
|
mAm,
|
||
|
"uri", uri,
|
||
|
"userId", userId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
ComponentName startService(Intent service, String resolvedType, int userId) throws InvocationTargetException {
|
||
|
return (ComponentName) mStartServiceMethod.invoke(
|
||
|
mAm,
|
||
|
"service", service,
|
||
|
"resolvedType", resolvedType,
|
||
|
"userId", userId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
int stopService(Intent service, String resolvedType, int userId) throws InvocationTargetException {
|
||
|
return (Integer) mStopServiceMethod.invoke(
|
||
|
mAm,
|
||
|
"service", service,
|
||
|
"resolvedType", resolvedType,
|
||
|
"userId", userId
|
||
|
);
|
||
|
}
|
||
|
}
|