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