• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <android/binder_auto_utils.h>
2 #include <android/binder_ibinder.h>
3 #include <android/binder_status.h>
4 
5 #include <cstdint>
6 #include <cstdlib>
7 #include <memory>
8 #include <optional>
9 #include <vector>
10 
11 #include "aidl/com/android/isolated_storage_service/BnIcingSearchEngine.h"
12 #include "aidl/com/android/isolated_storage_service/BnIsolatedStorageService.h"
13 #include <vm_payload.h>
14 #include "icing/icing-search-engine.h"
15 #include "icing/proto/blob.pb.h"
16 #include "icing/proto/document.pb.h"
17 #include "icing/proto/initialize.pb.h"
18 #include "icing/proto/schema.pb.h"
19 #include "icing/proto/scoring.pb.h"
20 #include "icing/proto/search.pb.h"
21 #include "icing/proto/status.pb.h"
22 #include "icing/proto/storage.pb.h"
23 #include "icing/proto/term.pb.h"
24 #include "icing/proto/usage.pb.h"
25 #include "icing/util/logging.h"
26 #include "macros.h"
27 
28 namespace {
29 
30 using ::aidl::com::android::isolated_storage_service::BnIcingSearchEngine;
31 using ::aidl::com::android::isolated_storage_service::BnIsolatedStorageService;
32 using ::icing::lib::BatchPutResultProto;
33 using ::icing::lib::BlobProto;
34 using ::icing::lib::DebugInfoResultProto;
35 using ::icing::lib::DebugInfoVerbosity;
36 using ::icing::lib::DeleteByNamespaceResultProto;
37 using ::icing::lib::DeleteByQueryResultProto;
38 using ::icing::lib::DeleteBySchemaTypeResultProto;
39 using ::icing::lib::DeleteResultProto;
40 using ::icing::lib::DocumentProto;
41 using ::icing::lib::GetAllNamespacesResultProto;
42 using ::icing::lib::GetOptimizeInfoResultProto;
43 using ::icing::lib::GetResultProto;
44 using ::icing::lib::GetResultSpecProto;
45 using ::icing::lib::GetSchemaResultProto;
46 using ::icing::lib::GetSchemaTypeResultProto;
47 using ::icing::lib::IcingSearchEngine;
48 using ::icing::lib::IcingSearchEngineOptions;
49 using ::icing::lib::InitializeResultProto;
50 using ::icing::lib::OptimizeResultProto;
51 using ::icing::lib::PersistToDiskResultProto;
52 using ::icing::lib::PersistType;
53 using ::icing::lib::PutDocumentRequest;
54 using ::icing::lib::PutResultProto;
55 using ::icing::lib::ReportUsageResultProto;
56 using ::icing::lib::ResetResultProto;
57 using ::icing::lib::ResultSpecProto;
58 using ::icing::lib::SchemaProto;
59 using ::icing::lib::ScoringSpecProto;
60 using ::icing::lib::SearchResultProto;
61 using ::icing::lib::SearchSpecProto;
62 using ::icing::lib::SetSchemaResultProto;
63 using ::icing::lib::StatusProto;
64 using ::icing::lib::StorageInfoResultProto;
65 using ::icing::lib::SuggestionResponse;
66 using ::icing::lib::SuggestionSpecProto;
67 using ::icing::lib::TermMatchType;
68 using ::icing::lib::UsageReport;
69 using BlobHandleProto = ::icing::lib::PropertyProto::BlobHandleProto;
70 using ::icing::lib::INFO;
71 using ::ndk::ScopedAStatus;
72 
73 // This class implements the AIDL interface for the Icing connection.
74 class IcingConnectionImpl
75     : public aidl::com::android::isolated_storage_service::BnIcingSearchEngine {
76  public:
IcingConnectionImpl(uint32_t uid)77   explicit IcingConnectionImpl(uint32_t uid) : uid_(uid) {}
78 
initialize(const std::vector<uint8_t> & icing_search_engine_options_proto,std::optional<std::vector<uint8_t>> * initialize_result_proto)79   ScopedAStatus initialize(
80       const std::vector<uint8_t>& icing_search_engine_options_proto,
81       std::optional<std::vector<uint8_t>>* initialize_result_proto) {
82     IcingSearchEngineOptions options;
83     DESERIALIZE_OR_RETURN(icing_search_engine_options_proto, options);
84     options.set_base_dir(std::string(AVmPayload_getEncryptedStoragePath()) +
85                          "/" + std::to_string(uid_) + "/" + options.base_dir());
86     icing_ = std::make_unique<IcingSearchEngine>(options);
87     InitializeResultProto initialize_result = icing_->Initialize();
88     SERIALIZE_AND_RETURN_ASTATUS(initialize_result, initialize_result_proto);
89   }
90 
close()91   ScopedAStatus close() {
92     CHECK_ICING_INIT(icing_);
93     ICING_LOG(INFO) << "IsolatedStorageService closing Icing connection.";
94     icing_->PersistToDisk(icing::lib::PersistType::FULL);
95     return ScopedAStatus::ok();
96   }
97 
reset(std::optional<std::vector<uint8_t>> * reset_result_proto)98   ScopedAStatus reset(std::optional<std::vector<uint8_t>>* reset_result_proto) {
99     CHECK_ICING_INIT(icing_);
100     ResetResultProto reset_result = icing_->Reset();
101     SERIALIZE_AND_RETURN_ASTATUS(reset_result, reset_result_proto);
102   }
103 
setSchema(const std::vector<uint8_t> & schema_proto,bool ignore_errors_and_delete_documents,std::optional<std::vector<uint8_t>> * set_schema_result_proto)104   ScopedAStatus setSchema(
105       const std::vector<uint8_t>& schema_proto,
106       bool ignore_errors_and_delete_documents,
107       std::optional<std::vector<uint8_t>>* set_schema_result_proto) {
108     CHECK_ICING_INIT(icing_);
109 
110     SchemaProto schema;
111     DESERIALIZE_OR_RETURN(schema_proto, schema)
112 
113     SetSchemaResultProto set_schema_result =
114         icing_->SetSchema(schema, ignore_errors_and_delete_documents);
115     SERIALIZE_AND_RETURN_ASTATUS(set_schema_result, set_schema_result_proto);
116   }
117 
getSchema(std::optional<std::vector<uint8_t>> * get_schema_result_proto)118   ScopedAStatus getSchema(
119       std::optional<std::vector<uint8_t>>* get_schema_result_proto) {
120     CHECK_ICING_INIT(icing_);
121 
122     GetSchemaResultProto schema = icing_->GetSchema();
123     SERIALIZE_AND_RETURN_ASTATUS(schema, get_schema_result_proto);
124   }
125 
getSchemaForDatabase(const std::string & database,std::optional<std::vector<uint8_t>> * get_schema_result_proto)126   ScopedAStatus getSchemaForDatabase(
127       const std::string& database,
128       std::optional<std::vector<uint8_t>>* get_schema_result_proto) {
129     CHECK_ICING_INIT(icing_);
130     GetSchemaResultProto schema = icing_->GetSchema(database);
131     SERIALIZE_AND_RETURN_ASTATUS(schema, get_schema_result_proto);
132   }
133 
getSchemaType(const std::string & schema_type,std::optional<std::vector<uint8_t>> * get_schema_type_result_proto)134   ScopedAStatus getSchemaType(
135       const std::string& schema_type,
136       std::optional<std::vector<uint8_t>>* get_schema_type_result_proto) {
137     CHECK_ICING_INIT(icing_);
138 
139     GetSchemaTypeResultProto schema_type_result =
140         icing_->GetSchemaType(schema_type);
141     SERIALIZE_AND_RETURN_ASTATUS(schema_type_result,
142                                  get_schema_type_result_proto);
143   }
144 
put(const std::vector<uint8_t> & document_proto,std::optional<std::vector<uint8_t>> * put_result_proto)145   ScopedAStatus put(const std::vector<uint8_t>& document_proto,
146                     std::optional<std::vector<uint8_t>>* put_result_proto) {
147     CHECK_ICING_INIT(icing_);
148 
149     DocumentProto document;
150     DESERIALIZE_OR_RETURN(document_proto, document);
151     PutResultProto put_result = icing_->Put(document);
152     *put_result_proto = std::vector<uint8_t>();
153     SERIALIZE_AND_RETURN_ASTATUS(put_result, put_result_proto);
154   }
155 
batchPut(const std::vector<uint8_t> & put_document_request_proto,std::optional<std::vector<uint8_t>> * batch_put_result_proto)156   ScopedAStatus batchPut(const std::vector<uint8_t>& put_document_request_proto,
157                          std::optional<std::vector<uint8_t>>* batch_put_result_proto) {
158     CHECK_ICING_INIT(icing_);
159 
160     PutDocumentRequest request;
161     DESERIALIZE_OR_RETURN(put_document_request_proto, request);
162 
163     BatchPutResultProto result = icing_->BatchPut(std::move(request));
164 
165     *batch_put_result_proto = std::vector<uint8_t>();
166     SERIALIZE_AND_RETURN_ASTATUS(result, batch_put_result_proto);
167   }
168 
get(const std::string & name_space,const std::string & uri,const std::vector<uint8_t> & get_result_spec_proto,std::optional<std::vector<uint8_t>> * get_result_proto)169   ScopedAStatus get(const std::string& name_space, const std::string& uri,
170                     const std::vector<uint8_t>& get_result_spec_proto,
171                     std::optional<std::vector<uint8_t>>* get_result_proto) {
172     CHECK_ICING_INIT(icing_);
173 
174     GetResultSpecProto get_result_spec;
175     DESERIALIZE_OR_RETURN(get_result_spec_proto, get_result_spec);
176 
177     GetResultProto get_result = icing_->Get(name_space, uri, get_result_spec);
178     SERIALIZE_AND_RETURN_ASTATUS(get_result, get_result_proto);
179   }
180 
reportUsage(const std::vector<uint8_t> & usage_report_proto,std::optional<std::vector<uint8_t>> * report_usage_result_proto)181   ScopedAStatus reportUsage(
182       const std::vector<uint8_t>& usage_report_proto,
183       std::optional<std::vector<uint8_t>>* report_usage_result_proto) {
184     CHECK_ICING_INIT(icing_);
185 
186     UsageReport usage_report;
187     DESERIALIZE_OR_RETURN(usage_report_proto, usage_report);
188 
189     ReportUsageResultProto report_usage_result =
190         icing_->ReportUsage(usage_report);
191     SERIALIZE_AND_RETURN_ASTATUS(report_usage_result,
192                                  report_usage_result_proto);
193   }
194 
getAllNamespaces(std::optional<std::vector<uint8_t>> * get_all_namespaces_result_proto)195   ScopedAStatus getAllNamespaces(
196       std::optional<std::vector<uint8_t>>* get_all_namespaces_result_proto) {
197     CHECK_ICING_INIT(icing_);
198 
199     GetAllNamespacesResultProto get_all_namespaces_result =
200         icing_->GetAllNamespaces();
201     SERIALIZE_AND_RETURN_ASTATUS(get_all_namespaces_result,
202                                  get_all_namespaces_result_proto);
203   }
204 
search(const std::vector<uint8_t> & search_spec_proto,const std::vector<uint8_t> & scoring_spec_proto,const std::vector<uint8_t> & result_spec_proto,std::optional<std::vector<uint8_t>> * search_result_proto)205   ScopedAStatus search(
206       const std::vector<uint8_t>& search_spec_proto,
207       const std::vector<uint8_t>& scoring_spec_proto,
208       const std::vector<uint8_t>& result_spec_proto,
209       std::optional<std::vector<uint8_t>>* search_result_proto) {
210     CHECK_ICING_INIT(icing_);
211 
212     SearchSpecProto search_spec;
213     DESERIALIZE_OR_RETURN(search_spec_proto, search_spec);
214     ScoringSpecProto scoring_spec;
215     DESERIALIZE_OR_RETURN(scoring_spec_proto, scoring_spec);
216     ResultSpecProto result_spec;
217     DESERIALIZE_OR_RETURN(result_spec_proto, result_spec);
218 
219     SearchResultProto search_result =
220         icing_->Search(search_spec, scoring_spec, result_spec);
221     SERIALIZE_AND_RETURN_ASTATUS(search_result, search_result_proto);
222 
223     return ScopedAStatus::ok();
224   }
225 
getNextPage(int64_t next_page_token,std::optional<std::vector<uint8_t>> * get_next_page_result_proto)226   ScopedAStatus getNextPage(
227       int64_t next_page_token,
228       std::optional<std::vector<uint8_t>>* get_next_page_result_proto) {
229     CHECK_ICING_INIT(icing_);
230 
231     SearchResultProto get_next_page_result =
232         icing_->GetNextPage(next_page_token);
233     SERIALIZE_AND_RETURN_ASTATUS(get_next_page_result,
234                                  get_next_page_result_proto);
235   }
236 
invalidateNextPageToken(int64_t next_page_token)237   ScopedAStatus invalidateNextPageToken(int64_t next_page_token) {
238     CHECK_ICING_INIT(icing_);
239 
240     icing_->InvalidateNextPageToken(next_page_token);
241     return ScopedAStatus::ok();
242   }
243 
openWriteBlob(const std::vector<uint8_t> & blob_handle_proto,std::optional<std::vector<uint8_t>> * blob_proto)244   ScopedAStatus openWriteBlob(const std::vector<uint8_t>& blob_handle_proto,
245                               std::optional<std::vector<uint8_t>>* blob_proto) {
246     CHECK_ICING_INIT(icing_);
247 
248     BlobHandleProto blob_handle;
249     DESERIALIZE_OR_RETURN(blob_handle_proto, blob_handle);
250 
251     BlobProto open_write_blob_result = icing_->OpenWriteBlob(blob_handle);
252     SERIALIZE_AND_RETURN_ASTATUS(open_write_blob_result, blob_proto);
253   }
254 
removeBlob(const std::vector<uint8_t> & blob_handle_proto,std::optional<std::vector<uint8_t>> * blob_proto)255   ScopedAStatus removeBlob(const std::vector<uint8_t>& blob_handle_proto,
256                            std::optional<std::vector<uint8_t>>* blob_proto) {
257     CHECK_ICING_INIT(icing_);
258 
259     BlobHandleProto blob_handle;
260     DESERIALIZE_OR_RETURN(blob_handle_proto, blob_handle);
261 
262     BlobProto remove_blob_result = icing_->RemoveBlob(blob_handle);
263     SERIALIZE_AND_RETURN_ASTATUS(remove_blob_result, blob_proto);
264   }
265 
openReadBlob(const std::vector<uint8_t> & blob_handle_proto,std::optional<std::vector<uint8_t>> * blob_proto)266   ScopedAStatus openReadBlob(const std::vector<uint8_t>& blob_handle_proto,
267                              std::optional<std::vector<uint8_t>>* blob_proto) {
268     CHECK_ICING_INIT(icing_);
269 
270     BlobHandleProto blob_handle;
271     DESERIALIZE_OR_RETURN(blob_handle_proto, blob_handle);
272 
273     BlobProto open_read_blob_result = icing_->OpenReadBlob(blob_handle);
274     SERIALIZE_AND_RETURN_ASTATUS(open_read_blob_result, blob_proto);
275   }
276 
commitBlob(const std::vector<uint8_t> & blob_handle_proto,std::optional<std::vector<uint8_t>> * blob_proto)277   ScopedAStatus commitBlob(const std::vector<uint8_t>& blob_handle_proto,
278                            std::optional<std::vector<uint8_t>>* blob_proto) {
279     CHECK_ICING_INIT(icing_);
280 
281     BlobHandleProto blob_handle;
282     DESERIALIZE_OR_RETURN(blob_handle_proto, blob_handle);
283 
284     BlobProto commit_blob_result = icing_->CommitBlob(blob_handle);
285     SERIALIZE_AND_RETURN_ASTATUS(commit_blob_result, blob_proto);
286   }
287 
deleteDoc(const std::string & name_space,const std::string & uri,std::optional<std::vector<uint8_t>> * delete_result_proto)288   ScopedAStatus deleteDoc(
289       const std::string& name_space, const std::string& uri,
290       std::optional<std::vector<uint8_t>>* delete_result_proto) {
291     CHECK_ICING_INIT(icing_);
292 
293     DeleteResultProto delete_result = icing_->Delete(name_space, uri);
294     SERIALIZE_AND_RETURN_ASTATUS(delete_result, delete_result_proto);
295   }
296 
searchSuggestions(const std::vector<uint8_t> & suggestion_spec_proto,std::optional<std::vector<uint8_t>> * suggestion_response_proto)297   ScopedAStatus searchSuggestions(
298       const std::vector<uint8_t>& suggestion_spec_proto,
299       std::optional<std::vector<uint8_t>>* suggestion_response_proto) {
300     CHECK_ICING_INIT(icing_);
301 
302     SuggestionSpecProto suggestion_spec;
303     DESERIALIZE_OR_RETURN(suggestion_spec_proto, suggestion_spec);
304 
305     SuggestionResponse suggestion_response =
306         icing_->SearchSuggestions(suggestion_spec);
307     SERIALIZE_AND_RETURN_ASTATUS(suggestion_response,
308                                  suggestion_response_proto);
309   }
310 
deleteByNamespace(const std::string & name_space,std::optional<std::vector<uint8_t>> * delete_by_namespace_result_proto)311   ScopedAStatus deleteByNamespace(
312       const std::string& name_space,
313       std::optional<std::vector<uint8_t>>* delete_by_namespace_result_proto) {
314     CHECK_ICING_INIT(icing_);
315 
316     DeleteByNamespaceResultProto delete_by_namespace_result =
317         icing_->DeleteByNamespace(name_space);
318     SERIALIZE_AND_RETURN_ASTATUS(delete_by_namespace_result,
319                                  delete_by_namespace_result_proto);
320   }
321 
deleteBySchemaType(const std::string & schema_type,std::optional<std::vector<uint8_t>> * delete_by_schema_type_result_proto)322   ScopedAStatus deleteBySchemaType(
323       const std::string& schema_type,
324       std::optional<std::vector<uint8_t>>* delete_by_schema_type_result_proto) {
325     CHECK_ICING_INIT(icing_);
326 
327     DeleteBySchemaTypeResultProto delete_by_schema_type_result =
328         icing_->DeleteBySchemaType(schema_type);
329     SERIALIZE_AND_RETURN_ASTATUS(delete_by_schema_type_result,
330                                  delete_by_schema_type_result_proto);
331   }
332 
deleteByQuery(const std::vector<uint8_t> & search_spec_proto,bool return_deleted_document_info,std::optional<std::vector<uint8_t>> * delete_by_query_result_proto)333   ScopedAStatus deleteByQuery(
334       const std::vector<uint8_t>& search_spec_proto,
335       bool return_deleted_document_info,
336       std::optional<std::vector<uint8_t>>* delete_by_query_result_proto) {
337     CHECK_ICING_INIT(icing_);
338 
339     SearchSpecProto search_spec;
340     DESERIALIZE_OR_RETURN(search_spec_proto, search_spec);
341 
342     DeleteByQueryResultProto delete_by_query_result =
343         icing_->DeleteByQuery(search_spec, return_deleted_document_info);
344     SERIALIZE_AND_RETURN_ASTATUS(delete_by_query_result,
345                                  delete_by_query_result_proto);
346   }
347 
persistToDisk(int32_t persist_type_code,std::optional<std::vector<uint8_t>> * persist_to_disk_result_proto)348   ScopedAStatus persistToDisk(
349       int32_t persist_type_code,
350       std::optional<std::vector<uint8_t>>* persist_to_disk_result_proto) {
351     CHECK_ICING_INIT(icing_);
352 
353     PersistToDiskResultProto persist_to_disk_result =
354         icing_->PersistToDisk(PersistType::Code(persist_type_code));
355     SERIALIZE_AND_RETURN_ASTATUS(persist_to_disk_result,
356                                  persist_to_disk_result_proto);
357   }
358 
optimize(std::optional<std::vector<uint8_t>> * optimize_result_proto)359   ScopedAStatus optimize(
360       std::optional<std::vector<uint8_t>>* optimize_result_proto) {
361     CHECK_ICING_INIT(icing_);
362 
363     OptimizeResultProto optimize_result = icing_->Optimize();
364     SERIALIZE_AND_RETURN_ASTATUS(optimize_result, optimize_result_proto);
365   }
366 
getOptimizeInfo(std::optional<std::vector<uint8_t>> * get_optimize_info_result_proto)367   ScopedAStatus getOptimizeInfo(
368       std::optional<std::vector<uint8_t>>* get_optimize_info_result_proto) {
369     CHECK_ICING_INIT(icing_);
370 
371     GetOptimizeInfoResultProto get_optimize_info_result =
372         icing_->GetOptimizeInfo();
373     SERIALIZE_AND_RETURN_ASTATUS(get_optimize_info_result,
374                                  get_optimize_info_result_proto);
375   }
376 
getStorageInfo(std::optional<std::vector<uint8_t>> * get_storage_info_result_proto)377   ScopedAStatus getStorageInfo(
378       std::optional<std::vector<uint8_t>>* get_storage_info_result_proto) {
379     CHECK_ICING_INIT(icing_);
380 
381     StorageInfoResultProto get_storage_info_result = icing_->GetStorageInfo();
382     SERIALIZE_AND_RETURN_ASTATUS(get_storage_info_result,
383                                  get_storage_info_result_proto);
384   }
385 
getDebugInfo(int32_t verbosity,std::optional<std::vector<uint8_t>> * get_debug_info_result_proto)386   ScopedAStatus getDebugInfo(
387       int32_t verbosity,
388       std::optional<std::vector<uint8_t>>* get_debug_info_result_proto) {
389     CHECK_ICING_INIT(icing_);
390 
391     DebugInfoResultProto get_debug_info_result =
392         icing_->GetDebugInfo(DebugInfoVerbosity::Code(verbosity));
393     SERIALIZE_AND_RETURN_ASTATUS(get_debug_info_result,
394                                  get_debug_info_result_proto);
395   }
396 
397  protected:
398   std::unique_ptr<icing::lib::IcingSearchEngine> icing_ = nullptr;
399   uint32_t uid_;
400 };
401 
402 class IsolatedStorageServiceImpl : public BnIsolatedStorageService {
403  public:
404   IsolatedStorageServiceImpl() = default;
405 
406  private:
quit()407   ScopedAStatus quit() override {
408     ICING_LOG(INFO) << "Received quit request, exiting";
409     for (const auto& [unused, connection] : icing_connections_) {
410       connection->close();
411     }
412     exit(0);
413   }
414 
getOrCreateIcingConnection(int32_t uid,std::shared_ptr<aidl::com::android::isolated_storage_service::IIcingSearchEngine> * icing_server)415   ScopedAStatus getOrCreateIcingConnection(
416       int32_t uid,
417       std::shared_ptr<
418           aidl::com::android::isolated_storage_service::IIcingSearchEngine>*
419           icing_server) override {
420     auto connection = icing_connections_.find(uid);
421     if (connection != icing_connections_.end()) {
422       *icing_server = connection->second;
423       return ScopedAStatus::ok();
424     }
425     icing_connections_[uid] =
426         ndk::SharedRefBase::make<IcingConnectionImpl>(uid);
427     *icing_server = icing_connections_[uid];
428     return ScopedAStatus::ok();
429   }
430 
431   std::map<int32_t, std::shared_ptr<IcingConnectionImpl>> icing_connections_;
432 };
433 }  // namespace
434 
AVmPayload_main()435 extern "C" int AVmPayload_main() {
436   ICING_LOG(INFO) << "IsolatedStorageService VM Payload starting";
437   auto service = ndk::SharedRefBase::make<IsolatedStorageServiceImpl>();
438   auto callback = []([[maybe_unused]] void* param) {
439     ICING_LOG(INFO) << "IsolatedStorageService VM Payload ready";
440     AVmPayload_notifyPayloadReady();
441   };
442   AVmPayload_runVsockRpcServer(service->asBinder().get(), service->PORT,
443                                callback, /*param=*/nullptr);
444 }
445