blob: 3bd083268d45fb49816f1ea3901760acb05d1003 [file] [log] [blame]
Jeff Sharkeybffd2502019-02-28 16:39:12 -07001/*
2 * Copyright (C) 2019 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 android.content;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.content.res.AssetFileDescriptor;
22import android.database.Cursor;
23import android.database.DatabaseUtils;
24import android.net.Uri;
25import android.os.Binder;
26import android.os.Bundle;
27import android.os.CancellationSignal;
28import android.os.ParcelFileDescriptor;
29import android.os.RemoteException;
30import android.util.Log;
31
32import java.io.FileNotFoundException;
33import java.util.ArrayList;
34import java.util.Arrays;
35
36/**
37 * Instance of {@link ContentInterface} that logs all inputs and outputs while
38 * delegating to another {@link ContentInterface}.
39 *
40 * @hide
41 */
42public class LoggingContentInterface implements ContentInterface {
43 private final String tag;
44 private final ContentInterface delegate;
45
46 public LoggingContentInterface(String tag, ContentInterface delegate) {
47 this.tag = tag;
48 this.delegate = delegate;
49 }
50
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -060051 private class Logger implements AutoCloseable {
52 private final StringBuilder sb = new StringBuilder();
53
54 public Logger(String method, Object... args) {
55 // First, force-unparcel any bundles so we can log them
56 for (Object arg : args) {
57 if (arg instanceof Bundle) {
58 ((Bundle) arg).size();
59 }
60 }
61
62 sb.append("callingUid=").append(Binder.getCallingUid()).append(' ');
63 sb.append(method);
64 sb.append('(').append(deepToString(args)).append(')');
65 }
66
67 private String deepToString(Object value) {
68 if (value != null && value.getClass().isArray()) {
69 return Arrays.deepToString((Object[]) value);
70 } else {
71 return String.valueOf(value);
Jeff Sharkeybffd2502019-02-28 16:39:12 -070072 }
73 }
74
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -060075 public <T> T setResult(T res) {
76 if (res instanceof Cursor) {
77 sb.append('\n');
78 DatabaseUtils.dumpCursor((Cursor) res, sb);
79 } else {
80 sb.append(" = ").append(deepToString(res));
81 }
82 return res;
Jeff Sharkeybffd2502019-02-28 16:39:12 -070083 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -060084
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -060085 @Override
86 public void close() {
Jeff Sharkey9bb54f22019-03-17 11:05:32 -060087 Log.v(tag, sb.toString());
88 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -070089 }
90
Jeff Sharkeybffd2502019-02-28 16:39:12 -070091 @Override
92 public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
93 @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
94 throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -060095 try (Logger l = new Logger("query", uri, projection, queryArgs, cancellationSignal)) {
96 try {
97 return l.setResult(delegate.query(uri, projection, queryArgs, cancellationSignal));
98 } catch (Exception res) {
99 l.setResult(res);
100 throw res;
101 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600102 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700103 }
104
105 @Override
106 public @Nullable String getType(@NonNull Uri uri) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600107 try (Logger l = new Logger("getType", uri)) {
108 try {
109 return l.setResult(delegate.getType(uri));
110 } catch (Exception res) {
111 l.setResult(res);
112 throw res;
113 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600114 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700115 }
116
117 @Override
118 public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter)
119 throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600120 try (Logger l = new Logger("getStreamTypes", uri, mimeTypeFilter)) {
121 try {
122 return l.setResult(delegate.getStreamTypes(uri, mimeTypeFilter));
123 } catch (Exception res) {
124 l.setResult(res);
125 throw res;
126 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600127 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700128 }
129
130 @Override
131 public @Nullable Uri canonicalize(@NonNull Uri uri) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600132 try (Logger l = new Logger("canonicalize", uri)) {
133 try {
134 return l.setResult(delegate.canonicalize(uri));
135 } catch (Exception res) {
136 l.setResult(res);
137 throw res;
138 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600139 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700140 }
141
142 @Override
143 public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600144 try (Logger l = new Logger("uncanonicalize", uri)) {
145 try {
146 return l.setResult(delegate.uncanonicalize(uri));
147 } catch (Exception res) {
148 l.setResult(res);
149 throw res;
150 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600151 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700152 }
153
154 @Override
155 public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
156 @Nullable CancellationSignal cancellationSignal) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600157 try (Logger l = new Logger("refresh", uri, args, cancellationSignal)) {
158 try {
159 return l.setResult(delegate.refresh(uri, args, cancellationSignal));
160 } catch (Exception res) {
161 l.setResult(res);
162 throw res;
163 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600164 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700165 }
166
167 @Override
Jeff Sharkey9edef252019-05-20 14:00:17 -0600168 public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
169 throws RemoteException {
170 try (Logger l = new Logger("checkUriPermission", uri, uid, modeFlags)) {
171 try {
172 return l.setResult(delegate.checkUriPermission(uri, uid, modeFlags));
173 } catch (Exception res) {
174 l.setResult(res);
175 throw res;
176 }
177 }
178 }
179
180 @Override
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700181 public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
182 @Nullable Bundle extras) throws RemoteException {
183 try (Logger l = new Logger("insert", uri, initialValues, extras)) {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600184 try {
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700185 return l.setResult(delegate.insert(uri, initialValues, extras));
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600186 } catch (Exception res) {
187 l.setResult(res);
188 throw res;
189 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600190 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700191 }
192
193 @Override
194 public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
195 throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600196 try (Logger l = new Logger("bulkInsert", uri, initialValues)) {
197 try {
198 return l.setResult(delegate.bulkInsert(uri, initialValues));
199 } catch (Exception res) {
200 l.setResult(res);
201 throw res;
202 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600203 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700204 }
205
206 @Override
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700207 public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException {
208 try (Logger l = new Logger("delete", uri, extras)) {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600209 try {
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700210 return l.setResult(delegate.delete(uri, extras));
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600211 } catch (Exception res) {
212 l.setResult(res);
213 throw res;
214 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600215 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700216 }
217
218 @Override
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700219 public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
220 throws RemoteException {
221 try (Logger l = new Logger("update", uri, values, extras)) {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600222 try {
Jeff Sharkeye9fe1522019-11-15 12:45:15 -0700223 return l.setResult(delegate.update(uri, values, extras));
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600224 } catch (Exception res) {
225 l.setResult(res);
226 throw res;
227 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600228 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700229 }
230
231 @Override
232 public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
233 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600234 try (Logger l = new Logger("openFile", uri, mode, signal)) {
235 try {
236 return l.setResult(delegate.openFile(uri, mode, signal));
237 } catch (Exception res) {
238 l.setResult(res);
239 throw res;
240 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600241 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700242 }
243
244 @Override
245 public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
246 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600247 try (Logger l = new Logger("openAssetFile", uri, mode, signal)) {
248 try {
249 return l.setResult(delegate.openAssetFile(uri, mode, signal));
250 } catch (Exception res) {
251 l.setResult(res);
252 throw res;
253 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600254 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700255 }
256
257 @Override
258 public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
259 @NonNull String mimeTypeFilter, @Nullable Bundle opts,
260 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600261 try (Logger l = new Logger("openTypedAssetFile", uri, mimeTypeFilter, opts, signal)) {
262 try {
263 return l.setResult(delegate.openTypedAssetFile(uri, mimeTypeFilter, opts, signal));
264 } catch (Exception res) {
265 l.setResult(res);
266 throw res;
267 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600268 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700269 }
270
271 @Override
272 public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
273 @NonNull ArrayList<ContentProviderOperation> operations)
274 throws RemoteException, OperationApplicationException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600275 try (Logger l = new Logger("applyBatch", authority, operations)) {
276 try {
277 return l.setResult(delegate.applyBatch(authority, operations));
278 } catch (Exception res) {
279 l.setResult(res);
280 throw res;
281 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600282 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700283 }
284
285 @Override
286 public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
287 @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600288 try (Logger l = new Logger("call", authority, method, arg, extras)) {
289 try {
290 return l.setResult(delegate.call(authority, method, arg, extras));
291 } catch (Exception res) {
292 l.setResult(res);
293 throw res;
294 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600295 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700296 }
297}