1 /* 2 * Copyright (C) 2018 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.uri; 18 19 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; 20 import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 21 22 import android.os.Binder; 23 import android.os.IBinder; 24 import android.os.UserHandle; 25 import android.util.ArraySet; 26 import android.util.proto.ProtoOutputStream; 27 28 import com.android.server.am.UriPermissionOwnerProto; 29 30 import com.google.android.collect.Sets; 31 32 import java.io.PrintWriter; 33 import java.util.Iterator; 34 35 public class UriPermissionOwner { 36 private final UriGrantsManagerInternal mService; 37 private final Object mOwner; 38 39 private Binder externalToken; 40 41 private ArraySet<UriPermission> mReadPerms; 42 private ArraySet<UriPermission> mWritePerms; 43 44 class ExternalToken extends Binder { getOwner()45 UriPermissionOwner getOwner() { 46 return UriPermissionOwner.this; 47 } 48 } 49 UriPermissionOwner(UriGrantsManagerInternal service, Object owner)50 public UriPermissionOwner(UriGrantsManagerInternal service, Object owner) { 51 mService = service; 52 mOwner = owner; 53 } 54 getExternalToken()55 public Binder getExternalToken() { 56 if (externalToken == null) { 57 externalToken = new ExternalToken(); 58 } 59 return externalToken; 60 } 61 fromExternalToken(IBinder token)62 static UriPermissionOwner fromExternalToken(IBinder token) { 63 if (token instanceof ExternalToken) { 64 return ((ExternalToken)token).getOwner(); 65 } 66 return null; 67 } 68 removeUriPermissions()69 public void removeUriPermissions() { 70 removeUriPermissions(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION); 71 } 72 removeUriPermissions(int mode)73 void removeUriPermissions(int mode) { 74 removeUriPermission(null, mode); 75 } 76 removeUriPermission(GrantUri grantUri, int mode)77 void removeUriPermission(GrantUri grantUri, int mode) { 78 removeUriPermission(grantUri, mode, null, UserHandle.USER_ALL); 79 } 80 removeUriPermission(GrantUri grantUri, int mode, String targetPgk, int targetUserId)81 void removeUriPermission(GrantUri grantUri, int mode, String targetPgk, int targetUserId) { 82 if ((mode & FLAG_GRANT_READ_URI_PERMISSION) != 0 && mReadPerms != null) { 83 Iterator<UriPermission> it = mReadPerms.iterator(); 84 while (it.hasNext()) { 85 UriPermission perm = it.next(); 86 if (grantUri != null && !grantUri.equals(perm.uri)) { 87 continue; 88 } 89 if (targetPgk != null && !targetPgk.equals(perm.targetPkg)) { 90 continue; 91 } 92 if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) { 93 continue; 94 } 95 perm.removeReadOwner(this); 96 mService.removeUriPermissionIfNeeded(perm); 97 it.remove(); 98 } 99 if (mReadPerms.isEmpty()) { 100 mReadPerms = null; 101 } 102 } 103 if ((mode & FLAG_GRANT_WRITE_URI_PERMISSION) != 0 && mWritePerms != null) { 104 Iterator<UriPermission> it = mWritePerms.iterator(); 105 while (it.hasNext()) { 106 UriPermission perm = it.next(); 107 if (grantUri != null && !grantUri.equals(perm.uri)) { 108 continue; 109 } 110 if (targetPgk != null && !targetPgk.equals(perm.targetPkg)) { 111 continue; 112 } 113 if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) { 114 continue; 115 } 116 perm.removeWriteOwner(this); 117 mService.removeUriPermissionIfNeeded(perm); 118 it.remove(); 119 } 120 if (mWritePerms.isEmpty()) { 121 mWritePerms = null; 122 } 123 } 124 } 125 addReadPermission(UriPermission perm)126 public void addReadPermission(UriPermission perm) { 127 if (mReadPerms == null) { 128 mReadPerms = Sets.newArraySet(); 129 } 130 mReadPerms.add(perm); 131 } 132 addWritePermission(UriPermission perm)133 public void addWritePermission(UriPermission perm) { 134 if (mWritePerms == null) { 135 mWritePerms = Sets.newArraySet(); 136 } 137 mWritePerms.add(perm); 138 } 139 removeReadPermission(UriPermission perm)140 public void removeReadPermission(UriPermission perm) { 141 mReadPerms.remove(perm); 142 if (mReadPerms.isEmpty()) { 143 mReadPerms = null; 144 } 145 } 146 removeWritePermission(UriPermission perm)147 public void removeWritePermission(UriPermission perm) { 148 mWritePerms.remove(perm); 149 if (mWritePerms.isEmpty()) { 150 mWritePerms = null; 151 } 152 } 153 dump(PrintWriter pw, String prefix)154 public void dump(PrintWriter pw, String prefix) { 155 if (mReadPerms != null) { 156 pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms); 157 } 158 if (mWritePerms != null) { 159 pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms); 160 } 161 } 162 dumpDebug(ProtoOutputStream proto, long fieldId)163 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 164 long token = proto.start(fieldId); 165 proto.write(UriPermissionOwnerProto.OWNER, mOwner.toString()); 166 if (mReadPerms != null) { 167 synchronized (mReadPerms) { 168 for (UriPermission p : mReadPerms) { 169 p.uri.dumpDebug(proto, UriPermissionOwnerProto.READ_PERMS); 170 } 171 } 172 } 173 if (mWritePerms != null) { 174 synchronized (mWritePerms) { 175 for (UriPermission p : mWritePerms) { 176 p.uri.dumpDebug(proto, UriPermissionOwnerProto.WRITE_PERMS); 177 } 178 } 179 } 180 proto.end(token); 181 } 182 183 @Override toString()184 public String toString() { 185 return mOwner.toString(); 186 } 187 } 188