blob: 83c0c91123871f6167ec3384c6207f54bddb4ffd [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
168 public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
169 throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600170 try (Logger l = new Logger("insert", uri, initialValues)) {
171 try {
172 return l.setResult(delegate.insert(uri, initialValues));
173 } catch (Exception res) {
174 l.setResult(res);
175 throw res;
176 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600177 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700178 }
179
180 @Override
181 public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
182 throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600183 try (Logger l = new Logger("bulkInsert", uri, initialValues)) {
184 try {
185 return l.setResult(delegate.bulkInsert(uri, initialValues));
186 } 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 delete(@NonNull Uri uri, @Nullable String selection,
195 @Nullable String[] selectionArgs) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600196 try (Logger l = new Logger("delete", uri, selection, selectionArgs)) {
197 try {
198 return l.setResult(delegate.delete(uri, selection, selectionArgs));
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
207 public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
208 @Nullable String[] selectionArgs) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600209 try (Logger l = new Logger("update", uri, values, selection, selectionArgs)) {
210 try {
211 return l.setResult(delegate.update(uri, values, selection, selectionArgs));
212 } catch (Exception res) {
213 l.setResult(res);
214 throw res;
215 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600216 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700217 }
218
219 @Override
220 public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
221 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600222 try (Logger l = new Logger("openFile", uri, mode, signal)) {
223 try {
224 return l.setResult(delegate.openFile(uri, mode, signal));
225 } catch (Exception res) {
226 l.setResult(res);
227 throw res;
228 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600229 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700230 }
231
232 @Override
233 public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
234 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600235 try (Logger l = new Logger("openAssetFile", uri, mode, signal)) {
236 try {
237 return l.setResult(delegate.openAssetFile(uri, mode, signal));
238 } catch (Exception res) {
239 l.setResult(res);
240 throw res;
241 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600242 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700243 }
244
245 @Override
246 public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
247 @NonNull String mimeTypeFilter, @Nullable Bundle opts,
248 @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600249 try (Logger l = new Logger("openTypedAssetFile", uri, mimeTypeFilter, opts, signal)) {
250 try {
251 return l.setResult(delegate.openTypedAssetFile(uri, mimeTypeFilter, opts, signal));
252 } catch (Exception res) {
253 l.setResult(res);
254 throw res;
255 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600256 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700257 }
258
259 @Override
260 public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
261 @NonNull ArrayList<ContentProviderOperation> operations)
262 throws RemoteException, OperationApplicationException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600263 try (Logger l = new Logger("applyBatch", authority, operations)) {
264 try {
265 return l.setResult(delegate.applyBatch(authority, operations));
266 } catch (Exception res) {
267 l.setResult(res);
268 throw res;
269 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600270 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700271 }
272
273 @Override
274 public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
275 @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
Jeff Sharkey4b32a4a2019-04-02 13:42:58 -0600276 try (Logger l = new Logger("call", authority, method, arg, extras)) {
277 try {
278 return l.setResult(delegate.call(authority, method, arg, extras));
279 } catch (Exception res) {
280 l.setResult(res);
281 throw res;
282 }
Jeff Sharkey9bb54f22019-03-17 11:05:32 -0600283 }
Jeff Sharkeybffd2502019-02-28 16:39:12 -0700284 }
285}