1 /* 2 * Copyright (C) 2024 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 package com.android.server.appsearch.appsindexer; 17 18 import android.annotation.NonNull; 19 import android.annotation.WorkerThread; 20 import android.app.appsearch.AppSearchBatchResult; 21 import android.app.appsearch.AppSearchManager; 22 import android.app.appsearch.AppSearchSession; 23 import android.app.appsearch.PutDocumentsRequest; 24 import android.app.appsearch.RemoveByDocumentIdRequest; 25 import android.app.appsearch.SearchSpec; 26 import android.app.appsearch.SetSchemaRequest; 27 import android.app.appsearch.SetSchemaResponse; 28 import android.app.appsearch.exceptions.AppSearchException; 29 30 import com.android.internal.annotations.GuardedBy; 31 32 import java.util.Objects; 33 import java.util.concurrent.Executor; 34 35 public class SyncAppSearchSessionImpl extends SyncAppSearchBase implements SyncAppSearchSession { 36 @GuardedBy("mSessionLock") 37 private volatile AppSearchSession mSession; 38 39 private final AppSearchManager.SearchContext mSearchContext; 40 private final AppSearchManager mAppSearchManager; 41 SyncAppSearchSessionImpl( @onNull AppSearchManager appSearchManager, @NonNull AppSearchManager.SearchContext searchContext, @NonNull Executor executor)42 public SyncAppSearchSessionImpl( 43 @NonNull AppSearchManager appSearchManager, 44 @NonNull AppSearchManager.SearchContext searchContext, 45 @NonNull Executor executor) { 46 super(Objects.requireNonNull(executor)); 47 mAppSearchManager = Objects.requireNonNull(appSearchManager); 48 mSearchContext = Objects.requireNonNull(searchContext); 49 } 50 51 /** 52 * Initializes the {@link AppSearchSession}. Only one AppSearchSession will be created per 53 * {@link SyncAppSearchSessionImpl}. 54 * 55 * @throws AppSearchException if unable to initialize the {@link AppSearchSession}. 56 */ 57 @WorkerThread ensureSessionInitializedLocked()58 private void ensureSessionInitializedLocked() throws AppSearchException { 59 synchronized (mSessionLock) { 60 if (mSession != null) { 61 return; 62 } 63 mSession = 64 executeAppSearchResultOperation( 65 resultHandler -> 66 mAppSearchManager.createSearchSession( 67 mSearchContext, mExecutor, resultHandler)); 68 } 69 } 70 71 /** 72 * Searches with a query and {@link SearchSpec}. Initializes the {@link AppSearchSession} if it 73 * hasn't been initialized already. 74 */ 75 @Override 76 @NonNull search(@onNull String query, @NonNull SearchSpec searchSpec)77 public SyncSearchResults search(@NonNull String query, @NonNull SearchSpec searchSpec) 78 throws AppSearchException { 79 Objects.requireNonNull(query); 80 Objects.requireNonNull(searchSpec); 81 ensureSessionInitializedLocked(); 82 return new SyncSearchResultsImpl(mSession.search(query, searchSpec), mExecutor); 83 } 84 85 /** 86 * Sets schemas into AppSearch. Initializes the {@link AppSearchSession} if it hasn't been 87 * initialized already. 88 */ 89 @Override 90 @NonNull 91 @WorkerThread setSchema(@onNull SetSchemaRequest setSchemaRequest)92 public SetSchemaResponse setSchema(@NonNull SetSchemaRequest setSchemaRequest) 93 throws AppSearchException { 94 Objects.requireNonNull(setSchemaRequest); 95 ensureSessionInitializedLocked(); 96 return executeAppSearchResultOperation( 97 resultHandler -> 98 mSession.setSchema(setSchemaRequest, mExecutor, mExecutor, resultHandler)); 99 } 100 101 /** 102 * Puts documents into AppSearch. Initializes the {@link AppSearchSession} if it hasn't been 103 * initialized already. 104 */ 105 @Override 106 @NonNull 107 @WorkerThread put(@onNull PutDocumentsRequest request)108 public AppSearchBatchResult<String, Void> put(@NonNull PutDocumentsRequest request) 109 throws AppSearchException { 110 Objects.requireNonNull(request); 111 ensureSessionInitializedLocked(); 112 // Put involves an AppSearchBatchResult, so it can't be simplified through 113 // executeAppSearchResultOperation. Instead we use executeAppSearchBatchResultOperation. 114 return executeAppSearchBatchResultOperation( 115 resultHandler -> mSession.put(request, mExecutor, resultHandler)); 116 } 117 118 /** 119 * Removes documents from AppSearch. Initializes the {@link AppSearchSession} if it hasn't been 120 * initialized already. 121 */ 122 @Override 123 @NonNull 124 @WorkerThread remove(@onNull String queryExpression, @NonNull SearchSpec searchSpec)125 public Void remove(@NonNull String queryExpression, @NonNull SearchSpec searchSpec) 126 throws AppSearchException { 127 Objects.requireNonNull(queryExpression); 128 Objects.requireNonNull(searchSpec); 129 ensureSessionInitializedLocked(); 130 return executeAppSearchResultOperation( 131 resultHandler -> { 132 synchronized (mSessionLock) { 133 mSession.remove(queryExpression, searchSpec, mExecutor, resultHandler); 134 } 135 }); 136 } 137 138 /** 139 * Removes documents from AppSearch using a list of ids. Initializes the {@link 140 * AppSearchSession} if it hasn't been initialized already. 141 */ 142 @Override 143 @NonNull 144 @WorkerThread 145 public AppSearchBatchResult<String, Void> remove(@NonNull RemoveByDocumentIdRequest request) 146 throws AppSearchException { 147 Objects.requireNonNull(request); 148 ensureSessionInitializedLocked(); 149 return executeAppSearchBatchResultOperation( 150 resultHandler -> { 151 synchronized (mSessionLock) { 152 mSession.remove(request, mExecutor, resultHandler); 153 } 154 }); 155 } 156 157 // Not asynchronous but it's necessary to be able to close the session 158 @Override 159 public void close() { 160 synchronized (mSessionLock) { 161 if (mSession != null) { 162 mSession.close(); 163 } 164 } 165 } 166 } 167