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