Skip to content

Commit

Permalink
select and add hook plugin manually
Browse files Browse the repository at this point in the history
  • Loading branch information
rk700 committed Jul 19, 2017
1 parent ad36757 commit a95ba51
Show file tree
Hide file tree
Showing 54 changed files with 293 additions and 669 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,24 @@ Import and build the project in Android Studio(__with Instant Run disabled__). T
- `YAHFA`. This is the YAHFA hook module.
- `demoHookPlugin`. This is a demo hook plugin which compiles to an APK.

After building the APKs, push the `demoHookPlugin` APK to device in folder `/sdcard/io.virtualhook/` and run the main application. All plugin APKs in `/sdcard/io.virtualhook` would be applied to applications running in VirtualHook.
## Usage

- Write and build a hook plugin APK. You can take a look at the [demoHookPlugin](https://github.com/rk700/VirtualHook/tree/master/VirtualApp/app/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.png) module for reference. __Don't forget to put following meta-data in AndroidManifest.xml:__

```xml
<application
android:label="@string/app_name">
<meta-data
android:name="yahfa.hook.plugin"
android:value="true"
/>
</application>
```

Please refer to [demoHookPlugin](https://github.com/rk700/VirtualHook/tree/master/VirtualApp/demoHookPlugin) for more details.
- Push the plugin APK to sdcard
- Run VirtualHook and click the `Add` button
- Swipe to the 'APPS IN SDCARD' page. Then select and add hook plugins which are displayed with an icon ![](VirtualApp/app/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.png)
- Add and run non-plugin apps

## Hooking Native Methods

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder cu
AppData data = mLaunchpadAdapter.getList().get(target.getAdapterPosition());
return data.canReorder();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
// e.printStackTrace();
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class AddResult {
VUiKit.defer().when(() -> {
InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(info.packageName, 0);
addResult.justEnableHidden = installedAppInfo != null;
if (addResult.justEnableHidden) {
if (addResult.justEnableHidden && !info.isHook) {
int[] userIds = installedAppInfo.getInstalledUsers();
int nextUserId = userIds.length;
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public boolean isSelectable(int position) {
ArrayList<AppInfoLite> dataList = new ArrayList<AppInfoLite>(selectedIndices.length);
for (int index : selectedIndices) {
AppInfo info = mAdapter.getItem(index);
dataList.add(new AppInfoLite(info.packageName, info.path, info.fastOpen));
dataList.add(new AppInfoLite(info.packageName, info.path, info.fastOpen, info.isHook));
}
Intent data = new Intent();
data.putParcelableArrayListExtra(VCommends.EXTRA_APP_INFO_LIST, dataList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ public AppPagerAdapter(FragmentManager fm) {
File dir = Reflect.on(volume).call("getPathFile").get();
String label = Reflect.on(volume).call("getUserLabel").get();
if (dir.listFiles() != null) {
titles.add(label);
titles.add("Apps in "+label);
dirs.add(dir);
}
}
} else {
// Fallback: only support the default storage sources
File storageFir = Environment.getExternalStorageDirectory();
if (storageFir.list() != null) {
titles.add("Ghost Installation");
titles.add("Apps in sdcard");
dirs.add(storageFir);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public void onBindViewHolder(ViewHolder holder, int position) {
} else {
holder.labelView.setVisibility(View.INVISIBLE);
}
if(info.isHook) {
holder.isHookIcon.setVisibility(View.VISIBLE);
}
else {
holder.isHookIcon.setVisibility(View.INVISIBLE);
}

holder.itemView.setOnClickListener(v -> {
mItemEventListener.onItemClick(info, position);
Expand Down Expand Up @@ -127,6 +133,7 @@ class ViewHolder extends RecyclerView.ViewHolder {
private TextView nameView;
private ImageView appCheckView;
private LabelView labelView;
ImageView isHookIcon;

ViewHolder(View itemView) {
super(itemView);
Expand All @@ -135,6 +142,7 @@ class ViewHolder extends RecyclerView.ViewHolder {
nameView = (TextView) itemView.findViewById(R.id.item_app_name);
appCheckView = (ImageView) itemView.findViewById(R.id.item_app_checked);
labelView = (LabelView) itemView.findViewById(R.id.item_app_clone_count);
isHookIcon = (ImageView)itemView.findViewById(R.id.item_app_ishook);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
Expand Down Expand Up @@ -59,11 +60,18 @@ public void onBindViewHolder(ViewHolder holder, int position) {
holder.color = getColor(position);
holder.iconView.setImageDrawable(data.getIcon());
holder.nameView.setText(data.getName());
if (data.isFirstOpen() && !data.isLoading()) {
holder.firstOpenDot.setVisibility(View.VISIBLE);
} else {
holder.firstOpenDot.setVisibility(View.INVISIBLE);
if(!data.isHook()) {
if (data.isFirstOpen() && !data.isLoading()) {
holder.firstOpenDot.setVisibility(View.VISIBLE);
} else {
holder.firstOpenDot.setVisibility(View.INVISIBLE);
}
holder.isHookIcon.setVisibility(View.INVISIBLE);
}
else{
holder.isHookIcon.setVisibility(View.VISIBLE);
}

holder.itemView.setBackgroundColor(holder.color);
holder.itemView.setOnClickListener(v -> {
if (mAppClickListener != null) {
Expand Down Expand Up @@ -172,13 +180,15 @@ public class ViewHolder extends RecyclerView.ViewHolder {
TextView nameView;
LabelView spaceLabelView;
View firstOpenDot;
ImageView isHookIcon;

ViewHolder(View itemView) {
super(itemView);
iconView = (LauncherIconView) itemView.findViewById(R.id.item_app_icon);
nameView = (TextView) itemView.findViewById(R.id.item_app_name);
iconView = (LauncherIconView) itemView.findViewById(R.id.item_app_icon_launcher);
nameView = (TextView) itemView.findViewById(R.id.item_app_name_launcher);
spaceLabelView = (LabelView) itemView.findViewById(R.id.item_app_space_idx);
firstOpenDot = itemView.findViewById(R.id.item_first_open_dot);
isHookIcon = (ImageView)itemView.findViewById(R.id.item_app_ishook_launcher);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Drawable getIcon() {

@Override
public String getName() {
return "Add App";
return "Add";
}

@Override
Expand All @@ -56,4 +56,9 @@ public boolean canDelete() {
public boolean canCreateShortcut() {
return false;
}

@Override
public boolean isHook() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ public interface AppData {
boolean canDelete();

boolean canCreateShortcut();

boolean isHook();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public class AppInfo {
public Drawable icon;
public CharSequence name;
public int cloneCount;
public boolean isHook;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@ public AppInfoLite[] newArray(int size) {
public String packageName;
public String path;
public boolean fastOpen;
public boolean isHook;

public AppInfoLite(String packageName, String path, boolean fastOpen) {
public AppInfoLite(String packageName, String path, boolean fastOpen, boolean isHook) {
this.packageName = packageName;
this.path = path;
this.fastOpen = fastOpen;
this.isHook = isHook;
}

protected AppInfoLite(Parcel in) {
this.packageName = in.readString();
this.path = in.readString();
this.fastOpen = in.readByte() != 0;
this.isHook = in.readByte() != 0;
}

@Override
Expand All @@ -46,5 +49,6 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.packageName);
dest.writeString(this.path);
dest.writeByte(this.fastOpen ? (byte) 1 : (byte) 0);
dest.writeByte(this.isHook ? (byte) 1 : (byte) 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@ public boolean canDelete() {
public boolean canCreateShortcut() {
return false;
}

@Override
public boolean isHook() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class MultiplePackageAppData implements AppData {
public boolean isLoading;
public Drawable icon;
public String name;
public boolean isHook;

public MultiplePackageAppData(PackageAppData target, int userId) {
this.userId = userId;
Expand All @@ -29,6 +30,7 @@ public MultiplePackageAppData(PackageAppData target, int userId) {
}
}
name = target.name;
isHook = target.isHook;
}

@Override
Expand Down Expand Up @@ -70,4 +72,9 @@ public boolean canDelete() {
public boolean canCreateShortcut() {
return true;
}

@Override
public boolean isHook() {
return isHook;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ public class PackageAppData implements AppData {
public boolean fastOpen;
public boolean isFirstOpen;
public boolean isLoading;
public boolean isHook;

public PackageAppData(Context context, InstalledAppInfo installedAppInfo) {
this.packageName = installedAppInfo.packageName;
this.isFirstOpen = !installedAppInfo.isLaunched(0);
this.isHook = installedAppInfo.isHook;
loadData(context, installedAppInfo.getApplicationInfo(installedAppInfo.getInstalledUsers()[0]));
}

Expand Down Expand Up @@ -80,4 +82,9 @@ public boolean canDelete() {
public boolean canCreateShortcut() {
return true;
}

@Override
public boolean isHook() {
return isHook;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.lody.virtual.GmsSupport;
import com.lody.virtual.client.core.InstallStrategy;
import com.lody.virtual.client.core.VirtualCore;
import com.lody.virtual.helper.utils.VLog;
import com.lody.virtual.remote.InstallResult;
import com.lody.virtual.remote.InstalledAppInfo;

Expand Down Expand Up @@ -60,7 +61,7 @@ public Promise<List<AppData>, Throwable, Void> getVirtualApps() {
List<InstalledAppInfo> infos = VirtualCore.get().getInstalledApps(0);
List<AppData> models = new ArrayList<>();
for (InstalledAppInfo info : infos) {
if (!VirtualCore.get().isPackageLaunchable(info.packageName)) {
if (!info.isHook && !VirtualCore.get().isPackageLaunchable(info.packageName)) {
continue;
}
PackageAppData data = new PackageAppData(mContext, info);
Expand Down Expand Up @@ -101,7 +102,8 @@ private List<PackageInfo> findAndParseAPKs(Context context, File rootDir, List<S
continue;
PackageInfo pkgInfo = null;
try {
pkgInfo = context.getPackageManager().getPackageArchiveInfo(f.getAbsolutePath(), 0);
pkgInfo = context.getPackageManager().getPackageArchiveInfo(
f.getAbsolutePath(), PackageManager.GET_META_DATA);
pkgInfo.applicationInfo.sourceDir = f.getAbsolutePath();
pkgInfo.applicationInfo.publicSourceDir = f.getAbsolutePath();
} catch (Exception e) {
Expand All @@ -128,6 +130,10 @@ private List<AppInfo> convertPackageInfoToAppData(Context context, List<PackageI
continue;
}
ApplicationInfo ai = pkg.applicationInfo;
boolean isHookPlugin = false;
if(ai.metaData != null) {
isHookPlugin = ai.metaData.getBoolean("yahfa.hook.plugin", false);
}
String path = ai.publicSourceDir != null ? ai.publicSourceDir : ai.sourceDir;
if (path == null) {
continue;
Expand All @@ -138,9 +144,14 @@ private List<AppInfo> convertPackageInfoToAppData(Context context, List<PackageI
info.path = path;
info.icon = ai.loadIcon(pm);
info.name = ai.loadLabel(pm);
info.isHook = isHookPlugin;
InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(pkg.packageName, 0);
if (installedAppInfo != null) {
info.cloneCount = installedAppInfo.getInstalledUsers().length;
if (isHookPlugin) { // do not show hook plugin if already installed
continue;
} else {
info.cloneCount = installedAppInfo.getInstalledUsers().length;
}
}
list.add(info);
}
Expand All @@ -150,9 +161,12 @@ private List<AppInfo> convertPackageInfoToAppData(Context context, List<PackageI
@Override
public InstallResult addVirtualApp(AppInfoLite info) {
int flags = InstallStrategy.COMPARE_VERSION; // do not SKIP_DEX_OPT since we want the hooked app compiled
if (info.fastOpen) {
if (info.fastOpen && !info.isHook) {
flags |= InstallStrategy.DEPEND_SYSTEM_IF_EXIST;
}
if(info.isHook) {
flags |= InstallStrategy.IS_HOOK;
}
return VirtualCore.get().installPackage(info.path, flags);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ public boolean setDragSelectActive(boolean active, int initialSelection) {
/**
* Use {@link #setAdapter(DragSelectRecyclerViewAdapter)} instead.
*/
/*
@Override
@Deprecated
public void setAdapter(Adapter adapter) {
if (!(adapter instanceof DragSelectRecyclerViewAdapter<?>))
throw new IllegalArgumentException("Adapter must be a DragSelectRecyclerViewAdapter.");
setAdapter((DragSelectRecyclerViewAdapter<?>) adapter);
}
*/

public void setAdapter(DragSelectRecyclerViewAdapter<?> adapter) {
super.setAdapter(adapter);
Expand Down
Binary file removed VirtualApp/app/src/main/res/drawable-hdpi/ic_add.png
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit a95ba51

Please sign in to comment.