Skip to content

Commit

Permalink
Wrap hidden methods of Instrumentation
Browse files Browse the repository at this point in the history
This should solve RikkaApps#41
  • Loading branch information
RikkaW committed Oct 4, 2022
1 parent 5465bc3 commit 6e50253
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 2 deletions.
5 changes: 3 additions & 2 deletions module/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ dependencies {
implementation project(':rish')
implementation project(':server-shared')

implementation 'dev.rikka.hidden:compat:3.2.0'
compileOnly 'dev.rikka.hidden:stub:3.2.0'
def hiddenApiVersion = '3.4.2'
implementation "dev.rikka.hidden:compat:$hiddenApiVersion"
compileOnly "dev.rikka.hidden:stub:$hiddenApiVersion"
}

def outDir = file("$rootDir/out")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.app.Activity;
import android.app.ActivityThread;
import android.app.Application;
import android.app.IAppTask;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ComponentCallbacks2;
Expand All @@ -41,17 +42,22 @@
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.TestLooperManager;
import android.os.UserHandle;
import android.view.KeyEvent;
import android.view.MotionEvent;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.android.internal.content.ReferrerIntent;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import rikka.sui.resource.SuiApk;
import rikka.sui.util.InstrumentationUtil;

public class SettingsInstrumentation extends Instrumentation {

Expand Down Expand Up @@ -400,6 +406,12 @@ public void callActivityOnNewIntent(Activity activity, Intent intent) {
original.callActivityOnNewIntent(activity, intent);
}

@Keep
public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
LOGGER.d("callActivityOnNewIntent: %s", activity);
InstrumentationUtil.callActivityOnNewIntent(original, activity, intent);
}

@Override
public void callActivityOnStart(Activity activity) {
original.callActivityOnStart(activity);
Expand Down Expand Up @@ -492,4 +504,60 @@ public UiAutomation getUiAutomation(int flags) {
public TestLooperManager acquireLooperManager(Looper looper) {
return original.acquireLooperManager(looper);
}

@Keep
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
LOGGER.d("execStartActivity: %s", target);
return InstrumentationUtil.execStartActivity(original, who, contextThread, token, target, intent, requestCode, options);
}

@Keep
public void execStartActivities(Context who, IBinder contextThread,
IBinder token, Activity target, Intent[] intents, Bundle options) {
LOGGER.d("execStartActivities: %s", target);
InstrumentationUtil.execStartActivities(original, who, contextThread, token, target, intents, options);
}

@Keep
public int execStartActivitiesAsUser(Context who, IBinder contextThread,
IBinder token, Activity target, Intent[] intents, Bundle options,
int userId) {
LOGGER.d("execStartActivitiesAsUser: %s", target);
return InstrumentationUtil.execStartActivitiesAsUser(original, who, contextThread, token, target, intents, options, userId);
}

@Keep
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
LOGGER.d("execStartActivity2: %s", target);
return InstrumentationUtil.execStartActivity(original, who, contextThread, token, target, intent, requestCode, options);
}

@Keep
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String resultWho,
Intent intent, int requestCode, Bundle options, UserHandle user) {
LOGGER.d("execStartActivity3: %s", intent);
return InstrumentationUtil.execStartActivity(original, who, contextThread, token, resultWho, intent, requestCode, options, user);
}

@Keep
public ActivityResult execStartActivityAsCaller(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options,
boolean ignoreTargetSecurity, int userId) {
LOGGER.d("execStartActivityAsCaller: %s", intent);
return InstrumentationUtil.execStartActivityAsCaller(original, who, contextThread, token, target, intent, requestCode, options, ignoreTargetSecurity, userId);
}

@Keep
public void execStartActivityFromAppTask(
Context who, IBinder contextThread, IAppTask appTask,
Intent intent, Bundle options) {
LOGGER.d("execStartActivityFromAppTask: %s", intent);
InstrumentationUtil.execStartActivityFromAppTask(original, who, contextThread, appTask, intent, options);
}
}
198 changes: 198 additions & 0 deletions module/src/main/java/rikka/sui/util/InstrumentationUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* This file is part of Sui.
*
* Sui is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sui is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Sui. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (c) 2022 Sui Contributors
*/

package rikka.sui.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.IAppTask;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;

