/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.IBinder; import android.os.Process; import java.util.Objects; /** * Represents the app that launched the component. See below for the APIs available on the component * caller. * *

Note, that in {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} only * {@link Activity} has access to {@link ComponentCaller} instances. * * @see Activity#getInitialCaller() */ @FlaggedApi(android.security.Flags.FLAG_CONTENT_URI_PERMISSION_APIS) public final class ComponentCaller { private final IBinder mActivityToken; private final IBinder mCallerToken; /** * @hide */ public ComponentCaller(@Nullable IBinder activityToken, @Nullable IBinder callerToken) { mActivityToken = activityToken; mCallerToken = callerToken; } /** * Returns the uid of this component caller. * *

Note, in {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} only * {@link Activity} has access to {@link ComponentCaller} instances. *

*

Requirements for {@link Activity} callers

* *

In order to receive the calling app's uid, at least one of the following has to be met: *

* These are the same requirements for {@link #getPackage()}; if any of these are met, then * these methods can be used to obtain the uid and package name of the calling app. If none are * met, then {@link Process#INVALID_UID} is returned. * *

Note, even if the above conditions are not met, the calling app's identity may still be * available from {@link Activity#getCallingPackage()} if this activity was started with * {@code Activity#startActivityForResult} to allow validation of the result's recipient. * * @return the uid of the calling app or {@link Process#INVALID_UID} if the current component * cannot access the identity of the calling app or the caller is invalid * * @see ActivityOptions#setShareIdentityEnabled(boolean) * @see Activity#getLaunchedFromUid() */ public int getUid() { return ActivityClient.getInstance().getActivityCallerUid(mActivityToken, mCallerToken); } /** * Returns the package name of this component caller. * *

Note, in {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} only * {@link Activity} has access to {@link ComponentCaller} instances. *

*

Requirements for {@link Activity} callers

* *

In order to receive the calling app's package name, at least one of the following has to * be met: *

* These are the same requirements for {@link #getUid()}; if any of these are met, then these * methods can be used to obtain the uid and package name of the calling app. If none are met, * then {@code null} is returned. * *

Note, even if the above conditions are not met, the calling app's identity may still be * available from {@link Activity#getCallingPackage()} if this activity was started with * {@code Activity#startActivityForResult} to allow validation of the result's recipient. * * @return the package name of the calling app or null if the current component cannot access * the identity of the calling app or the caller is invalid * * @see ActivityOptions#setShareIdentityEnabled(boolean) * @see Activity#getLaunchedFromPackage() */ @Nullable public String getPackage() { return ActivityClient.getInstance().getActivityCallerPackage(mActivityToken, mCallerToken); } /** * Determines whether this component caller had access to a specific content URI at launch time. * Apps can use this API to validate content URIs coming from other apps. * *

Note, in {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} only * {@link Activity} has access to {@link ComponentCaller} instances. * *

Before using this method, note the following: *

* * @param uri The content uri that is being checked * @param modeFlags The access modes to check * @return {@link PackageManager#PERMISSION_GRANTED} if this activity caller is allowed to * access that uri, or {@link PackageManager#PERMISSION_DENIED} if it is not * @throws IllegalArgumentException if uri is a non-content URI or it wasn't passed at launch in * {@link Intent#getData()}, {@link Intent#EXTRA_STREAM}, and * {@link Intent#getClipData()} * @throws SecurityException if you don't have access to uri * * @see android.content.Context#checkContentUriPermissionFull(Uri, int, int, int) */ @PackageManager.PermissionResult public int checkContentUriPermission(@NonNull Uri uri, @Intent.AccessUriMode int modeFlags) { return ActivityClient.getInstance().checkActivityCallerContentUriPermission(mActivityToken, mCallerToken, uri, modeFlags); } @Override public boolean equals(@Nullable Object obj) { if (obj == null || !(obj instanceof ComponentCaller other)) { return false; } return this.mActivityToken == other.mActivityToken && this.mCallerToken == other.mCallerToken; } @Override public int hashCode() { int result = 17; result = 31 * result + Objects.hashCode(mActivityToken); result = 31 * result + Objects.hashCode(mCallerToken); return result; } }