1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.sdksandbox; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.os.Binder; 23 import android.os.IBinder; 24 import android.os.Process; 25 import android.os.UserHandle; 26 27 import java.util.Objects; 28 29 /** 30 * Representation of a caller for an SDK sandbox. 31 * @hide 32 */ 33 public final class CallingInfo { 34 35 private final int mUid; 36 private final String mPackageName; 37 private final @Nullable IBinder mAppProcessToken; 38 private boolean mIsCallFromSdkSandbox; 39 enforceCallingPackageBelongsToUid( Context context, int uid, String packageName)40 private static void enforceCallingPackageBelongsToUid( 41 Context context, int uid, String packageName) { 42 int packageUid; 43 PackageManager pm = 44 context.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0) 45 .getPackageManager(); 46 try { 47 packageUid = pm.getPackageUid(packageName, 0); 48 } catch (PackageManager.NameNotFoundException e) { 49 throw new SecurityException(packageName + " not found"); 50 } 51 if (packageUid != uid) { 52 throw new SecurityException(packageName + " does not belong to uid " + uid); 53 } 54 } 55 CallingInfo(int uid, String packageName, @Nullable IBinder processTokenBinder)56 public CallingInfo(int uid, String packageName, @Nullable IBinder processTokenBinder) { 57 mUid = uid; 58 mPackageName = Objects.requireNonNull(packageName); 59 mAppProcessToken = processTokenBinder; 60 mIsCallFromSdkSandbox = Process.isSdkSandboxUid(mUid); 61 } 62 CallingInfo(int uid, String packageName)63 public CallingInfo(int uid, String packageName) { 64 this(uid, packageName, null); 65 } 66 fromExternal(Context context, int uid, String packageNameUnchecked)67 static CallingInfo fromExternal(Context context, int uid, String packageNameUnchecked) { 68 enforceCallingPackageBelongsToUid(context, uid, packageNameUnchecked); 69 CallingInfo callingInfo = new CallingInfo(uid, packageNameUnchecked); 70 callingInfo.mIsCallFromSdkSandbox = true; 71 return callingInfo; 72 } 73 fromBinder(Context context, String packageNameUnchecked)74 static CallingInfo fromBinder(Context context, String packageNameUnchecked) { 75 return fromBinderWithApplicationThread(context, packageNameUnchecked, null); 76 } 77 fromBinderWithApplicationThread( Context context, String packageNameUnchecked, @Nullable IBinder callingApplicationThread)78 static CallingInfo fromBinderWithApplicationThread( 79 Context context, 80 String packageNameUnchecked, 81 @Nullable IBinder callingApplicationThread) { 82 final int uid = Binder.getCallingUid(); 83 enforceCallingPackageBelongsToUid(context, uid, packageNameUnchecked); 84 85 return new CallingInfo(uid, packageNameUnchecked, callingApplicationThread); 86 } 87 getUid()88 public int getUid() { 89 return mUid; 90 } 91 getAppProcessToken()92 public @Nullable IBinder getAppProcessToken() { 93 return mAppProcessToken; 94 } 95 getPackageName()96 public String getPackageName() { 97 return mPackageName; 98 } 99 isCallFromSdkSandbox()100 public boolean isCallFromSdkSandbox() { 101 return mIsCallFromSdkSandbox; 102 } 103 104 @Override toString()105 public String toString() { 106 return "CallingInfo{" 107 + "mUid=" 108 + mUid 109 + ", mPackageName='" 110 + mPackageName 111 + ", mAppProcessToken='" 112 + mAppProcessToken 113 + "'}"; 114 } 115 116 @Override equals(Object o)117 public boolean equals(Object o) { 118 // Note that mApplicationThread is not part of the comparison, because it is not always set, 119 // nor is it necessary to determine whether two instances refer to the same caller. 120 if (this == o) return true; 121 if (!(o instanceof CallingInfo)) return false; 122 CallingInfo that = (CallingInfo) o; 123 return mUid == that.mUid && mPackageName.equals(that.mPackageName); 124 } 125 126 @Override hashCode()127 public int hashCode() { 128 return mUid ^ mPackageName.hashCode(); 129 } 130 } 131