Added broadcast receiver in system server.

The broadcast receiver is registered in a context in the SystemService
AdServicesManagerService.  The broadcast receiver is registered after
the device boots up to avoid receiving broadcasts for changes to system packages
and attempting to call the API before the AdServices services have been registered.

The broadcast receiver listens for only uninstall broadcasts  and calls into
a new AIDL API in the AdServices process to tell the AdServices process about the
app uninstallation.

On uninstall the AdServices process will only delete app records from
measurement tables.

Test: manually uninstalled app to check broadcast.
Change-Id: Id3731fb2941bbe4aac0f4e8faf54bfbf2998ed20

Change-Id: Ib8144c3cab889e9e26ae54de05c29f2fda9b6bfe
diff --git a/adservices/apk/AndroidManifest.xml b/adservices/apk/AndroidManifest.xml
index 9d7af59..b5c3361 100644
--- a/adservices/apk/AndroidManifest.xml
+++ b/adservices/apk/AndroidManifest.xml
@@ -105,6 +105,15 @@
             </intent-filter>
         </service>
 
+        <service android:name="com.android.adservices.common.AdServicesCommonService"
+                 android:exported="true"
+                 android:visibleToInstantApps="false"
+             >
+            <intent-filter>
+                <action android:name="android.adservices.AD_SERVICES_COMMON_SERVICE"/>
+            </intent-filter>
+        </service>
+
         <!-- Daily maintenance Job. -->
         <service android:name="com.android.adservices.service.MaintenanceJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE">
diff --git a/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java b/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java
new file mode 100644
index 0000000..e81f450
--- /dev/null
+++ b/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 com.android.adservices.common;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import com.android.adservices.service.common.AdServicesCommonServiceImpl;
+
+import java.util.Objects;
+
+/** Common service for work that applies to all PPAPIs. */
+public class AdServicesCommonService extends Service {
+
+    /** The binder service. This field must only be accessed on the main thread. */
+    private AdServicesCommonServiceImpl mAdServicesCommonService;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        if (mAdServicesCommonService == null) {
+            mAdServicesCommonService =
+                    new AdServicesCommonServiceImpl(this);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return Objects.requireNonNull(mAdServicesCommonService);
+    }
+}
diff --git a/adservices/framework/java/android/adservices/AdServicesFrameworkInitializer.java b/adservices/framework/java/android/adservices/AdServicesFrameworkInitializer.java
index 0134e6a..14d0609 100644
--- a/adservices/framework/java/android/adservices/AdServicesFrameworkInitializer.java
+++ b/adservices/framework/java/android/adservices/AdServicesFrameworkInitializer.java
@@ -17,11 +17,13 @@
 package android.adservices;
 
 import static android.adservices.adselection.AdSelectionManager.AD_SELECTION_SERVICE;
+import static android.adservices.common.AdServicesCommonManager.AD_SERVICES_COMMON_SERVICE;
 import static android.adservices.customaudience.CustomAudienceManager.CUSTOM_AUDIENCE_SERVICE;
 import static android.adservices.measurement.MeasurementManager.MEASUREMENT_SERVICE;
 import static android.adservices.topics.TopicsManager.TOPICS_SERVICE;
 
 import android.adservices.adselection.AdSelectionManager;
+import android.adservices.common.AdServicesCommonManager;
 import android.adservices.customaudience.CustomAudienceManager;
 import android.adservices.measurement.MeasurementManager;
 import android.adservices.topics.TopicsManager;
@@ -69,5 +71,10 @@
         SystemServiceRegistry.registerContextAwareService(
                 MEASUREMENT_SERVICE, MeasurementManager.class,
                 (c) -> new MeasurementManager(c));
+
+        LogUtil.d("Registering AdServices's AdServicesCommonManager.");
+        SystemServiceRegistry.registerContextAwareService(AD_SERVICES_COMMON_SERVICE,
+                AdServicesCommonManager.class,
+                (c) -> new AdServicesCommonManager(c));
     }
 }
