diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index e422d860772..33be28fdd84 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -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; @@ -466,20 +468,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; } @@ -529,6 +530,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(