Added IContentCaptureServiceCallback.

This binder object will be used to implement the ContentCaptureService methods that require calls to
system server.

Bug: 122595322
Test: atest CtsContentCaptureServiceTestCases

Change-Id: If918af540f78777d00970e0fc75df458aad168b7
diff --git a/Android.bp b/Android.bp
index 7e97e66..6cdbeb0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -305,6 +305,7 @@
         "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
         "core/java/android/service/gatekeeper/IGateKeeperService.aidl",
         "core/java/android/service/contentcapture/IContentCaptureService.aidl",
+        "core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl",
         "core/java/android/service/notification/INotificationListener.aidl",
         "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
         "core/java/android/service/notification/IConditionListener.aidl",
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index e5e028d..bedd2a0 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -48,6 +48,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -77,6 +78,7 @@
             "android.service.contentcapture.ContentCaptureService";
 
     private Handler mHandler;
+    private IContentCaptureServiceCallback mCallback;
 
     /**
      * Binder that receives calls from the system server.
@@ -84,9 +86,15 @@
     private final IContentCaptureService mServerInterface = new IContentCaptureService.Stub() {
 
         @Override
-        public void onConnectedStateChanged(boolean state) {
-            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnConnectedStateChanged,
-                    ContentCaptureService.this, state));
+        public void onConnected(IBinder callback) {
+            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnConnected,
+                    ContentCaptureService.this, callback));
+        }
+
+        @Override
+        public void onDisconnected() {
+            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnDisconnected,
+                    ContentCaptureService.this));
         }
 
         @Override
@@ -166,7 +174,16 @@
      */
     public final void setContentCaptureWhitelist(@Nullable List<String> packages,
             @Nullable List<ComponentName> activities) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setContentCaptureWhitelist(): no server callback");
+            return;
+        }
+        try {
+            callback.setContentCaptureWhitelist(packages, activities);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -177,7 +194,16 @@
      */
     public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
             boolean enabled) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setActivityContentCaptureEnabled(): no server callback");
+            return;
+        }
+        try {
+            callback.setActivityContentCaptureEnabled(activity, enabled);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -188,7 +214,16 @@
      */
     public final void setPackageContentCaptureEnabled(@NonNull String packageName,
             boolean enabled) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setPackageContentCaptureEnabled(): no server callback");
+            return;
+        }
+        try {
+            callback.setPackageContentCaptureEnabled(packageName, enabled);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -197,7 +232,12 @@
      */
     @NonNull
     public final Set<ComponentName> getContentCaptureDisabledActivities() {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "getContentCaptureDisabledActivities(): no server callback");
+            return Collections.emptySet();
+        }
+        //TODO(b/122595322): implement (using SyncResultReceiver)
         return null;
     }
 
@@ -207,7 +247,12 @@
      */
     @NonNull
     public final Set<String> getContentCaptureDisabledPackages() {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "getContentCaptureDisabledPackages(): no server callback");
+            return Collections.emptySet();
+        }
+        //TODO(b/122595322): implement (using SyncResultReceiver)
         return null;
     }
 
@@ -307,12 +352,14 @@
         }
     }
 
