Merge "Allow 2-pane deep link to access unexported Activity" into tm-qpr-dev am: e8e2d9c68f

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/20704230

Change-Id: Ic7b667e5d12c125769feabc0ac13f79eaafab771
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Arc Wang
2022-12-15 05:16:14 +00:00
committed by Automerger Merge Worker

View File

@@ -32,6 +32,8 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
@@ -448,20 +450,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements
return;
}
if (!TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()),
getPackageName())) {
ActivityInfo targetActivityInfo = null;
try {
targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName,
/* flags= */ 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to get target ActivityInfo: " + e);
finish();
return;
}
ActivityInfo targetActivityInfo = null;
try {
targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName,
/* flags= */ 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to get target ActivityInfo: " + e);
finish();
return;
}
if (!hasPrivilegedAccess(targetActivityInfo)) {
if (!targetActivityInfo.exported) {
Log.e(TAG, "Must not launch an unexported Actvity for deep link");
Log.e(TAG, "Target Activity is not exported");
finish();
return;
}
@@ -514,6 +515,46 @@ public class SettingsHomepageActivity extends FragmentActivity implements
}
}
// Check if calling app has privileged access to launch Activity of activityInfo.
private boolean hasPrivilegedAccess(ActivityInfo activityInfo) {
if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()),
getPackageName())) {
return true;
}
int callingUid = -1;
try {
callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken());
} catch (RemoteException re) {
Log.e(TAG, "Not able to get callingUid: " + re);
return false;
}
int targetUid = -1;
try {
targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName,
/* flags= */ 0).uid;
} catch (PackageManager.NameNotFoundException nnfe) {
Log.e(TAG, "Not able to get targetUid: " + nnfe);
return false;
}
// When activityInfo.exported is false, Activity still can be launched if applications have
// the same user ID.
if (UserHandle.isSameApp(callingUid, targetUid)) {
return true;
}
// When activityInfo.exported is false, Activity still can be launched if calling app has
// root or system privilege.
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID) {
return true;
}
return false;
}
@VisibleForTesting
boolean isCallingAppPermitted(String permission) {
return TextUtils.isEmpty(permission) || PasswordUtils.isCallingAppPermitted(