blob: 0aa54d910ea7161464a9b17d71d7127a5bcc996a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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.am;
18
19import android.content.Intent;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070020import android.os.UserHandle;
Jeff Sharkey846318a2014-04-04 12:12:41 -070021import android.util.ArraySet;
Jeff Sharkeyd16b1252016-09-01 11:07:23 -060022import android.util.Log;
Jeff Sharkey846318a2014-04-04 12:12:41 -070023import android.util.Slog;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070024
Jeff Sharkey846318a2014-04-04 12:12:41 -070025import com.android.server.am.ActivityManagerService.GrantUri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070026import com.google.android.collect.Sets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28import java.io.PrintWriter;
Jeff Sharkeye66c1772013-09-20 14:30:59 -070029import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Dianne Hackborn7e269642010-08-25 19:50:20 -070031/**
32 * Description of a permission granted to an app to access a particular URI.
33 *
34 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
35 *
Dianne Hackborncca1f0e2010-09-26 18:34:53 -070036 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
37 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
Dianne Hackborn7e269642010-08-25 19:50:20 -070038 */
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070039final class UriPermission {
Jeff Sharkey328ebf22013-03-21 18:09:39 -070040 private static final String TAG = "UriPermission";
41
Jeff Sharkeye66c1772013-09-20 14:30:59 -070042 public static final int STRENGTH_NONE = 0;
43 public static final int STRENGTH_OWNED = 1;
44 public static final int STRENGTH_GLOBAL = 2;
45 public static final int STRENGTH_PERSISTABLE = 3;
46
Nicolas Prevotd85fc722014-04-16 19:52:08 +010047 final int targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070048 final String sourcePkg;
49 final String targetPkg;
50
51 /** Cached UID of {@link #targetPkg}; should not be persisted */
52 final int targetUid;
53
Jeff Sharkey846318a2014-04-04 12:12:41 -070054 final GrantUri uri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070055
56 /**
57 * Allowed modes. All permission enforcement should use this field. Must
Jeff Sharkeye66c1772013-09-20 14:30:59 -070058 * always be a combination of {@link #ownedModeFlags},
59 * {@link #globalModeFlags}, {@link #persistableModeFlags}, and
60 * {@link #persistedModeFlags}. Mutations <em>must</em> only be performed by
61 * the owning class.
Jeff Sharkey328ebf22013-03-21 18:09:39 -070062 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 int modeFlags = 0;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070064
Jeff Sharkey846318a2014-04-04 12:12:41 -070065 /** Allowed modes with active owner. */
Jeff Sharkeye66c1772013-09-20 14:30:59 -070066 int ownedModeFlags = 0;
67 /** Allowed modes without explicit owner. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 int globalModeFlags = 0;
Jeff Sharkeye66c1772013-09-20 14:30:59 -070069 /** Allowed modes that have been offered for possible persisting. */
70 int persistableModeFlags = 0;
Jeff Sharkey846318a2014-04-04 12:12:41 -070071
Jeff Sharkeye66c1772013-09-20 14:30:59 -070072 /** Allowed modes that should be persisted across device boots. */
73 int persistedModeFlags = 0;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070074
75 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -070076 * Timestamp when {@link #persistedModeFlags} was first defined in
77 * {@link System#currentTimeMillis()} time base.
Jeff Sharkey328ebf22013-03-21 18:09:39 -070078 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -070079 long persistedCreateTime = INVALID_TIME;
80
81 private static final long INVALID_TIME = Long.MIN_VALUE;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070082
Jeff Sharkey846318a2014-04-04 12:12:41 -070083 private ArraySet<UriPermissionOwner> mReadOwners;
84 private ArraySet<UriPermissionOwner> mWriteOwners;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070085
86 private String stringName;
87
Jeff Sharkey846318a2014-04-04 12:12:41 -070088 UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
Nicolas Prevotd85fc722014-04-16 19:52:08 +010089 this.targetUserId = UserHandle.getUserId(targetUid);
Jeff Sharkey328ebf22013-03-21 18:09:39 -070090 this.sourcePkg = sourcePkg;
91 this.targetPkg = targetPkg;
92 this.targetUid = targetUid;
93 this.uri = uri;
94 }
95
Jeff Sharkeye66c1772013-09-20 14:30:59 -070096 private void updateModeFlags() {
Jeff Sharkeyd16b1252016-09-01 11:07:23 -060097 final int oldModeFlags = modeFlags;
Jeff Sharkeye66c1772013-09-20 14:30:59 -070098 modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
Jeff Sharkeyd16b1252016-09-01 11:07:23 -060099
100 if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) {
101 Slog.d(TAG,
102 "Permission for " + targetPkg + " to " + uri + " is changing from 0x"
103 + Integer.toHexString(oldModeFlags) + " to 0x"
104 + Integer.toHexString(modeFlags),
105 new Throwable());
106 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700107 }
108
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700109 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700110 * Initialize persisted modes as read from file. This doesn't issue any
111 * global or owner grants.
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700112 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700113 void initPersistedModes(int modeFlags, long createdTime) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700114 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
115 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
116
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700117 persistableModeFlags = modeFlags;
118 persistedModeFlags = modeFlags;
119 persistedCreateTime = createdTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700120
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700121 updateModeFlags();
122 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700123
Jeff Sharkey846318a2014-04-04 12:12:41 -0700124 void grantModes(int modeFlags, UriPermissionOwner owner) {
125 final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
126 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
127 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
128
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700129 if (persistable) {
130 persistableModeFlags |= modeFlags;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700131 }
132
133 if (owner == null) {
134 globalModeFlags |= modeFlags;
135 } else {
136 if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
137 addReadOwner(owner);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700138 }
139 if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
140 addWriteOwner(owner);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700141 }
142 }
143
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700144 updateModeFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700146
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700147 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700148 * @return if mode changes should trigger persisting.
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700149 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700150 boolean takePersistableModes(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700151 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
152 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
153
Jeff Sharkey582f7122013-10-11 17:46:47 -0700154 if ((modeFlags & persistableModeFlags) != modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700155 Slog.w(TAG, "Requested flags 0x"
Jeff Sharkey582f7122013-10-11 17:46:47 -0700156 + Integer.toHexString(modeFlags) + ", but only 0x"
157 + Integer.toHexString(persistableModeFlags) + " are allowed");
Jeff Sharkey846318a2014-04-04 12:12:41 -0700158 return false;
Jeff Sharkey582f7122013-10-11 17:46:47 -0700159 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700160
161 final int before = persistedModeFlags;
162 persistedModeFlags |= (persistableModeFlags & modeFlags);
163
164 if (persistedModeFlags != 0) {
165 persistedCreateTime = System.currentTimeMillis();
166 }
167
168 updateModeFlags();
169 return persistedModeFlags != before;
170 }
171
172 boolean releasePersistableModes(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700173 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
174 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
175
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700176 final int before = persistedModeFlags;
177
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700178 persistableModeFlags &= ~modeFlags;
179 persistedModeFlags &= ~modeFlags;
180
181 if (persistedModeFlags == 0) {
182 persistedCreateTime = INVALID_TIME;
183 }
184
185 updateModeFlags();
186 return persistedModeFlags != before;
187 }
188
189 /**
190 * @return if mode changes should trigger persisting.
191 */
Jeff Sharkey29b25162014-09-19 09:14:34 -0700192 boolean revokeModes(int modeFlags, boolean includingOwners) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700193 final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
194 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
195 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
196
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700197 final int before = persistedModeFlags;
198
199 if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
200 if (persistable) {
201 persistableModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700202 persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey29b25162014-09-19 09:14:34 -0700205 if (mReadOwners != null && includingOwners) {
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700206 ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700207 for (UriPermissionOwner r : mReadOwners) {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700208 r.removeReadPermission(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700210 mReadOwners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 }
212 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700213 if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
214 if (persistable) {
215 persistableModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700216 persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey29b25162014-09-19 09:14:34 -0700219 if (mWriteOwners != null && includingOwners) {
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700220 ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700221 for (UriPermissionOwner r : mWriteOwners) {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700222 r.removeWritePermission(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700224 mWriteOwners = null;
225 }
226 }
227
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700228 if (persistedModeFlags == 0) {
229 persistedCreateTime = INVALID_TIME;
230 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700231
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700232 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700233 return persistedModeFlags != before;
234 }
235
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700236 /**
237 * Return strength of this permission grant for the given flags.
238 */
239 public int getStrength(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700240 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
241 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700242 if ((persistableModeFlags & modeFlags) == modeFlags) {
243 return STRENGTH_PERSISTABLE;
244 } else if ((globalModeFlags & modeFlags) == modeFlags) {
245 return STRENGTH_GLOBAL;
246 } else if ((ownedModeFlags & modeFlags) == modeFlags) {
247 return STRENGTH_OWNED;
248 } else {
249 return STRENGTH_NONE;
250 }
251 }
252
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700253 private void addReadOwner(UriPermissionOwner owner) {
254 if (mReadOwners == null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700255 mReadOwners = Sets.newArraySet();
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700256 ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
257 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700258 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700259 if (mReadOwners.add(owner)) {
260 owner.addReadPermission(this);
261 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700262 }
263
264 /**
265 * Remove given read owner, updating {@Link #modeFlags} as needed.
266 */
267 void removeReadOwner(UriPermissionOwner owner) {
268 if (!mReadOwners.remove(owner)) {
Dianne Hackborn8d051722014-10-01 14:59:58 -0700269 Slog.wtf(TAG, "Unknown read owner " + owner + " in " + this);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700270 }
271 if (mReadOwners.size() == 0) {
272 mReadOwners = null;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700273 ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
274 updateModeFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 }
276 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700277
278 private void addWriteOwner(UriPermissionOwner owner) {
279 if (mWriteOwners == null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700280 mWriteOwners = Sets.newArraySet();
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700281 ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
282 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700283 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700284 if (mWriteOwners.add(owner)) {
285 owner.addWritePermission(this);
286 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700287 }
288
289 /**
290 * Remove given write owner, updating {@Link #modeFlags} as needed.
291 */
292 void removeWriteOwner(UriPermissionOwner owner) {
293 if (!mWriteOwners.remove(owner)) {
Dianne Hackborn8d051722014-10-01 14:59:58 -0700294 Slog.wtf(TAG, "Unknown write owner " + owner + " in " + this);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700295 }
296 if (mWriteOwners.size() == 0) {
297 mWriteOwners = null;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700298 ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
299 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700300 }
301 }
302
303 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700305 if (stringName != null) {
306 return stringName;
307 }
308 StringBuilder sb = new StringBuilder(128);
309 sb.append("UriPermission{");
310 sb.append(Integer.toHexString(System.identityHashCode(this)));
311 sb.append(' ');
312 sb.append(uri);
313 sb.append('}');
314 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 }
316
317 void dump(PrintWriter pw, String prefix) {
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700318 pw.print(prefix);
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100319 pw.print("targetUserId=" + targetUserId);
Jeff Sharkey9e0036e2013-04-26 16:54:55 -0700320 pw.print(" sourcePkg=" + sourcePkg);
321 pw.println(" targetPkg=" + targetPkg);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700322
323 pw.print(prefix);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700324 pw.print("mode=0x" + Integer.toHexString(modeFlags));
325 pw.print(" owned=0x" + Integer.toHexString(ownedModeFlags));
326 pw.print(" global=0x" + Integer.toHexString(globalModeFlags));
327 pw.print(" persistable=0x" + Integer.toHexString(persistableModeFlags));
328 pw.print(" persisted=0x" + Integer.toHexString(persistedModeFlags));
329 if (persistedCreateTime != INVALID_TIME) {
330 pw.print(" persistedCreate=" + persistedCreateTime);
331 }
332 pw.println();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700333
334 if (mReadOwners != null) {
335 pw.print(prefix);
336 pw.println("readOwners:");
337 for (UriPermissionOwner owner : mReadOwners) {
338 pw.print(prefix);
339 pw.println(" * " + owner);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700340 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700341 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700342 if (mWriteOwners != null) {
343 pw.print(prefix);
344 pw.println("writeOwners:");
345 for (UriPermissionOwner owner : mReadOwners) {
346 pw.print(prefix);
347 pw.println(" * " + owner);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700348 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700351
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700352 public static class PersistedTimeComparator implements Comparator<UriPermission> {
353 @Override
354 public int compare(UriPermission lhs, UriPermission rhs) {
355 return Long.compare(lhs.persistedCreateTime, rhs.persistedCreateTime);
356 }
357 }
358
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700359 /**
360 * Snapshot of {@link UriPermission} with frozen
361 * {@link UriPermission#persistedModeFlags} state.
362 */
363 public static class Snapshot {
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100364 final int targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700365 final String sourcePkg;
366 final String targetPkg;
Jeff Sharkey846318a2014-04-04 12:12:41 -0700367 final GrantUri uri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700368 final int persistedModeFlags;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700369 final long persistedCreateTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700370
371 private Snapshot(UriPermission perm) {
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100372 this.targetUserId = perm.targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700373 this.sourcePkg = perm.sourcePkg;
374 this.targetPkg = perm.targetPkg;
375 this.uri = perm.uri;
376 this.persistedModeFlags = perm.persistedModeFlags;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700377 this.persistedCreateTime = perm.persistedCreateTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700378 }
379 }
380
381 public Snapshot snapshot() {
382 return new Snapshot(this);
383 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700384
385 public android.content.UriPermission buildPersistedPublicApiObject() {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700386 return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388}