diff options
8 files changed, 160 insertions, 73 deletions
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index e2c9b0f74870..39abe7813578 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -23,6 +23,7 @@ import android.os.RemoteException; import com.android.internal.infra.AndroidFuture; +import com.google.android.icing.proto.DocumentProto; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SearchSpecProto; @@ -181,6 +182,53 @@ public class AppSearchManager { } /** + * Retrieves {@link android.app.appsearch.AppSearch.Document}s by URI. + * + * <p>You should not call this method directly; instead, use the + * {@code AppSearch#getDocuments()} API provided by JetPack. + * + * @param uris URIs of the documents to look up. + * @param executor Executor on which to invoke the callback. + * @param callback Callback to receive the documents or error. + */ + public void getDocuments( + @NonNull List<String> uris, + @NonNull @CallbackExecutor Executor executor, + @NonNull BiConsumer<List<AppSearch.Document>, ? super Throwable> callback) { + AndroidFuture<List<byte[]>> future = new AndroidFuture<>(); + future.whenCompleteAsync((documentProtos, err) -> { + if (err != null) { + callback.accept(null, err); + return; + } + if (documentProtos != null) { + List<AppSearch.Document> results = new ArrayList<>(documentProtos.size()); + for (int i = 0; i < documentProtos.size(); i++) { + DocumentProto documentProto; + try { + documentProto = DocumentProto.parseFrom(documentProtos.get(i)); + } catch (InvalidProtocolBufferException e) { + callback.accept(null, e); + return; + } + results.add(new AppSearch.Document(documentProto)); + } + callback.accept(results, null); + return; + } + // Nothing was supplied in the future at all + callback.accept(null, new IllegalStateException( + "Unknown failure occurred while retrieving documents")); + }, executor); + // TODO(b/146386470) stream uris? + try { + mService.getDocuments(uris.toArray(new String[uris.size()]), future); + } catch (RemoteException e) { + future.completeExceptionally(e); + } + } + + /** * This method searches for documents based on a given query string. It also accepts * specifications regarding how to search and format the results. * @@ -237,7 +285,6 @@ public class AppSearchManager { callback.accept(null, err); return; } - if (searchResultBytes != null) { SearchResultProto searchResultProto; try { @@ -257,12 +304,10 @@ public class AppSearchManager { callback.accept(searchResults, null); return; } - // Nothing was supplied in the future at all callback.accept( null, new IllegalStateException("Unknown failure occurred while querying")); }, executor); - try { SearchSpecProto searchSpecProto = searchSpec.getSearchSpecProto(); searchSpecProto = searchSpecProto.toBuilder().setQuery(queryExpression).build(); diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index eef41ed7104d..b80082536ebd 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -47,6 +47,16 @@ interface IAppSearchManager { void putDocuments(in List documentsBytes, in AndroidFuture<AppSearchBatchResult> callback); /** + * Retrieves documents from the index. + * + * @param uris The URIs of the documents to retrieve + * @param callback {@link AndroidFuture}<{@link List}<byte[]>>. Will be completed + * with a {@link List} containing serialized DocumentProtos, or completed exceptionally if + * get fails. + */ + void getDocuments(in String[] uris, in AndroidFuture callback); + + /** * Searches a document based on a given specifications. * * @param searchSpecBytes Serialized SearchSpecProto. diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 6293ee7059e5..2608e8453b3e 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -35,6 +35,7 @@ import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SearchSpecProto; import com.google.android.icing.protobuf.InvalidProtocolBufferException; +import java.util.ArrayList; import java.util.List; /** @@ -103,6 +104,30 @@ public class AppSearchManagerService extends SystemService { Binder.restoreCallingIdentity(callingIdentity); } } + + @Override + public void getDocuments(String[] uris, AndroidFuture callback) { + Preconditions.checkNotNull(uris); + Preconditions.checkNotNull(callback); + int callingUid = Binder.getCallingUidOrThrow(); + int callingUserId = UserHandle.getUserId(callingUid); + long callingIdentity = Binder.clearCallingIdentity(); + try { + AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); + // Contains serialized DocumentProto. byte[][] is not transmissible via Binder. + List<byte[]> results = new ArrayList<>(uris.length); + for (String uri : uris) { + DocumentProto result = impl.getDocument(callingUid, uri); + results.add(result.toByteArray()); + } + callback.complete(results); + } catch (Throwable t) { + callback.completeExceptionally(t); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + // TODO(sidchhabra):Init FakeIcing properly. // TODO(sidchhabra): Do this in a threadpool. @Override diff --git a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java index 04b4b1427328..7442d0625280 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java @@ -17,6 +17,7 @@ package com.android.server.appsearch.impl; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; @@ -106,30 +107,65 @@ public final class AppSearchImpl { // Rewrite the type names to include the app's prefix String typePrefix = getTypePrefix(callingUid); DocumentProto.Builder documentBuilder = origDocument.toBuilder(); - rewriteDocumentTypes(typePrefix, documentBuilder); + rewriteDocumentTypes(typePrefix, documentBuilder, /*add=*/ true); mFakeIcing.put(documentBuilder.build()); } /** - * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend + * Retrieves a document from the AppSearch index by URI. + * + * @param callingUid The uid of the app calling AppSearch. + * @param uri The URI of the document to get. + * @return The Document contents, or {@code null} if no such URI exists in the system. + */ + @Nullable + public DocumentProto getDocument(int callingUid, @NonNull String uri) { + String typePrefix = getTypePrefix(callingUid); + DocumentProto document = mFakeIcing.get(uri); + // Rewrite the type names to remove the app's prefix + DocumentProto.Builder documentBuilder = document.toBuilder(); + rewriteDocumentTypes(typePrefix, documentBuilder, /*add=*/ false); + return documentBuilder.build(); + } + + /** + * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend or remove * {@code typePrefix}. * - * @param typePrefix The prefix to add + * @param typePrefix The prefix to add or remove * @param documentBuilder The document to mutate + * @param add Whether to add typePrefix to the types. If {@code false}, typePrefix will be + * removed from the types. + * @throws IllegalArgumentException If {@code add=false} and the document has a type that + * doesn't start with {@code typePrefix}. */ @VisibleForTesting void rewriteDocumentTypes( @NonNull String typePrefix, - @NonNull DocumentProto.Builder documentBuilder) { - // Rewrite the type name to include the app's prefix - String newSchema = typePrefix + documentBuilder.getSchema(); + @NonNull DocumentProto.Builder documentBuilder, + boolean add) { + // Rewrite the type name to include/remove the app's prefix + String newSchema; + if (add) { + newSchema = typePrefix + documentBuilder.getSchema(); + } else { + newSchema = removePrefix(typePrefix, documentBuilder.getSchema()); + } documentBuilder.setSchema(newSchema); - // Add namespace. If we ever allow users to set their own namespaces, this will have + // Add/remove namespace. If we ever allow users to set their own namespaces, this will have // to change to prepend the prefix instead of setting the whole namespace. We will also have // to store the namespaces in a map similar to the type map so we can rewrite queries with // empty namespaces. - documentBuilder.setNamespace(typePrefix); + if (add) { + documentBuilder.setNamespace(typePrefix); + } else if (!documentBuilder.getNamespace().equals(typePrefix)) { + throw new IllegalStateException( + "Unexpected namespace \"" + documentBuilder.getNamespace() + + "\" (expected \"" + typePrefix + "\")"); + } else { + documentBuilder.clearNamespace(); + } // Recurse into derived documents for (int propertyIdx = 0; @@ -142,7 +178,7 @@ public final class AppSearchImpl { for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) { DocumentProto.Builder derivedDocumentBuilder = propertyBuilder.getDocumentValues(documentIdx).toBuilder(); - rewriteDocumentTypes(typePrefix, derivedDocumentBuilder); + rewriteDocumentTypes(typePrefix, derivedDocumentBuilder, add); propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder); } documentBuilder.setProperties(propertyIdx, propertyBuilder); @@ -165,4 +201,13 @@ public final class AppSearchImpl { } return callingUidName + "@" + mUserId + "/"; } + + @NonNull + private static String removePrefix(@NonNull String prefix, @NonNull String input) { + if (!input.startsWith(prefix)) { + throw new IllegalArgumentException( + "Input \"" + input + "\" does not start with \"" + prefix + "\""); + } + return input.substring(prefix.length()); + } } diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java index 20661c6f0833..eb414b0f11a6 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java @@ -27,6 +27,11 @@ class BlobStoreConfig { public static final int CURRENT_XML_VERSION = 1; + private static final String ROOT_DIR_NAME = "blobstore"; + private static final String BLOBS_DIR_NAME = "blobs"; + private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml"; + private static final String BLOBS_INDEX_FILE_NAME = "blobs_index.xml"; + @Nullable public static File prepareBlobFile(long sessionId) { final File blobsDir = prepareBlobsDir(); @@ -60,7 +65,7 @@ class BlobStoreConfig { @NonNull private static File getBlobsDir(File blobsRootDir) { - return new File(blobsRootDir, "blobs"); + return new File(blobsRootDir, BLOBS_DIR_NAME); } @Nullable @@ -69,7 +74,7 @@ class BlobStoreConfig { if (blobStoreRootDir == null) { return null; } - return new File(blobStoreRootDir, "sessions_index.xml"); + return new File(blobStoreRootDir, SESSIONS_INDEX_FILE_NAME); } @Nullable @@ -78,7 +83,7 @@ class BlobStoreConfig { if (blobsStoreRootDir == null) { return null; } - return new File(blobsStoreRootDir, "blobs_index.xml"); + return new File(blobsStoreRootDir, BLOBS_INDEX_FILE_NAME); } @Nullable @@ -93,6 +98,6 @@ class BlobStoreConfig { @NonNull public static File getBlobStoreRootDir() { - return new File(Environment.getDataSystemDirectory(), "blobstore"); + return new File(Environment.getDataSystemDirectory(), ROOT_DIR_NAME); } } diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index 4469d7de28fb..5cd4eb576aad 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -75,13 +75,11 @@ public class NetworkKey implements Parcelable { * * @return A new {@link NetworkKey} instance or <code>null</code> if the given * {@link ScanResult} instance is malformed. - * @throws IllegalArgumentException + * @throws NullPointerException */ @Nullable public static NetworkKey createFromScanResult(@NonNull ScanResult result) { - if (result == null) { - throw new IllegalArgumentException("ScanResult cannot be null"); - } + Objects.requireNonNull(result); final String ssid = result.SSID; if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) { return null; diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 30ad9c5d658c..48d405a4b91f 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -156,7 +156,6 @@ public class BugreportProgressService extends Service { static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE"; static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT"; static final String EXTRA_ID = "android.intent.extra.ID"; - static final String EXTRA_MAX = "android.intent.extra.MAX"; static final String EXTRA_NAME = "android.intent.extra.NAME"; static final String EXTRA_TITLE = "android.intent.extra.TITLE"; static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION"; @@ -173,7 +172,6 @@ public class BugreportProgressService extends Service { // Maximum progress displayed in %. private static final int CAPPED_PROGRESS = 99; - private static final int CAPPED_MAX = 100; /** Show the progress log every this percent. */ private static final int LOG_PROGRESS_STEP = 10; @@ -528,12 +526,10 @@ public class BugreportProgressService extends Service { } final String action = intent.getAction(); final int id = intent.getIntExtra(EXTRA_ID, 0); - final int max = intent.getIntExtra(EXTRA_MAX, -1); final String name = intent.getStringExtra(EXTRA_NAME); if (DEBUG) - Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id - + ", max: " + max); + Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id); switch (action) { case INTENT_BUGREPORT_REQUESTED: startBugreportAPI(intent); @@ -608,7 +604,7 @@ public class BugreportProgressService extends Service { String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); BugreportInfo info = new BugreportInfo(mContext, baseName, name, - 100 /* max progress*/, shareTitle, shareDescription, bugreportType); + shareTitle, shareDescription, bugreportType); ParcelFileDescriptor bugreportFd = info.createBugreportFd(); if (bugreportFd == null) { @@ -662,8 +658,8 @@ public class BugreportProgressService extends Service { * Updates the system notification for a given bugreport. */ private void updateProgress(BugreportInfo info) { - if (info.max <= 0 || info.progress < 0) { - Log.e(TAG, "Invalid progress values for " + info); + if (info.progress < 0) { + Log.e(TAG, "Invalid progress value for " + info); return; } @@ -676,7 +672,7 @@ public class BugreportProgressService extends Service { final NumberFormat nf = NumberFormat.getPercentInstance(); nf.setMinimumFractionDigits(2); nf.setMaximumFractionDigits(2); - final String percentageText = nf.format((double) info.progress / info.max); + final String percentageText = nf.format((double) info.progress / 100); String title = mContext.getString(R.string.bugreport_in_progress_title, info.id); @@ -684,7 +680,7 @@ public class BugreportProgressService extends Service { if (mIsWatch) { nf.setMinimumFractionDigits(0); nf.setMaximumFractionDigits(0); - final String watchPercentageText = nf.format((double) info.progress / info.max); + final String watchPercentageText = nf.format((double) info.progress / 100); title = title + "\n" + watchPercentageText; } @@ -695,7 +691,7 @@ public class BugreportProgressService extends Service { .setContentTitle(title) .setTicker(title) .setContentText(name) - .setProgress(info.max, info.progress, false) + .setProgress(100 /* max value of progress percentage */, info.progress, false) .setOngoing(true); // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action. @@ -724,7 +720,7 @@ public class BugreportProgressService extends Service { .setActions(infoAction, screenshotAction, cancelAction); } // Show a debug log, every LOG_PROGRESS_STEP percent. - final int progress = (info.progress * 100) / info.max; + final int progress = info.progress; if ((info.progress == 0) || (info.progress >= 100) || ((progress / LOG_PROGRESS_STEP) != (mLastProgressPercent / LOG_PROGRESS_STEP))) { @@ -1457,7 +1453,6 @@ public class BugreportProgressService extends Service { } final StringBuilder buffer = new StringBuilder(action).append(" extras: "); addExtra(buffer, intent, EXTRA_ID); - addExtra(buffer, intent, EXTRA_MAX); addExtra(buffer, intent, EXTRA_NAME); addExtra(buffer, intent, EXTRA_DESCRIPTION); addExtra(buffer, intent, EXTRA_BUGREPORT); @@ -1761,26 +1756,11 @@ public class BugreportProgressService extends Service { String description; /** - * Maximum progress of the bugreport generation as displayed by the UI. - */ - int max; - - /** - * Current progress of the bugreport generation as displayed by the UI. + * Current progress (in percentage) of the bugreport generation as displayed by the UI. */ int progress; /** - * Maximum progress of the bugreport generation as reported by dumpstate. - */ - int realMax; - - /** - * Current progress of the bugreport generation as reported by dumpstate. - */ - int realProgress; - - /** * Time of the last progress update. */ long lastUpdate = System.currentTimeMillis(); @@ -1831,12 +1811,11 @@ public class BugreportProgressService extends Service { /** * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_REQUESTED. */ - BugreportInfo(Context context, String baseName, String name, int max, + BugreportInfo(Context context, String baseName, String name, @Nullable String shareTitle, @Nullable String shareDescription, @BugreportParams.BugreportMode int type) { this.context = context; this.name = this.initialName = name; - this.max = this.realMax = max; this.shareTitle = shareTitle == null ? "" : shareTitle; this.shareDescription = shareDescription == null ? "" : shareDescription; this.type = type; @@ -1930,8 +1909,6 @@ public class BugreportProgressService extends Service { @Override public String toString() { - final float percent = ((float) progress * 100 / max); - final float realPercent = ((float) realProgress * 100 / realMax); final StringBuilder builder = new StringBuilder() .append("\tid: ").append(id) @@ -1953,10 +1930,7 @@ public class BugreportProgressService extends Service { return builder .append("\n\tfile: ").append(bugreportFile) .append("\n\tscreenshots: ").append(screenshotFiles) - .append("\n\tprogress: ").append(progress).append("/").append(max) - .append(" (").append(percent).append(")") - .append("\n\treal progress: ").append(realProgress).append("/").append(realMax) - .append(" (").append(realPercent).append(")") + .append("\n\tprogress: ").append(progress) .append("\n\tlast_update: ").append(getFormattedLastUpdate()) .append("\n\taddingDetailsToZip: ").append(addingDetailsToZip) .append(" addedDetailsToZip: ").append(addedDetailsToZip) @@ -1974,10 +1948,7 @@ public class BugreportProgressService extends Service { initialName = in.readString(); title = in.readString(); description = in.readString(); - max = in.readInt(); progress = in.readInt(); - realMax = in.readInt(); - realProgress = in.readInt(); lastUpdate = in.readLong(); formattedLastUpdate = in.readString(); bugreportFile = readFile(in); @@ -2001,10 +1972,7 @@ public class BugreportProgressService extends Service { dest.writeString(initialName); dest.writeString(title); dest.writeString(description); - dest.writeInt(max); dest.writeInt(progress); - dest.writeInt(realMax); - dest.writeInt(realProgress); dest.writeLong(lastUpdate); dest.writeString(getFormattedLastUpdate()); writeFile(dest, bugreportFile); @@ -2055,22 +2023,13 @@ public class BugreportProgressService extends Service { if (progress > CAPPED_PROGRESS) { progress = CAPPED_PROGRESS; } - updateProgressInfo(info, progress, CAPPED_MAX); - } - - private void updateProgressInfo(BugreportInfo info, int progress, int max) { if (DEBUG) { if (progress != info.progress) { Log.v(TAG, "Updating progress for name " + info.name + "(id: " + info.id + ") from " + info.progress + " to " + progress); } - if (max != info.max) { - Log.v(TAG, "Updating max progress for name " + info.name + "(id: " + info.id - + ") from " + info.max + " to " + max); - } } info.progress = progress; - info.max = max; info.lastUpdate = System.currentTimeMillis(); updateProgress(info); diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index bb298e937fbb..b95092a9384c 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -27,7 +27,6 @@ import static com.android.shell.BugreportPrefs.getWarningState; import static com.android.shell.BugreportPrefs.setWarningState; import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT; import static com.android.shell.BugreportProgressService.EXTRA_ID; -import static com.android.shell.BugreportProgressService.EXTRA_MAX; import static com.android.shell.BugreportProgressService.EXTRA_NAME; import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT; import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED; @@ -144,6 +143,7 @@ public class BugreportReceiverTest { private static final String DESCRIPTION = "One's description..."; private static final String DESCRIPTION2 = "...is another's treasure."; // TODO(b/143130523): Fix (update) tests and add to presubmit + private static final String EXTRA_MAX = "android.intent.extra.MAX"; private static final String EXTRA_PID = "android.intent.extra.PID"; private static final String INTENT_BUGREPORT_STARTED = "com.android.internal.intent.action.BUGREPORT_STARTED"; |