diff --git a/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java b/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java index 2d773f95..1260aa08 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java +++ b/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java @@ -19,6 +19,7 @@ package com.emanuelef.remote_capture; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -34,13 +35,18 @@ import com.emanuelef.remote_capture.model.AppDescriptor; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Arrays; public class AppsResolver { private static final String TAG = "AppsResolver"; + public static final int PER_USER_RANGE = 100000; private final SparseArray mApps; private final PackageManager mPm; private final Context mContext; + private Method getPackageInfoAsUser; + private boolean mFallbackToGlobalResolution; private Drawable mVirtualAppIcon; public AppsResolver(Context context) { @@ -102,6 +108,7 @@ public class AppsResolver { return new AppDescriptor(pm, pinfo); } + @SuppressLint("DiscouragedPrivateApi") public @Nullable AppDescriptor get(int uid, int pm_flags) { AppDescriptor app = mApps.get(uid); if(app != null) @@ -127,6 +134,22 @@ public class AppsResolver { Arrays.sort(packages); String packageName = packages[0]; + if(!mFallbackToGlobalResolution && CaptureService.isCapturingAsRoot()) { + // Try to resolve for the specific user + try { + if(getPackageInfoAsUser == null) + getPackageInfoAsUser = PackageManager.class.getDeclaredMethod("getPackageInfoAsUser", String.class, int.class, int.class); + + PackageInfo pinfo = (PackageInfo) getPackageInfoAsUser.invoke(mPm, packageName, pm_flags, uid / PER_USER_RANGE); + if(pinfo != null) + return new AppDescriptor(mPm, pinfo); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + Log.w(TAG, "getPackageInfoAsUser call fails, falling back to standard resolution"); + e.printStackTrace(); + mFallbackToGlobalResolution = true; + } + } + app = resolve(mPm, packageName, pm_flags); if(app != null) mApps.put(uid, app); diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java index ca96defa..ddd0772e 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java @@ -23,6 +23,8 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.UserHandle; import androidx.annotation.Nullable; @@ -89,6 +91,12 @@ public class AppDescriptor implements Comparable, Serializable { // NOTE: this call is expensive mIcon = mPackageInfo.applicationInfo.loadIcon(mPm); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + UserHandle handle = UserHandle.getUserHandleForUid(mUid); + mIcon = mPm.getUserBadgedIcon(mIcon, handle); + } + //Log.d("Icon size", mIcon.getIntrinsicWidth() + "x" + mIcon.getIntrinsicHeight()); return mIcon; diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/MatchList.java b/app/src/main/java/com/emanuelef/remote_capture/model/MatchList.java index 80215214..db122946 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/MatchList.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/MatchList.java @@ -153,6 +153,7 @@ public class MatchList { } if(tp == RuleType.APP) { + // TODO handle cross-users/profiles? AppDescriptor app = AppsResolver.resolve(ctx.getPackageManager(), value, 0); if(app != null) value = app.getName();