1 /*
2  * Copyright (C) 2021 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 
17 package com.android.server.appsearch.observer;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.appsearch.aidl.IAppSearchObserverProxy;
22 import android.app.appsearch.observer.DocumentChangeInfo;
23 import android.app.appsearch.observer.ObserverCallback;
24 import android.app.appsearch.observer.SchemaChangeInfo;
25 import android.os.RemoteException;
26 import android.util.Log;
27 
28 import java.util.ArrayList;
29 import java.util.Objects;
30 
31 /**
32  * A wrapper that adapts {@link android.app.appsearch.aidl.IAppSearchObserverProxy} to the {@link
33  * android.app.appsearch.observer.ObserverCallback} interface.
34  *
35  * <p>When using this class, you must register for {@link android.os.IBinder#linkToDeath}
36  * notifications on the stub you provide to the constructor, to unregister this class from {@link
37  * com.android.server.appsearch.external.localstorage.AppSearchImpl} when binder dies.
38  *
39  * @hide
40  */
41 public class AppSearchObserverProxy implements ObserverCallback {
42     private static final String TAG = "AppSearchObserverProxy";
43 
44     private final IAppSearchObserverProxy mStub;
45 
AppSearchObserverProxy(@onNull IAppSearchObserverProxy stub)46     public AppSearchObserverProxy(@NonNull IAppSearchObserverProxy stub) {
47         mStub = Objects.requireNonNull(stub);
48     }
49 
50     @Override
onSchemaChanged(@onNull SchemaChangeInfo changeInfo)51     public void onSchemaChanged(@NonNull SchemaChangeInfo changeInfo) {
52         try {
53             mStub.onSchemaChanged(
54                     changeInfo.getPackageName(),
55                     changeInfo.getDatabaseName(),
56                     new ArrayList<>(changeInfo.getChangedSchemaNames()));
57         } catch (RemoteException e) {
58             onRemoteException(e);
59         }
60     }
61 
62     @Override
onDocumentChanged(@onNull DocumentChangeInfo changeInfo)63     public void onDocumentChanged(@NonNull DocumentChangeInfo changeInfo) {
64         try {
65             mStub.onDocumentChanged(
66                     changeInfo.getPackageName(),
67                     changeInfo.getDatabaseName(),
68                     changeInfo.getNamespace(),
69                     changeInfo.getSchemaName(),
70                     new ArrayList<>(changeInfo.getChangedDocumentIds()));
71         } catch (RemoteException e) {
72             onRemoteException(e);
73         }
74     }
75 
onRemoteException(@onNull RemoteException e)76     private void onRemoteException(@NonNull RemoteException e) {
77         // The originating app has disconnected. The user of this class must watch for binder
78         // disconnections and unregister us, so we don't have to take any special action.
79         Log.w(TAG, "AppSearchObserver failed to fire; stub disconnected", e);
80     }
81 
82     @Override
equals(@ullable Object o)83     public boolean equals(@Nullable Object o) {
84         if (this == o) {
85             return true;
86         }
87         if (!(o instanceof AppSearchObserverProxy)) {
88             return false;
89         }
90         AppSearchObserverProxy that = (AppSearchObserverProxy) o;
91         return Objects.equals(mStub.asBinder(), that.mStub.asBinder());
92     }
93 
94     @Override
hashCode()95     public int hashCode() {
96         return Objects.hashCode(mStub.asBinder());
97     }
98 }
99