From 08b45d35182271376a1823d0750d4655e54909d2 Mon Sep 17 00:00:00 2001
From: Oliver Scott <olivercscott@gmail.com>
Date: Mon, 25 Jan 2021 14:36:29 -0500
Subject: [PATCH] Add shared library packages to app cache database using
 F-DroidPrivilegedExtension query

https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java;l=4725?q=filterSharedLibPackageLPr&sq=
PackageManager filters some packages from getInstalledPackages if the calling uid is not root, shell or system or does not have install permissions granted. Additionally, the hidden MATCH_STATIC_SHARED_LIBRARIES flag must be set.
https://review.calyxos.org/c/CalyxOS/platform_packages_apps_F-DroidPrivilegedExtension/+/2305
We added an API call in F-DroidPrivilegedExtension given it has the necessary requirements to get the unfiltered results from getInstalledPackages. This allows shared library packages to be added to the app cache database which will allow F-Droid to update them
---
 .../fdroid/privileged/IPrivilegedService.aidl |  2 +
 .../data/InstalledAppProviderService.java     | 61 ++++++++++++++++---
 .../fdroid/installer/PrivilegedInstaller.java |  2 +-
 3 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/app/src/main/aidl/org/fdroid/fdroid/privileged/IPrivilegedService.aidl b/app/src/main/aidl/org/fdroid/fdroid/privileged/IPrivilegedService.aidl
index 5c1724b1d..8592196d0 100644
--- a/app/src/main/aidl/org/fdroid/fdroid/privileged/IPrivilegedService.aidl
+++ b/app/src/main/aidl/org/fdroid/fdroid/privileged/IPrivilegedService.aidl
@@ -63,4 +63,6 @@ interface IPrivilegedService {
      */
     oneway void deletePackage(in String packageName, in int flags, in IPrivilegedCallback callback);
 
+    List<PackageInfo> getInstalledPackages(in int flags);
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java
index d3113392e..d6c6ea08e 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java
@@ -1,23 +1,28 @@
 package org.fdroid.fdroid.data;
 
+import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.net.Uri;
+import android.os.IBinder;
 import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.core.app.JobIntentService;
-import android.util.Log;
+
 import org.acra.ACRA;
 import org.fdroid.fdroid.AppUpdateStatusManager;
 import org.fdroid.fdroid.Utils;
 import org.fdroid.fdroid.data.Schema.InstalledAppTable;
-import rx.functions.Action1;
-import rx.schedulers.Schedulers;
-import rx.subjects.PublishSubject;
+import org.fdroid.fdroid.installer.PrivilegedInstaller;
+import org.fdroid.fdroid.privileged.IPrivilegedService;
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -27,6 +32,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import rx.subjects.PublishSubject;
+
 /**
  * Handles all updates to {@link InstalledAppProvider}, whether checking the contents
  * versus what Android says is installed, or processing {@link Intent}s that come
@@ -174,12 +183,48 @@ public class InstalledAppProviderService extends JobIntentService {
      *
      * @see <a href="https://gitlab.com/fdroid/fdroidclient/issues/819>issue #819</a>
      */
-    public static void compareToPackageManager(Context context) {
+    public static void compareToPackageManager(final Context context) {
         Utils.debugLog(TAG, "Comparing package manager to our installed app cache.");
-        Map<String, Long> cachedInfo = InstalledAppProvider.Helper.lastUpdateTimes(context);
 
-        List<PackageInfo> packageInfoList = context.getPackageManager()
-                .getInstalledPackages(PackageManager.GET_SIGNATURES);
+        if (PrivilegedInstaller.isExtensionInstalledCorrectly(context) == PrivilegedInstaller.IS_EXTENSION_INSTALLED_YES) {
+            ServiceConnection mServiceConnection = new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName name, IBinder service) {
+                    IPrivilegedService privService = IPrivilegedService.Stub.asInterface(service);
+                    List<PackageInfo> packageInfoList = null;
+                    try {
+                        packageInfoList =
+                                privService.getInstalledPackages(PackageManager.GET_SIGNATURES);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "RemoteException", e);
+                    } finally {
+                        compareToPackageManager(context, packageInfoList);
+                    }
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName componentName) {
+                    // Nothing to tear down from onServiceConnected
+                }
+            };
+
+            Intent serviceIntent = new Intent(PrivilegedInstaller.PRIVILEGED_EXTENSION_SERVICE_INTENT);
+            serviceIntent.setPackage(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME);
+            context.getApplicationContext().bindService(serviceIntent, mServiceConnection,
+                    Context.BIND_AUTO_CREATE);
+        } else {
+            List<PackageInfo> packageInfoList = context.getPackageManager()
+                    .getInstalledPackages(PackageManager.GET_SIGNATURES);
+            compareToPackageManager(context, packageInfoList);
+        }
+    }
+
+    private static void compareToPackageManager(Context context, List<PackageInfo> packageInfoList) {
+        if (packageInfoList == null || packageInfoList.isEmpty()) {
+            packageInfoList = context.getPackageManager()
+                    .getInstalledPackages(PackageManager.GET_SIGNATURES);
+        }
+        Map<String, Long> cachedInfo = InstalledAppProvider.Helper.lastUpdateTimes(context);
         Collections.sort(packageInfoList, new Comparator<PackageInfo>() {
             @Override
             public int compare(PackageInfo o1, PackageInfo o2) {
diff --git a/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java
index 47e26c817..a60c804d4 100644
--- a/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java
+++ b/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java
@@ -66,7 +66,7 @@ public class PrivilegedInstaller extends Installer {
 
     private static final String TAG = "PrivilegedInstaller";
 
-    private static final String PRIVILEGED_EXTENSION_SERVICE_INTENT
+    public static final String PRIVILEGED_EXTENSION_SERVICE_INTENT
             = "org.fdroid.fdroid.privileged.IPrivilegedService";
     public static final String PRIVILEGED_EXTENSION_PACKAGE_NAME = BuildConfig.PRIVILEGED_EXTENSION_PACKAGE_NAME;