blob: 6e602d59c42131622bdf51939fca3d294aa2b575 [file] [log] [blame]
Jason Monkbf3eedc2018-04-05 20:56:42 -04001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.server.slice;
16
17import android.annotation.NonNull;
18import android.util.ArrayMap;
19import android.util.ArraySet;
20import android.util.Slog;
21
22import com.android.server.slice.DirtyTracker.Persistable;
23import com.android.server.slice.SlicePermissionManager.PkgUser;
24
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27import org.xmlpull.v1.XmlSerializer;
28
29import java.io.IOException;
30import java.util.ArrayList;
31import java.util.Collection;
32import java.util.Objects;
33
34public class SliceProviderPermissions implements DirtyTracker, Persistable {
35
36 private static final String TAG = "SliceProviderPermissions";
37
38 static final String TAG_PROVIDER = "provider";
39 private static final String TAG_AUTHORITY = "authority";
40 private static final String TAG_PKG = "pkg";
41 private static final String NAMESPACE = null;
42
43 private static final String ATTR_PKG = "pkg";
44 private static final String ATTR_AUTHORITY = "authority";
45
46 private final PkgUser mPkg;
47 private final ArrayMap<String, SliceAuthority> mAuths = new ArrayMap<>();
48 private final DirtyTracker mTracker;
49
50 public SliceProviderPermissions(@NonNull PkgUser pkg, @NonNull DirtyTracker tracker) {
51 mPkg = pkg;
52 mTracker = tracker;
53 }
54
55 public PkgUser getPkg() {
56 return mPkg;
57 }
58
59 public synchronized Collection<SliceAuthority> getAuthorities() {
60 return new ArrayList<>(mAuths.values());
61 }
62
63 public synchronized SliceAuthority getOrCreateAuthority(String authority) {
64 SliceAuthority ret = mAuths.get(authority);
65 if (ret == null) {
66 ret = new SliceAuthority(authority, this);
67 mAuths.put(authority, ret);
68 onPersistableDirty(ret);
69 }
70 return ret;
71 }
72
73 @Override
74 public void onPersistableDirty(Persistable obj) {
75 mTracker.onPersistableDirty(this);
76 }
77
78 @Override
79 public String getFileName() {
80 return getFileName(mPkg);
81 }
82
83 public synchronized void writeTo(XmlSerializer out) throws IOException {
84 out.startTag(NAMESPACE, TAG_PROVIDER);
85 out.attribute(NAMESPACE, ATTR_PKG, mPkg.toString());
86
87 final int N = mAuths.size();
88 for (int i = 0; i < N; i++) {
89 out.startTag(NAMESPACE, TAG_AUTHORITY);
90 out.attribute(NAMESPACE, ATTR_AUTHORITY, mAuths.valueAt(i).mAuthority);
91
92 mAuths.valueAt(i).writeTo(out);
93
94 out.endTag(NAMESPACE, TAG_AUTHORITY);
95 }
96
97 out.endTag(NAMESPACE, TAG_PROVIDER);
98 }
99
100 public static SliceProviderPermissions createFrom(XmlPullParser parser, DirtyTracker tracker)
101 throws XmlPullParserException, IOException {
102 // Get to the beginning of the provider.
103 while (parser.getEventType() != XmlPullParser.START_TAG
104 || !TAG_PROVIDER.equals(parser.getName())) {
105 parser.next();
106 }
107 int depth = parser.getDepth();
108 PkgUser pkgUser = new PkgUser(parser.getAttributeValue(NAMESPACE, ATTR_PKG));
109 SliceProviderPermissions provider = new SliceProviderPermissions(pkgUser, tracker);
110 parser.next();
111
112 while (parser.getDepth() > depth) {
113 if (parser.getEventType() == XmlPullParser.START_TAG
114 && TAG_AUTHORITY.equals(parser.getName())) {
115 try {
116 SliceAuthority authority = new SliceAuthority(
117 parser.getAttributeValue(NAMESPACE, ATTR_AUTHORITY), provider);
118 authority.readFrom(parser);
119 provider.mAuths.put(authority.getAuthority(), authority);
120 } catch (IllegalArgumentException e) {
121 Slog.e(TAG, "Couldn't read PkgUser", e);
122 }
123 }
124
125 parser.next();
126 }
127 return provider;
128 }
129
130 public static String getFileName(PkgUser pkg) {
131 return String.format("provider_%s", pkg.toString());
132 }
133
134 public static class SliceAuthority implements Persistable {
135 private final String mAuthority;
136 private final DirtyTracker mTracker;
137 private final ArraySet<PkgUser> mPkgs = new ArraySet<>();
138
139 public SliceAuthority(String authority, DirtyTracker tracker) {
140 mAuthority = authority;
141 mTracker = tracker;
142 }
143
144 public String getAuthority() {
145 return mAuthority;
146 }
147
148 public synchronized void addPkg(PkgUser pkg) {
149 if (mPkgs.add(pkg)) {
150 mTracker.onPersistableDirty(this);
151 }
152 }
153
154 public synchronized void removePkg(PkgUser pkg) {
155 if (mPkgs.remove(pkg)) {
156 mTracker.onPersistableDirty(this);
157 }
158 }
159
160 public synchronized Collection<PkgUser> getPkgs() {
161 return new ArraySet<>(mPkgs);
162 }
163
164 @Override
165 public String getFileName() {
166 return null;
167 }
168
169 public synchronized void writeTo(XmlSerializer out) throws IOException {
170 final int N = mPkgs.size();
171 for (int i = 0; i < N; i++) {
172 out.startTag(NAMESPACE, TAG_PKG);
173 out.text(mPkgs.valueAt(i).toString());
174 out.endTag(NAMESPACE, TAG_PKG);
175 }
176 }
177
178 public synchronized void readFrom(XmlPullParser parser)
179 throws IOException, XmlPullParserException {
180 parser.next();
181 int depth = parser.getDepth();
182 while (parser.getDepth() >= depth) {
183 if (parser.getEventType() == XmlPullParser.START_TAG
184 && TAG_PKG.equals(parser.getName())) {
185 mPkgs.add(new PkgUser(parser.nextText()));
186 }
187 parser.next();
188 }
189 }
190
191 @Override
192 public boolean equals(Object obj) {
193 if (!getClass().equals(obj != null ? obj.getClass() : null)) return false;
194 SliceAuthority other = (SliceAuthority) obj;
195 return Objects.equals(mAuthority, other.mAuthority)
196 && Objects.equals(mPkgs, other.mPkgs);
197 }
198
199 @Override
200 public String toString() {
201 return String.format("(%s: %s)", mAuthority, mPkgs.toString());
202 }
203 }
204}