Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.os.IBinder;
import android.util.MergedConfiguration;
import android.view.DisplayAdjustments;
import android.window.SplashScreenViewParcelable;

import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -202,4 +203,42 @@ public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord

/** Deliver new intent. */
public abstract void handleNewIntent(IBinder token, List intents);
}

/**
* Get {@link ActivityClientRecord} that is preparing to be launched.
* @param token Activity token.
* @return An initialized instance of {@link ActivityClientRecord} to use during launch.
*/
public abstract ActivityThread.ActivityClientRecord getLaunchingActivity(IBinder token);

/**
* Remove {@link ActivityClientRecord} from the launching activity list.
* @param token Activity token.
* */
public abstract void removeLaunchingActivity(IBinder token);

/** Whether the activity want to handle splash screen exit animation */
public abstract boolean isHandleSplashScreenExit(IBinder token);

/** Hand over the splash screen window view to the activity */
public abstract void handOverSplashScreenView(ActivityThread.ActivityClientRecord r);

/** Attach a splash screen window view to the top of the activity */
public abstract void handleAttachSplashScreenView(ActivityThread.ActivityClientRecord r, SplashScreenViewParcelable parcelable);

public abstract void handlePictureInPictureStateChanged(ActivityThread.ActivityClientRecord r, PictureInPictureUiState pipState);

/** Pause the activity. */
public abstract void handlePauseActivity(ActivityThread.ActivityClientRecord r, boolean finished,
boolean userLeaving, int configChanges, PendingTransactionActions pendingActions,
String reason);

/** Deliver result from another activity. */
public abstract void handleSendResult(ActivityThread.ActivityClientRecord r, List<ResultInfo> results, String reason);

public abstract void handleStopActivity(ActivityThread.ActivityClientRecord r, int configChanges, PendingTransactionActions pendingActions, boolean finalStateRequest, String reason);
public abstract void handleDestroyActivity(ActivityThread.ActivityClientRecord r, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason);

/** Restart the activity after it was stopped. */
public abstract void performRestartActivity(ActivityThread.ActivityClientRecord r, boolean start);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package android.app;

import android.os.Parcel;
import android.os.Parcelable;

