1 /* 2 * Copyright (C) 2017 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.job; 18 19 import android.app.IActivityManager; 20 import android.app.UriGrantsManager; 21 import android.content.ClipData; 22 import android.content.ContentProvider; 23 import android.content.Intent; 24 import android.net.Uri; 25 import android.os.IBinder; 26 import android.os.RemoteException; 27 import android.os.UserHandle; 28 import android.util.Slog; 29 import android.util.proto.ProtoOutputStream; 30 import com.android.server.LocalServices; 31 import com.android.server.uri.UriGrantsManagerInternal; 32 33 import java.io.PrintWriter; 34 import java.util.ArrayList; 35 36 public final class GrantedUriPermissions { 37 private final int mGrantFlags; 38 private final int mSourceUserId; 39 private final String mTag; 40 private final IBinder mPermissionOwner; 41 private final ArrayList<Uri> mUris = new ArrayList<>(); 42 GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag)43 private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag) 44 throws RemoteException { 45 mGrantFlags = grantFlags; 46 mSourceUserId = UserHandle.getUserId(uid); 47 mTag = tag; 48 mPermissionOwner = LocalServices 49 .getService(UriGrantsManagerInternal.class).newUriPermissionOwner("job: " + tag); 50 } 51 revoke(IActivityManager am)52 public void revoke(IActivityManager am) { 53 for (int i = mUris.size()-1; i >= 0; i--) { 54 LocalServices.getService(UriGrantsManagerInternal.class).revokeUriPermissionFromOwner( 55 mPermissionOwner, mUris.get(i), mGrantFlags, mSourceUserId); 56 } 57 mUris.clear(); 58 } 59 checkGrantFlags(int grantFlags)60 public static boolean checkGrantFlags(int grantFlags) { 61 return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION 62 |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0; 63 } 64 createFromIntent(IActivityManager am, Intent intent, int sourceUid, String targetPackage, int targetUserId, String tag)65 public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent, 66 int sourceUid, String targetPackage, int targetUserId, String tag) { 67 int grantFlags = intent.getFlags(); 68 if (!checkGrantFlags(grantFlags)) { 69 return null; 70 } 71 72 GrantedUriPermissions perms = null; 73 74 Uri data = intent.getData(); 75 if (data != null) { 76 perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag, 77 perms); 78 } 79 80 ClipData clip = intent.getClipData(); 81 if (clip != null) { 82 perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag, 83 perms); 84 } 85 86 return perms; 87 } 88 createFromClip(IActivityManager am, ClipData clip, int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag)89 public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip, 90 int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) { 91 if (!checkGrantFlags(grantFlags)) { 92 return null; 93 } 94 GrantedUriPermissions perms = null; 95 if (clip != null) { 96 perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, 97 tag, perms); 98 } 99 return perms; 100 } 101 grantClip(IActivityManager am, ClipData clip, int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, GrantedUriPermissions curPerms)102 private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip, 103 int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, 104 GrantedUriPermissions curPerms) { 105 final int N = clip.getItemCount(); 106 for (int i = 0; i < N; i++) { 107 curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId, 108 grantFlags, tag, curPerms); 109 } 110 return curPerms; 111 } 112 grantUri(IActivityManager am, Uri uri, int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, GrantedUriPermissions curPerms)113 private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri, 114 int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, 115 GrantedUriPermissions curPerms) { 116 try { 117 int sourceUserId = ContentProvider.getUserIdFromUri(uri, 118 UserHandle.getUserId(sourceUid)); 119 uri = ContentProvider.getUriWithoutUserId(uri); 120 if (curPerms == null) { 121 curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag); 122 } 123 UriGrantsManager.getService().grantUriPermissionFromOwner(curPerms.mPermissionOwner, 124 sourceUid, targetPackage, uri, grantFlags, sourceUserId, targetUserId); 125 curPerms.mUris.add(uri); 126 } catch (RemoteException e) { 127 Slog.e("JobScheduler", "AM dead"); 128 } 129 return curPerms; 130 } 131 grantItem(IActivityManager am, ClipData.Item item, int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, GrantedUriPermissions curPerms)132 private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item, 133 int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag, 134 GrantedUriPermissions curPerms) { 135 if (item.getUri() != null) { 136 curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId, 137 grantFlags, tag, curPerms); 138 } 139 Intent intent = item.getIntent(); 140 if (intent != null && intent.getData() != null) { 141 curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId, 142 grantFlags, tag, curPerms); 143 } 144 return curPerms; 145 } 146 147 // Dumpsys infrastructure dump(PrintWriter pw, String prefix)148 public void dump(PrintWriter pw, String prefix) { 149 pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags)); 150 pw.print(" mSourceUserId="); pw.println(mSourceUserId); 151 pw.print(prefix); pw.print("mTag="); pw.println(mTag); 152 pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner); 153 for (int i = 0; i < mUris.size(); i++) { 154 pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": "); 155 pw.println(mUris.get(i)); 156 } 157 } 158 dump(ProtoOutputStream proto, long fieldId)159 public void dump(ProtoOutputStream proto, long fieldId) { 160 final long token = proto.start(fieldId); 161 162 proto.write(GrantedUriPermissionsDumpProto.FLAGS, mGrantFlags); 163 proto.write(GrantedUriPermissionsDumpProto.SOURCE_USER_ID, mSourceUserId); 164 proto.write(GrantedUriPermissionsDumpProto.TAG, mTag); 165 proto.write(GrantedUriPermissionsDumpProto.PERMISSION_OWNER, mPermissionOwner.toString()); 166 for (int i = 0; i < mUris.size(); i++) { 167 Uri u = mUris.get(i); 168 if (u != null) { 169 proto.write(GrantedUriPermissionsDumpProto.URIS, u.toString()); 170 } 171 } 172 173 proto.end(token); 174 } 175 } 176