-    private void handleOnConnectedStateChanged(boolean state) {
-        if (state) {
-            onConnected();
-        } else {
-            onDisconnected();
-        }
+    private void handleOnConnected(@NonNull IBinder callback) {
+        mCallback = IContentCaptureServiceCallback.Stub.asInterface(callback);
+        onConnected();
+    }
+
+    private void handleOnDisconnected() {
+        onDisconnected();
+        mCallback = null;
     }
 
     //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index 1b4cccf..a8dd213 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -16,6 +16,7 @@
 
 package android.service.contentcapture;
 
+import android.os.IBinder;
 import android.service.contentcapture.SnapshotData;
 import android.view.contentcapture.ContentCaptureContext;
 
@@ -29,7 +30,8 @@
  * @hide
  */
 oneway interface IContentCaptureService {
-    void onConnectedStateChanged(boolean state);
+    void onConnected(IBinder callback);
+    void onDisconnected();
     void onSessionStarted(in ContentCaptureContext context, String sessionId, int uid,
                           in IResultReceiver clientReceiver);
     void onSessionFinished(String sessionId);
diff --git a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
new file mode 100644
index 0000000..e84bd6f
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.content.ComponentName;
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * Interface from the Content Capture service to the system.
+ *
+ * @hide
+ */
+oneway interface IContentCaptureServiceCallback {
+    void setContentCaptureWhitelist(in List<String> packages, in List<ComponentName> activities);
+    void setActivityContentCaptureEnabled(in ComponentName activity, boolean enabled);
+    void setPackageContentCaptureEnabled(in String packageName, boolean enabled);
+    void getContentCaptureDisabledActivities(in IResultReceiver receiver);
+    void getContentCaptureDisabledPackages(in IResultReceiver receiver);
+}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 09aa421..e0aa23d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -36,8 +36,10 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 import android.view.contentcapture.ContentCaptureSession;
 
@@ -48,6 +50,7 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Per-user instance of {@link ContentCaptureManagerService}.
@@ -72,6 +75,9 @@
     @GuardedBy("mLock")
     private RemoteContentCaptureService mRemoteService;
 
+    private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
+            new ContentCaptureServiceRemoteCallback();
+
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
     ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@@ -100,10 +106,10 @@
         }
 
         if (!disabled) {
-            mRemoteService = new RemoteContentCaptureService(
-                  mMaster.getContext(),
-                  ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, mUserId, this,
-                  mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+            mRemoteService = new RemoteContentCaptureService(mMaster.getContext(),
+                    ContentCaptureService.SERVICE_INTERFACE, serviceComponentName,
+                    mRemoteServiceCallback, mUserId, this, mMaster.isBindInstantServiceAllowed(),
+                    mMaster.verbose);
         }
     }
 
@@ -338,4 +344,50 @@
         }
         return null;
     }
+
+    private final class ContentCaptureServiceRemoteCallback extends
+            IContentCaptureServiceCallback.Stub {
+
+        @Override
+        public void setContentCaptureWhitelist(List<String> packages,
+                List<ComponentName> activities) {
+            if (mMaster.verbose) {
+                Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+                        + activities + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void setActivityContentCaptureEnabled(ComponentName activity, boolean enabled) {
+            if (mMaster.verbose) {
+                Log.v(TAG, "setActivityContentCaptureEnabled(activity=" + activity + ", enabled="
+                        + enabled + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void setPackageContentCaptureEnabled(String packageName, boolean enabled) {
+            if (mMaster.verbose) {
+                Log.v(TAG,
+                        "setPackageContentCaptureEnabled(packageName=" + packageName + ", enabled="
+                                + enabled + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void getContentCaptureDisabledActivities(IResultReceiver receiver) {
+            // TODO(b/122595322): implement
+        }
+
+        @Override
+        public void getContentCaptureDisabledPackages(IResultReceiver receiver) {
+            // TODO(b/122595322): implement
+        }
+    }
 }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 82416286..12742ca 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.text.format.DateUtils;
 import android.util.Slog;
@@ -35,12 +36,15 @@
 
     private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
 
+    private final IBinder mServerCallback;
+
     RemoteContentCaptureService(Context context, String serviceInterface,
-            ComponentName componentName, int userId,
+            ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
             ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
             boolean verbose) {
-        super(context, serviceInterface, componentName, userId, callbacks,
+        super(context, serviceInterface, serviceComponentName, userId, callbacks,
                 bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+        mServerCallback = callback.asBinder();
 
         // Bind right away, which will trigger a onConnected() on service's
         scheduleBind();
@@ -69,7 +73,11 @@
             scheduleUnbind();
         }
         try {
-            mService.onConnectedStateChanged(state);
+            if (state) {
+                mService.onConnected(mServerCallback);
+            } else {
+                mService.onDisconnected();
+            }
         } catch (Exception e) {
             Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e);
         }