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