/**
* @author LittleAngry
* @date 2021/11/28.
*/
public class PictureInPictureUiState implements Parcelable {

protected PictureInPictureUiState(Parcel in) {
}

public static final Creator<PictureInPictureUiState> CREATOR = new Creator<PictureInPictureUiState>() {
@Override
public PictureInPictureUiState createFromParcel(Parcel in) {
return new PictureInPictureUiState(in);
}

@Override
public PictureInPictureUiState[] newArray(int size) {
return new PictureInPictureUiState[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel parcel, int i) {
}
}
35 changes: 35 additions & 0 deletions VirtualApp/lib/src/main/java/android/app/ResultInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package android.app;

import android.os.Parcel;
import android.os.Parcelable;

/**
* @author LittleAngry
* @date 2021/11/28.
*/

public class ResultInfo implements Parcelable {
protected ResultInfo(Parcel in) {
}

public static final Creator<ResultInfo> CREATOR = new Creator<ResultInfo>() {
@Override
public ResultInfo createFromParcel(Parcel in) {
return new ResultInfo(in);
}

@Override
public ResultInfo[] newArray(int size) {
return new ResultInfo[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel parcel, int i) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.util.Log;
import android.util.MergedConfiguration;
import android.view.DisplayAdjustments;
import android.window.SplashScreenViewParcelable;

import com.lody.virtual.client.VClientImpl;
import com.lody.virtual.client.core.VirtualCore;
Expand Down Expand Up @@ -271,4 +272,59 @@ public void countLaunchingActivities(int num) {
public void handleNewIntent(IBinder token, List intents) {
originalHandler.handleNewIntent(token, intents);
}

@Override
public ActivityClientRecord getLaunchingActivity(IBinder token) {
return originalHandler.getLaunchingActivity(token);
}

@Override
public void removeLaunchingActivity(IBinder token) {
originalHandler.removeLaunchingActivity(token);
}

@Override
public boolean isHandleSplashScreenExit(IBinder token) {
return originalHandler.isHandleSplashScreenExit(token);
}

@Override
public void handOverSplashScreenView(ActivityClientRecord r) {
originalHandler.handOverSplashScreenView(r);
}

@Override
public void handleAttachSplashScreenView(ActivityClientRecord r, SplashScreenViewParcelable parcelable) {
originalHandler.handleAttachSplashScreenView(r, parcelable);
}

@Override
public void handlePictureInPictureStateChanged(ActivityClientRecord r, PictureInPictureUiState pipState) {
originalHandler.handlePictureInPictureStateChanged(r, pipState);
}

@Override
public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) {
originalHandler.handlePauseActivity(r, finished, userLeaving, configChanges, pendingActions, reason);
}

@Override
public void handleSendResult(ActivityClientRecord r, List<ResultInfo> results, String reason) {
originalHandler.handleSendResult(r, results, reason);
}

@Override
public void handleStopActivity(ActivityClientRecord r, int configChanges, PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
originalHandler.handleStopActivity(r, configChanges, pendingActions, finalStateRequest, reason);
}

@Override
public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) {
originalHandler.handleDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
}

@Override
public void performRestartActivity(ActivityClientRecord r, boolean start) {
originalHandler.performRestartActivity(r, start);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package android.window;

import android.os.Parcel;
import android.os.Parcelable;

/**
* @author LittleAngry
* @date 2021/11/28.
*/
public class SplashScreenViewParcelable implements Parcelable {

protected SplashScreenViewParcelable(Parcel in) {
}

public static final Creator<SplashScreenViewParcelable> CREATOR = new Creator<SplashScreenViewParcelable>() {
@Override
public SplashScreenViewParcelable createFromParcel(Parcel in) {
return new SplashScreenViewParcelable(in);
}

@Override
public SplashScreenViewParcelable[] newArray(int size) {
return new SplashScreenViewParcelable[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel parcel, int i) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public final class VirtualCore {
private ComponentDelegate componentDelegate;
private TaskDescriptionDelegate taskDescriptionDelegate;

public String obbDir;


private VirtualCore() {
}

Expand Down Expand Up @@ -185,6 +188,7 @@ public void startup(Context context) throws Throwable {
throw new IllegalStateException("VirtualCore.startup() must called in main thread.");
}
Reflection.unseal(context);
obbDir = context.getObbDir().toString();

VASettings.STUB_CP_AUTHORITY = context.getPackageName() + "." + VASettings.STUB_DEF_AUTHORITY;
ServiceManagerNative.SERVICE_CP_AUTH = context.getPackageName() + "." + ServiceManagerNative.SERVICE_DEF_AUTH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.os.IInterface;
import android.os.ParcelFileDescriptor;

import com.lody.virtual.client.core.VirtualCore;
import com.lody.virtual.client.hook.base.MethodBox;
import com.lody.virtual.helper.compat.BuildCompat;
import com.lody.virtual.helper.utils.VLog;
Expand All @@ -21,6 +22,8 @@
import java.util.HashMap;
import java.util.Map;

import mirror.android.content.AttributionSource;
import mirror.android.content.AttributionSourceState;
import mirror.android.content.IContentProvider;

/**
Expand Down Expand Up @@ -144,6 +147,11 @@ public AssetFileDescriptor openAssetFile(MethodBox methodBox, Uri url, String mo
return (AssetFileDescriptor) methodBox.call();
}

public void fixAttributionSource(Object attributionSource) {
AttributionSourceState.packageName.set(AttributionSource.mAttributionSourceState.get(attributionSource), VirtualCore.get().getContext().getPackageName());
AttributionSourceState.uid.set(AttributionSource.mAttributionSourceState.get(attributionSource), VirtualCore.get().myUid());
}

@Override
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
try {
Expand All @@ -158,7 +166,12 @@ public Object invoke(Object proxy, Method method, Object... args) throws Throwab
try {
String name = method.getName();
if ("call".equals(name)) {
if (BuildCompat.isR()) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

if (Build.VERSION.SDK_INT >= 31) {
start = 2;
} else if (BuildCompat.isR()) {
start = 3;
} else if (BuildCompat.isQ()) {
start = 2;
Expand All @@ -168,35 +181,58 @@ public Object invoke(Object proxy, Method method, Object... args) throws Throwab
Bundle extras = (Bundle) args[start + 2];
return call(methodBox, methodName, arg, extras);
} else if ("insert".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
ContentValues initialValues = (ContentValues) args[start + 1];
return insert(methodBox, url, initialValues);
} else if ("getType".equals(name)) {
return getType(methodBox, (Uri) args[0]);
} else if ("delete".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
String selection = (String) args[start + 1];
String[] selectionArgs = (String[]) args[start + 2];
return delete(methodBox, url, selection, selectionArgs);
} else if ("bulkInsert".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
ContentValues[] initialValues = (ContentValues[]) args[start + 1];
return bulkInsert(methodBox, url, initialValues);
} else if ("update".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
ContentValues values = (ContentValues) args[start + 1];
String selection = (String) args[start + 2];
String[] selectionArgs = (String[]) args[start + 3];
return update(methodBox, url, values, selection, selectionArgs);
} else if ("openFile".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
String mode = (String) args[start + 1];
return openFile(methodBox, url, mode);
} else if ("openAssetFile".equals(name)) {
if(Build.VERSION.SDK_INT >= 31)
fixAttributionSource(args[0]);

Uri url = (Uri) args[start];
String mode = (String) args[start + 1];
return openAssetFile(methodBox, url, mode);
} else if ("query".equals(name)) {
if(Build.VERSION.SDK_INT >= 31) {
fixAttributionSource(args[0]);
start--;
}

Uri url = (Uri) args[start];
String[] projection = (String[]) args[start + 1];
String selection = null;
Expand Down
Loading