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.AppSearchManager; 21 import android.app.appsearch.GlobalSearchSession; 22 import android.app.appsearch.SearchSpec; 23 import android.app.appsearch.exceptions.AppSearchException; 24 25 import com.android.internal.annotations.GuardedBy; 26 27 import java.util.Objects; 28 import java.util.concurrent.Executor; 29 30 public class SyncGlobalSearchSessionImpl extends SyncAppSearchBase 31 implements SyncGlobalSearchSession { 32 33 @GuardedBy("mSessionLock") 34 private volatile GlobalSearchSession mGlobalSession; 35 36 private final AppSearchManager mAppSearchManager; 37 SyncGlobalSearchSessionImpl( @onNull AppSearchManager appSearchManager, @NonNull Executor executor)38 public SyncGlobalSearchSessionImpl( 39 @NonNull AppSearchManager appSearchManager, @NonNull Executor executor) { 40 super(Objects.requireNonNull(executor)); 41 mAppSearchManager = Objects.requireNonNull(appSearchManager); 42 } 43 44 /** 45 * Sets up the {@link GlobalSearchSession}. 46 * 47 * @throws AppSearchException if unable to initialize the {@link GlobalSearchSession}. 48 */ 49 @WorkerThread ensureSessionInitializedLocked()50 private void ensureSessionInitializedLocked() throws AppSearchException { 51 synchronized (mSessionLock) { 52 if (mGlobalSession != null) { 53 return; 54 } 55 // It is best to initialize search sessions in a different thread from the thread that 56 // calls onUserUnlock, which calls the constructor. 57 mGlobalSession = 58 executeAppSearchResultOperation( 59 resultHandler -> 60 mAppSearchManager.createGlobalSearchSession( 61 mExecutor, resultHandler)); 62 } 63 } 64 65 /** 66 * Searches with a query and {@link SearchSpec}. Initializes the {@link GlobalSearchSession} if 67 * it hasn't been initialized already. 68 */ 69 @Override 70 @NonNull 71 @WorkerThread search(@onNull String query, @NonNull SearchSpec searchSpec)72 public SyncSearchResults search(@NonNull String query, @NonNull SearchSpec searchSpec) 73 throws AppSearchException { 74 Objects.requireNonNull(query); 75 Objects.requireNonNull(searchSpec); 76 ensureSessionInitializedLocked(); 77 return new SyncSearchResultsImpl(mGlobalSession.search(query, searchSpec), mExecutor); 78 } 79 80 // Not an asynchronous call but it's necessary to be able to close the session 81 @Override close()82 public void close() { 83 synchronized (mSessionLock) { 84 if (mGlobalSession != null) { 85 mGlobalSession.close(); 86 } 87 } 88 } 89 } 90