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