1 /*
2  * Copyright (C) 2022 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.adservices.data.adselection;
18 
19 import android.adservices.common.AdTechIdentifier;
20 import android.content.pm.PackageManager;
21 
22 import androidx.annotation.NonNull;
23 import androidx.room.Dao;
24 import androidx.room.Insert;
25 import androidx.room.OnConflictStrategy;
26 import androidx.room.Query;
27 import androidx.room.Transaction;
28 
29 import com.android.adservices.data.common.CleanupUtils;
30 import com.android.adservices.service.Flags;
31 
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Objects;
35 
36 /**
37  * Data access object abstract class for running app install related queries.
38  *
39  * <p>Annotation will generate Room based SQLite Dao implementation.
40  */
41 @Dao
42 public abstract class AppInstallDao {
43 
44     /**
45      * Checks if a buyer is allowed to filter a given package.
46      *
47      * @param buyer the name of the buyer.
48      * @param packageName the name of the package.
49      * @return true if the (buyer, package name) pair is in the database, false otherwise
50      */
51     @Query(
52             "SELECT EXISTS(SELECT 1 FROM app_install WHERE buyer = :buyer"
53                     + " AND package_name = :packageName)")
canBuyerFilterPackage( @onNull AdTechIdentifier buyer, @NonNull String packageName)54     public abstract boolean canBuyerFilterPackage(
55             @NonNull AdTechIdentifier buyer, @NonNull String packageName);
56 
57     /**
58      * Insert new buyer, package pairs which will allow the buyer to filter on the package. If the
59      * entry already exists, nothing is inserted or changed.
60      *
61      * @param appInstalls The buyer, package pairs to insert
62      */
63     @Insert(onConflict = OnConflictStrategy.IGNORE)
insertAllAppInstallPermissions( @onNull List<DBAppInstallPermissions> appInstalls)64     protected abstract void insertAllAppInstallPermissions(
65             @NonNull List<DBAppInstallPermissions> appInstalls);
66 
67     /**
68      * Get all the packages names with app install data.
69      *
70      * @return A list of all packages with entries in the app install table.
71      */
72     @Query("SELECT package_name FROM app_install")
getAllPackageNames()73     protected abstract List<String> getAllPackageNames();
74 
75     /**
76      * Removes all entries associated with any package in the given list.
77      *
78      * @param packageNames the list of packages.
79      */
80     @Query("DELETE FROM app_install WHERE package_name IN (:packageNames)")
deleteByPackageNames(@onNull List<String> packageNames)81     protected abstract int deleteByPackageNames(@NonNull List<String> packageNames);
82 
83     /**
84      * Removes all entries associated with a package
85      *
86      * @param packageName The name of the package.
87      */
88     @Query("DELETE FROM app_install WHERE package_name = :packageName")
deleteByPackageName(@onNull String packageName)89     public abstract int deleteByPackageName(@NonNull String packageName);
90 
91     /** Deletes ALL app install data from the database. */
92     @Query("DELETE FROM app_install")
deleteAllAppInstallData()93     public abstract void deleteAllAppInstallData();
94 
95     /**
96      * Runs deleteByPackageName on the given packagename then insertAllAppInstallPermissions on the
97      * given list of DBAppInstallPermissions in a single transaction. Note that there is no that the
98      * package/packages in the DBAppInstallPermissions match the packageName parameter.
99      *
100      * @param packageName The package name to clear all entries for
101      * @param appInstalls The DBAppInstallPermissions to insert
102      */
103     @Transaction
setAdTechsForPackage( @onNull String packageName, @NonNull List<DBAppInstallPermissions> appInstalls)104     public void setAdTechsForPackage(
105             @NonNull String packageName, @NonNull List<DBAppInstallPermissions> appInstalls) {
106         deleteByPackageName(packageName);
107         insertAllAppInstallPermissions(appInstalls);
108     }
109 
110     /**
111      * Deletes all app install data belonging to disallowed packages in a single transaction.
112      *
113      * <p>Disallowed means package cannot be found in the installed list or that the package is not
114      * found in the ppapi allowlist.
115      *
116      * <p>TODO(b/272537512): Consider returning more information
117      *
118      * @return the number of entries removed
119      */
120     @Transaction
121     @NonNull
deleteAllDisallowedPackageEntries( @onNull PackageManager packageManager, @NonNull Flags flags)122     public int deleteAllDisallowedPackageEntries(
123             @NonNull PackageManager packageManager, @NonNull Flags flags) {
124         Objects.requireNonNull(packageManager);
125         Objects.requireNonNull(flags);
126 
127         List<String> packagesToRemove = getAllPackageNames();
128         CleanupUtils.removeAllowedPackages(
129                 packagesToRemove,
130                 packageManager,
131                 Arrays.asList(flags.getPpapiAppAllowList(), flags.getPasAppAllowList()));
132         if (packagesToRemove.isEmpty()) {
133             return 0;
134         }
135         return deleteByPackageNames(packagesToRemove);
136     }
137 }
138