blob: 8fecb8faa9f49ca219e7dadeb20b8bbde4c488b7 [file] [log] [blame]
Dianne Hackborn342e6032017-04-13 18:04:31 -07001/*
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;
Kweku Adams85f2fbc2017-12-18 12:04:12 -080028import android.util.proto.ProtoOutputStream;
Dianne Hackborn342e6032017-04-13 18:04:31 -070029
30import java.io.PrintWriter;
31import java.util.ArrayList;
32
Dianne Hackborn6466c1c2017-06-13 10:33:19 -070033public final class GrantedUriPermissions {
Dianne Hackborn342e6032017-04-13 18:04:31 -070034 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 }
Kweku Adams85f2fbc2017-12-18 12:04:12 -0800157
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 }
Dianne Hackborn342e6032017-04-13 18:04:31 -0700174}