1 /* 2 * Copyright (C) 2020 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 android.searchuiservice.cts; 17 18 import android.app.search.Query; 19 import android.app.search.SearchContext; 20 import android.app.search.SearchSessionId; 21 import android.app.search.SearchTarget; 22 import android.app.search.SearchTargetEvent; 23 import android.content.Intent; 24 import android.service.search.SearchUiService; 25 import android.util.Log; 26 27 import org.mockito.Mockito; 28 29 import java.util.List; 30 import java.util.concurrent.CountDownLatch; 31 import java.util.function.Consumer; 32 33 public class CtsSearchUiService extends SearchUiService { 34 35 private static final boolean DEBUG = false; 36 private static final String TAG = CtsSearchUiService.class.getSimpleName(); 37 38 public static final String MY_PACKAGE = "android.searchuiservice.cts"; 39 public static final String SERVICE_NAME = MY_PACKAGE + "/." 40 + CtsSearchUiService.class.getSimpleName(); 41 42 private static Watcher sWatcher; 43 44 @Override onCreate()45 public void onCreate() { 46 super.onCreate(); 47 if (DEBUG) Log.d(TAG, "onCreate"); 48 49 } 50 51 @Override onDestroy(SearchSessionId sessionId)52 public void onDestroy(SearchSessionId sessionId) { 53 if (DEBUG) Log.d(TAG, "onDestroy"); 54 super.onDestroy(); 55 sWatcher.destroyed.countDown(); 56 } 57 58 @Override onUnbind(Intent intent)59 public boolean onUnbind(Intent intent) { 60 if (DEBUG) Log.d(TAG, "unbind"); 61 return super.onUnbind(intent); 62 } 63 64 @Override onSearchSessionCreated(SearchContext context, SearchSessionId sessionId)65 public void onSearchSessionCreated(SearchContext context, 66 SearchSessionId sessionId) { 67 if (DEBUG) Log.d(TAG, "onCreateSearchSession"); 68 super.onSearchSessionCreated(context, sessionId); 69 if (sWatcher.verifier != null) { 70 Log.e(TAG, "onCreateSearchSession, trying to set verifier when it already exists"); 71 } 72 sWatcher.verifier = Mockito.mock(CtsSearchUiService.class); 73 sWatcher.created.countDown(); 74 sWatcher.searchContext = context; 75 } 76 77 @Override onNotifyEvent(SearchSessionId sessionId, Query input, SearchTargetEvent event)78 public void onNotifyEvent(SearchSessionId sessionId, 79 Query input, SearchTargetEvent event) { 80 if (DEBUG){ 81 Log.d(TAG, "onNotifyEvent query=" + input.getInput() + ", event=" 82 + event.getTargetId()); 83 } 84 sWatcher.verifier.onNotifyEvent(sessionId, input, event); 85 } 86 87 @Override onQuery(SearchSessionId sessionId, Query input, Consumer<List<SearchTarget>> callback)88 public void onQuery(SearchSessionId sessionId, Query input, 89 Consumer<List<SearchTarget>> callback) { 90 if (DEBUG) Log.d(TAG, "onQuery query=" + input.getInput()); 91 if (sWatcher.searchTargets != null) { 92 callback.accept(sWatcher.searchTargets); 93 } else { 94 sWatcher.verifier.onQuery(sessionId, input, callback); 95 } 96 } 97 98 @Override onStartUpdateEmptyQueryResult()99 public void onStartUpdateEmptyQueryResult() { 100 super.onStartUpdateEmptyQueryResult(); 101 sWatcher.startedUpdateEmptyQueryResult.countDown(); 102 sWatcher.verifier.onStartUpdateEmptyQueryResult(); 103 } 104 105 @Override onStopUpdateEmptyQueryResult()106 public void onStopUpdateEmptyQueryResult() { 107 super.onStopUpdateEmptyQueryResult(); 108 sWatcher.stoppedUpdateEmptyQueryResult.countDown(); 109 sWatcher.verifier.onStopUpdateEmptyQueryResult(); 110 } 111 setWatcher()112 public static Watcher setWatcher() { 113 if (DEBUG) { 114 Log.d(TAG, ""); 115 Log.d(TAG, "----------------------------------------------"); 116 Log.d(TAG, " setWatcher"); 117 } 118 if (sWatcher != null) { 119 throw new IllegalStateException("Set watcher with watcher already set"); 120 } 121 sWatcher = new Watcher(); 122 return sWatcher; 123 } 124 clearWatcher()125 public static void clearWatcher() { 126 if (DEBUG) Log.d(TAG, "clearWatcher"); 127 sWatcher = null; 128 } 129 130 public static final class Watcher { 131 public CountDownLatch created = new CountDownLatch(1); 132 public CountDownLatch destroyed = new CountDownLatch(1); 133 public CountDownLatch queried = new CountDownLatch(1); 134 public CountDownLatch startedUpdateEmptyQueryResult = new CountDownLatch(1); 135 public CountDownLatch requestEmptyQueryResultUpdate = new CountDownLatch(1); 136 public CountDownLatch stoppedUpdateEmptyQueryResult = new CountDownLatch(1); 137 138 /** 139 * Can be used to verify that API specific service methods are called. Not a real mock as 140 * the system isn't talking to this directly, it has calls proxied to it. 141 */ 142 public CtsSearchUiService verifier; 143 144 public List<SearchTarget> searchTargets; 145 146 public SearchContext searchContext; 147 setTargets(List<SearchTarget> targets)148 public void setTargets(List<SearchTarget> targets) { 149 searchTargets = targets; 150 } 151 } 152 } 153