import com.android.internal.content.ReferrerIntent;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@SuppressWarnings("JavaReflectionMemberAccess")
@SuppressLint({"SoonBlockedPrivateApi", "DiscouragedPrivateApi"})
public class InstrumentationUtil {

private static Method callActivityOnNewIntentMethod = null;
private static Method execStartActivityMethod = null;
private static Method execStartActivityMethod2 = null;
private static Method execStartActivityMethod3 = null;
private static Method execStartActivitiesMethod = null;
private static Method execStartActivitiesAsUserMethod = null;
private static Method execStartActivityAsCallerMethod = null;
private static Method execStartActivityFromAppTaskMethod = null;

public static void callActivityOnNewIntent(Instrumentation instrumentation, Activity activity, ReferrerIntent intent) {
if (callActivityOnNewIntentMethod == null) {
try {
callActivityOnNewIntentMethod = Instrumentation.class.getDeclaredMethod("callActivityOnNewIntent", Activity.class, ReferrerIntent.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (callActivityOnNewIntentMethod != null) {
try {
callActivityOnNewIntentMethod.invoke(instrumentation, intent, activity, intent);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}

public static Instrumentation.ActivityResult execStartActivity(Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
if (execStartActivityMethod == null) {
try {
execStartActivityMethod = Instrumentation.class.getDeclaredMethod("execStartActivity", Context.class, IBinder.class, IBinder.class, Activity.class, Intent.class, int.class, Bundle.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivityMethod != null) {
try {
return (Instrumentation.ActivityResult) execStartActivityMethod.invoke(instrumentation, who, contextThread, token, target, intent, requestCode, options);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}

public static Instrumentation.ActivityResult execStartActivity(
Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
if (execStartActivityMethod2 == null) {
try {
execStartActivityMethod2 = Instrumentation.class.getDeclaredMethod("execStartActivity",
Context.class, IBinder.class, IBinder.class, String.class, Intent.class, int.class, Bundle.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivityMethod2 != null) {
try {
return (Instrumentation.ActivityResult) execStartActivityMethod2.invoke(instrumentation, who, contextThread, token, target, intent, requestCode, options);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}

public static Instrumentation.ActivityResult execStartActivity(
Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user) {
if (execStartActivityMethod3 == null) {
try {
execStartActivityMethod3 = Instrumentation.class.getDeclaredMethod("execStartActivity",
Context.class, IBinder.class, IBinder.class, String.class, Intent.class, int.class, Bundle.class, UserHandle.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivityMethod3 != null) {
try {
return (Instrumentation.ActivityResult) execStartActivityMethod3.invoke(instrumentation, who, contextThread, token, resultWho, intent, requestCode, options, user);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}

public static void execStartActivities(Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options) {
if (execStartActivitiesMethod == null) {
try {
execStartActivitiesMethod = Instrumentation.class.getDeclaredMethod("execStartActivities", Context.class, IBinder.class, IBinder.class, Activity.class, Intent[].class, Bundle.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivitiesMethod != null) {
try {
execStartActivitiesMethod.invoke(instrumentation, who, contextThread, token, target, intents, options);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}

public static int execStartActivitiesAsUser(Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId) {
if (execStartActivitiesAsUserMethod == null) {
try {
execStartActivitiesAsUserMethod = Instrumentation.class.getDeclaredMethod("execStartActivitiesAsUser", Context.class, IBinder.class, IBinder.class, Activity.class, Intent[].class, Bundle.class, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivitiesAsUserMethod != null) {
try {
//noinspection ConstantConditions
return (int) execStartActivitiesAsUserMethod.invoke(instrumentation, who, contextThread, token, target, intents, options, userId);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return 0;
}

public static Instrumentation.ActivityResult execStartActivityAsCaller(
Instrumentation instrumentation, Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity, int userId) {
if (execStartActivityAsCallerMethod == null) {
try {
execStartActivityAsCallerMethod = Instrumentation.class.getDeclaredMethod("execStartActivityAsCaller",
Context.class, IBinder.class, IBinder.class, Activity.class, Intent.class, int.class, Bundle.class, boolean.class, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivityAsCallerMethod != null) {
try {
return (Instrumentation.ActivityResult) execStartActivityAsCallerMethod.invoke(instrumentation, who, contextThread, token, target, intent, requestCode, options, ignoreTargetSecurity, userId);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}

public static void execStartActivityFromAppTask(Instrumentation original, Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options) {
if (execStartActivityFromAppTaskMethod == null) {
try {
execStartActivityFromAppTaskMethod = Instrumentation.class.getDeclaredMethod("execStartActivityFromAppTask", Context.class, IBinder.class, IAppTask.class, Intent.class, Bundle.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (execStartActivityFromAppTaskMethod != null) {
try {
execStartActivityFromAppTaskMethod.invoke(original, who, contextThread, appTask, intent, options);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}

0 comments on commit 6e50253

Please sign in to comment.