diff --git a/adservices/framework/java/android/adservices/common/AdServicesCommonManager.java b/adservices/framework/java/android/adservices/common/AdServicesCommonManager.java
new file mode 100644
index 0000000..e58d5ca
--- /dev/null
+++ b/adservices/framework/java/android/adservices/common/AdServicesCommonManager.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 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.adservices.common;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.Uri;
+import android.os.RemoteException;
+
+import com.android.adservices.AdServicesCommon;
+import com.android.adservices.LogUtil;
+import com.android.adservices.ServiceBinder;
+
+/**
+ * AdServicesCommonManager class.
+ * Ths contains APIs common across the various PPAPIs.
+ * @hide
+ */
+public class AdServicesCommonManager {
+    public static final String AD_SERVICES_COMMON_SERVICE =
+            "ad_services_common_service";
+
+    private final Context mContext;
+    private final ServiceBinder<IAdServicesCommonService>
+            mAdServicesCommonServiceBinder;
+
+    /**
+     * Create AdServicesCommonManager.
+     * @hide
+     */
+    public AdServicesCommonManager(@NonNull Context context) {
+        mContext = context;
+        mAdServicesCommonServiceBinder = ServiceBinder.getServiceBinder(
+                context,
+                AdServicesCommon.ACTION_AD_SERVICES_COMMON_SERVICE,
+                IAdServicesCommonService.Stub::asInterface);
+    }
+
+    @NonNull
+    private IAdServicesCommonService getService() {
+        IAdServicesCommonService service =
+                mAdServicesCommonServiceBinder.getService();
+        if (service == null) {
+            throw new IllegalStateException("Unable to find the service");
+        }
+        return service;
+    }
+
+    /**
+     * Delete a package's records.
+     * @hide
+     */
+    public void onPackageFullyRemoved(@NonNull Uri packageUri) {
+        final IAdServicesCommonService service = getService();
+        try {
+            service.onPackageFullyRemoved(packageUri);
+        } catch (RemoteException e) {
+            LogUtil.e("RemoteException", e);
+        } finally {
+            mAdServicesCommonServiceBinder.unbindFromService();
+        }
+    }
+}
diff --git a/adservices/framework/java/android/adservices/common/IAdServicesCommonService.aidl b/adservices/framework/java/android/adservices/common/IAdServicesCommonService.aidl
new file mode 100644
index 0000000..a15d5a9
--- /dev/null
+++ b/adservices/framework/java/android/adservices/common/IAdServicesCommonService.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 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.adservices.common;
+
+import android.net.Uri;
+
+/**
+  * Common AdServices service for updating data based on received Package Manager broadcasts.
+  * {@hide}
+  */
+interface IAdServicesCommonService {
+    oneway void onPackageFullyRemoved(in Uri packageUri);
+}
diff --git a/adservices/framework/java/com/android/adservices/AdServicesCommon.java b/adservices/framework/java/com/android/adservices/AdServicesCommon.java
index 0c00594..731b9e8 100644
--- a/adservices/framework/java/com/android/adservices/AdServicesCommon.java
+++ b/adservices/framework/java/com/android/adservices/AdServicesCommon.java
@@ -37,4 +37,8 @@
     /** Intent action to discover the Measurement service in the APK. */
     public static final String ACTION_MEASUREMENT_SERVICE =
             "android.adservices.MEASUREMENT_SERVICE";
+
+    /** Intent action to discover the AdServicesCommon service in the APK. */
+    public static final String ACTION_AD_SERVICES_COMMON_SERVICE =
+            "android.adservices.AD_SERVICES_COMMON_SERVICE";
 }
diff --git a/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java b/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
index c2ae518..2208f41 100644
--- a/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
+++ b/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
@@ -16,6 +16,7 @@
 package com.android.adservices;
 
 import static com.android.adservices.AdServicesCommon.ACTION_AD_SELECTION_SERVICE;
+import static com.android.adservices.AdServicesCommon.ACTION_AD_SERVICES_COMMON_SERVICE;
 import static com.android.adservices.AdServicesCommon.ACTION_CUSTOM_AUDIENCE_SERVICE;
 import static com.android.adservices.AdServicesCommon.ACTION_MEASUREMENT_SERVICE;
 import static com.android.adservices.AdServicesCommon.ACTION_TOPICS_SERVICE;
