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.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 java.io.PrintWriter; 31 import java.util.ArrayList; 32 33 public final class GrantedUriPermissions { 34 private final int mGrantFlags; 35 private final int mSourceUserId; 36 private final String mTag; 37 private final IBinder mPermissionOwner; 38 private final ArrayList<Uri> mUris = new ArrayList<>(); 39 40 private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag) 41 throws RemoteException { 42 mGrantFlags = grantFlags; 43 mSourceUserId = UserHandle.getUserId(uid); 44 mTag = tag; 45 mPermissionOwner = am.newUriPermissionOwner("job: " + tag); 46 } 47 48 public void revoke(IActivityManager am) { 49 for (int i = mUris.size()-1; i >= 0; i--) { 50 try { 51 am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i), 52 mGrantFlags, mSourceUserId); 53 } catch (RemoteException e) { 54 } 55 } 56 mUris.clear(); 57 } 58 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 64 public static GrantedUriPermissions createFromIntent(IActivityManager am, 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(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag, 76 perms); 77 } 78 79 ClipData clip = intent.getClipData(); 80 if (clip != null) { 81 perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag, 82 perms); 83 } 84 85 return perms; 86 } 87 88 public static GrantedUriPermissions createFromClip(IActivityManager am, 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(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, 96 tag, perms); 97 } 98 return perms; 99 } 100 101 private static GrantedUriPermissions grantClip(IActivityManager am, 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(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId, 107 grantFlags, tag, curPerms); 108 } 109 return curPerms; 110 } 111 112 private static GrantedUriPermissions grantUri(IActivityManager am, 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(am, grantFlags, sourceUid, tag); 121 } 122 am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage, 123 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 131 private static GrantedUriPermissions grantItem(IActivityManager am, 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(am, 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(am, intent.getData(), sourceUid, targetPackage, targetUserId, 141 grantFlags, tag, curPerms); 142 } 143 return curPerms; 144 } 145 146 // Dumpsys infrastructure 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 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