@@ -178,7 +179,8 @@
         if (!mServiceIntentAction.equals(ACTION_TOPICS_SERVICE)
                 && !mServiceIntentAction.equals(ACTION_MEASUREMENT_SERVICE)
                 && !mServiceIntentAction.equals(ACTION_CUSTOM_AUDIENCE_SERVICE)
-                && !mServiceIntentAction.equals(ACTION_AD_SELECTION_SERVICE)) {
+                && !mServiceIntentAction.equals(ACTION_AD_SELECTION_SERVICE)
+                && !mServiceIntentAction.equals(ACTION_AD_SERVICES_COMMON_SERVICE)) {
             LogUtil.e("Bad service intent action: " + mServiceIntentAction);
             return null;
         }
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java
new file mode 100644
index 0000000..a8d6aab
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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 com.android.adservices.service.common;
+
+import android.adservices.common.IAdServicesCommonService;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.adservices.LogUtil;
+import com.android.adservices.service.AdServicesExecutors;
+import com.android.adservices.service.measurement.MeasurementImpl;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of {@link IAdServicesCommonService}.
+ *
+ * @hide
+ */
+public class AdServicesCommonServiceImpl extends
+        IAdServicesCommonService.Stub {
+    private final MeasurementImpl mMeasurementImpl;
+    private static final Executor sBackgroundExecutor = AdServicesExecutors.getBackgroundExecutor();
+
+    public AdServicesCommonServiceImpl(Context context) {
+        mMeasurementImpl = MeasurementImpl.getInstance(context);
+    }
+
+    @Override
+    public void onPackageFullyRemoved(@NonNull Uri packageUri) {
+        Objects.requireNonNull(packageUri);
+        measurementOnPackageFullyRemoved(packageUri);
+    }
+
+    private void measurementOnPackageFullyRemoved(@NonNull Uri packageUri) {
+        LogUtil.d("Deleting package measurement records for package: " + packageUri.toString());
+        sBackgroundExecutor.execute(() -> {
+            mMeasurementImpl.deletePackageRecords(packageUri);
+        });
+    }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/MeasurementImpl.java b/adservices/service-core/java/com/android/adservices/service/measurement/MeasurementImpl.java
index 0be416f..4ad143f 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/MeasurementImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/MeasurementImpl.java
@@ -65,6 +65,8 @@
     private final TriggerFetcher mTriggerFetcher;
     private final ContentResolver mContentResolver;
 
+    private static final String ANDROID_APP_SCHEME = "android-app://";
+
     private MeasurementImpl(Context context) {
         mContentResolver = context.getContentResolver();
         mDatastoreManager = DatastoreManagerFactory.getDatastoreManager(context);
@@ -88,7 +90,7 @@
      * existing instance will be returned.
      */
     @NonNull
-    static MeasurementImpl getInstance(Context context) {
+    public static MeasurementImpl getInstance(Context context) {
         if (sMeasurementImpl == null) {
             synchronized (MeasurementImpl.class) {
                 if (sMeasurementImpl == null) {
@@ -162,6 +164,22 @@
         }
     }
 
+    /**
+     * Delete all records from a specific package.
+     */
+    public void deletePackageRecords(Uri packageUri) {
+        Uri appUri = getAppUri(packageUri);
+        LogUtil.i("Deleting records for " + appUri);
+        mReadWriteLock.writeLock().lock();
+        try {
+            mDatastoreManager.runInTransaction((dao) ->
+                    dao.deleteAppRecords(appUri));
+        } catch (NullPointerException | IllegalArgumentException e) {
+            LogUtil.e(e, "Delete package records received invalid parameters");
+        } finally {
+            mReadWriteLock.writeLock().unlock();
+        }
+    }
     private void insertSources(
             @NonNull RegistrationRequest request,
             ArrayList<SourceRegistration> responseBasedRegistrations,
@@ -255,6 +273,10 @@
 
     private Uri getRegistrant(AttributionSource attributionSource) {
         return Uri.parse(
-                "android-app://" + attributionSource.getPackageName());
+                ANDROID_APP_SCHEME + attributionSource.getPackageName());
+    }
+
+    private Uri getAppUri(Uri packageUri) {
+        return Uri.parse(ANDROID_APP_SCHEME + packageUri.getEncodedSchemeSpecificPart());
     }
 }
diff --git a/adservices/service/Android.bp b/adservices/service/Android.bp
index 6fe6ea9..6b75dcc 100644
--- a/adservices/service/Android.bp
+++ b/adservices/service/Android.bp
@@ -33,6 +33,9 @@
     sdk_version: "system_server_current",
     min_sdk_version: "Tiramisu",
     permitted_packages: ["com.android.server.adservices"],
+    libs: [
+        "framework-adservices.impl",
+    ],
     defaults: ["framework-system-server-module-defaults"],
     visibility: [
         "//packages/modules/AdServices/tests:__subpackages__",
diff --git a/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java b/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
index def32bd..6e2418a 100644
--- a/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
+++ b/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
@@ -15,7 +15,14 @@
  */
 package com.android.server.adservices;
 
+import android.adservices.common.AdServicesCommonManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.util.Log;
 
 import com.android.server.SystemService;
@@ -25,26 +32,80 @@
  */
 public class AdServicesManagerService {
     private static final String TAG = "AdServicesManagerService";
-
     private final Context mContext;
 
+    private final Handler mHandler;
+
     private AdServicesManagerService(Context context) {
         mContext = context;
+
+        // Start the handler thread.
+        HandlerThread handlerThread = new HandlerThread("AdServicesManagerServiceHandler");
+        handlerThread.start();
+        mHandler = new Handler(handlerThread.getLooper());
+        registerBootBroadcastReceivers();
     }
 
     /** @hide */
     public static class Lifecycle extends SystemService {
+        private AdServicesManagerService mService;
+
         /** @hide */
         public Lifecycle(Context context) {
             super(context);
+            mService = new AdServicesManagerService(getContext());
         }
 
         /** @hide */
         @Override
         public void onStart() {
-            AdServicesManagerService service =
-                    new AdServicesManagerService(getContext());
-            Log.i(TAG, "AdServicesManagerService started!");
+            Log.d(TAG, "AdServicesManagerService started!");
         }
     }
+
+    private void registerBootBroadcastReceivers() {
+        BroadcastReceiver bootIntentReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                switch(intent.getAction()) {
+                    case Intent.ACTION_BOOT_COMPLETED:
+                        registerPackagedChangedBroadcastReceivers();
+                }
+            }
+        };
+        mContext.registerReceiver(bootIntentReceiver,
+                new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+        Log.d(TAG, "Boot Broadcast Receivers registered.");
+    }
+
+    private void registerPackagedChangedBroadcastReceivers() {
+        final IntentFilter packageChangedIntentFilter = new IntentFilter();
+
+        packageChangedIntentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+        // TODO(b/229412239): Add other actions.
+        packageChangedIntentFilter.addDataScheme("package");
+
+        BroadcastReceiver packageChangedIntentReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.d(TAG, "Received for intent: " + intent);
+                switch(intent.getAction()) {
+                    case Intent.ACTION_PACKAGE_FULLY_REMOVED:
+                        Uri packageUri = intent.getData();
+                        Log.d(TAG, "Removed package: " + packageUri.toString());
+                        onPackageFullyRemoved(packageUri);
+                    // TODO(b/229412239): Add other actions.
+                }
+            }
+        };
+        mContext.registerReceiver(packageChangedIntentReceiver, packageChangedIntentFilter,
+                null, mHandler);
+        Log.d(TAG, "Package changed Broadcast Receivers registered.");
+    }
+
+    private void onPackageFullyRemoved(Uri packageUri) {
+        mHandler.post(() -> mContext.getSystemService(AdServicesCommonManager.class)
+                .onPackageFullyRemoved(packageUri));
+
+    }
 }