Merge "Add package information to association sources."
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1b45d17..497e193c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6152,7 +6152,7 @@
         try {
             synchronized (getGetProviderLock(auth, userId)) {
                 holder = ActivityManager.getService().getContentProvider(
-                        getApplicationThread(), auth, userId, stable);
+                        getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
             }
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 88fb025..fb519b6 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -124,7 +124,7 @@
             int ignoreWindowingMode);
     void moveTaskToFront(int task, int flags, in Bundle options);
     int getTaskForActivity(in IBinder token, in boolean onlyRoot);
-    ContentProviderHolder getContentProvider(in IApplicationThread caller,
+    ContentProviderHolder getContentProvider(in IApplicationThread caller, in String callingPackage,
             in String name, int userId, boolean stable);
     void publishContentProviders(in IApplicationThread caller,
             in List<ContentProviderHolder> providers);
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 4da3391..2df5158 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -17,6 +17,7 @@
 package com.android.internal.app.procstats;
 
 
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -192,9 +193,16 @@
          */
         String mProcess;
 
-        SourceKey(int uid, String process) {
+        /**
+         * Optional package name, or null; consider this final.  Not final just to avoid a
+         * temporary object during lookup.
+         */
+        @Nullable String mPackage;
+
+        SourceKey(int uid, String process, String pkg) {
             mUid = uid;
             mProcess = process;
+            mPackage = pkg;
         }
 
         public boolean equals(Object o) {
@@ -202,12 +210,14 @@
                 return false;
             }
             SourceKey s = (SourceKey) o;
-            return s.mUid == mUid && Objects.equals(s.mProcess, mProcess);
+            return s.mUid == mUid && Objects.equals(s.mProcess, mProcess)
+                    && Objects.equals(s.mPackage, mPackage);
         }
 
         @Override
         public int hashCode() {
-            return Integer.hashCode(mUid) ^ (mProcess == null ? 0 : mProcess.hashCode());
+            return Integer.hashCode(mUid) ^ (mProcess == null ? 0 : mProcess.hashCode())
+                    ^ (mPackage == null ? 0 : (mPackage.hashCode() * 33));
         }
 
         @Override
@@ -217,6 +227,8 @@
             UserHandle.formatUid(sb, mUid);
             sb.append(' ');
             sb.append(mProcess);
+            sb.append(' ');
+            sb.append(mPackage);
             sb.append('}');
             return sb.toString();
         }
@@ -227,7 +239,7 @@
      */
     private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>();
 
-    private final SourceKey mTmpSourceKey = new SourceKey(0, null);
+    private final SourceKey mTmpSourceKey = new SourceKey(0, null, null);
 
     private ProcessState mProc;
 
@@ -266,12 +278,13 @@
         mProc = proc;
     }
 
-    public SourceState startSource(int uid, String processName) {
+    public SourceState startSource(int uid, String processName, String packageName) {
         mTmpSourceKey.mUid = uid;
         mTmpSourceKey.mProcess = processName;
+        mTmpSourceKey.mPackage = packageName;
         SourceState src = mSources.get(mTmpSourceKey);
         if (src == null) {
-            SourceKey key = new SourceKey(uid, processName);
+            SourceKey key = new SourceKey(uid, processName, packageName);
             src = new SourceState(key);
             mSources.put(key, src);
         }
@@ -379,6 +392,7 @@
             final SourceState src = mSources.valueAt(isrc);
             out.writeInt(key.mUid);
             stats.writeCommonString(out, key.mProcess);
+            stats.writeCommonString(out, key.mPackage);
             out.writeInt(src.mCount);
             out.writeLong(src.mDuration);
             out.writeInt(src.mActiveCount);
@@ -405,7 +419,8 @@
         for (int isrc = 0; isrc < NSRC; isrc++) {
             final int uid = in.readInt();
             final String procName = stats.readCommonString(in, parcelVersion);
-            final SourceKey key = new SourceKey(uid, procName);
+            final String pkgName = stats.readCommonString(in, parcelVersion);
+            final SourceKey key = new SourceKey(uid, procName, pkgName);
             final SourceState src = new SourceState(key);
             src.mCount = in.readInt();
             src.mDuration = in.readLong();
@@ -445,10 +460,11 @@
         }
     }
 
-    public boolean hasProcess(String procName) {
+    public boolean hasProcessOrPackage(String procName) {
         final int NSRC = mSources.size();
         for (int isrc = 0; isrc < NSRC; isrc++) {
-            if (mSources.keyAt(isrc).mProcess.equals(procName)) {
+            final SourceKey key = mSources.keyAt(isrc);
+            if (procName.equals(key.mProcess) || procName.equals(key.mPackage)) {
                 return true;
             }
         }
@@ -466,14 +482,20 @@
         for (int isrc = 0; isrc < NSRC; isrc++) {
             final SourceKey key = mSources.keyAt(isrc);
             final SourceState src = mSources.valueAt(isrc);
-            if (reqPackage != null && !reqPackage.equals(key.mProcess)) {
+            if (reqPackage != null && !reqPackage.equals(key.mProcess)
+                    && !reqPackage.equals(key.mPackage)) {
                 continue;
             }
             pw.print(prefixInner);
             pw.print("<- ");
             pw.print(key.mProcess);
-            pw.print(" / ");
+            pw.print("/");
             UserHandle.formatUid(pw, key.mUid);
+            if (key.mPackage != null) {
+                pw.print(" (");
+                pw.print(key.mPackage);
+                pw.print(")");
+            }
             pw.println(":");
             pw.print(prefixInner);
             pw.print("   Total count ");
@@ -683,6 +705,7 @@
             final SourceState src = mSources.valueAt(isrc);
             final long sourceToken = proto.start(PackageAssociationProcessStatsProto.SOURCES);
             proto.write(PackageAssociationSourceProcessStatsProto.PROCESS_NAME, key.mProcess);
+            proto.write(PackageAssociationSourceProcessStatsProto.PACKAGE_NAME, key.mPackage);
             proto.write(PackageAssociationSourceProcessStatsProto.PROCESS_UID, key.mUid);
             proto.write(PackageAssociationSourceProcessStatsProto.TOTAL_COUNT, src.mCount);
             long duration = src.mDuration;
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 9ee583a..9b9b771 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -178,7 +178,7 @@
             {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
 
     // Current version of the parcel format.
-    private static final int PARCEL_VERSION = 34;
+    private static final int PARCEL_VERSION = 35;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0x50535454;
 
@@ -1490,7 +1490,7 @@
                                 // package, so that if so we print those.
                                 for (int iasc = 0; iasc < NASCS; iasc++) {
                                     AssociationState asc = pkgState.mAssociations.valueAt(iasc);
-                                    if (asc.hasProcess(reqPackage)) {
+                                    if (asc.hasProcessOrPackage(reqPackage)) {
                                         onlyAssociations = true;
                                         break;
                                     }
@@ -1591,7 +1591,7 @@
                             for (int iasc = 0; iasc < NASCS; iasc++) {
                                 AssociationState asc = pkgState.mAssociations.valueAt(iasc);
                                 if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
-                                    if (!onlyAssociations || !asc.hasProcess(reqPackage)) {
+                                    if (!onlyAssociations || !asc.hasProcessOrPackage(reqPackage)) {
                                         continue;
                                     }
                                 }
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index ce19ce3..71ebcc1 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -186,7 +186,7 @@
     repeated PackageServiceOperationStatsProto operation_stats = 2;
 }
 
-// Next Tag: 7
+// Next Tag: 8
 message PackageAssociationSourceProcessStatsProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -194,6 +194,8 @@
     optional int32 process_uid = 1;
     // Process name.
     optional string process_name = 2;
+    // Package name.
+    optional string package_name = 7;
 
     // Total count of the times this association appeared.
     optional int32 total_count = 3;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5afb90d..fe632e5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1665,7 +1665,7 @@
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
             ConnectionRecord c = new ConnectionRecord(b, activity,
                     connection, flags, clientLabel, clientIntent,
-                    callerApp.uid, callerApp.processName);
+                    callerApp.uid, callerApp.processName, callingPackage);
 
             IBinder binder = connection.asBinder();
             ArrayList<ConnectionRecord> clist = s.connections.get(binder);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2cc4296..d114397 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6291,7 +6291,7 @@
 
     ContentProviderConnection incProviderCountLocked(ProcessRecord r,
             final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
-            String callingTag, boolean stable) {
+            String callingPackage, String callingTag, boolean stable) {
         if (r != null) {
             for (int i=0; i<r.conProviders.size(); i++) {
                 ContentProviderConnection conn = r.conProviders.get(i);
@@ -6311,7 +6311,7 @@
                     return conn;
                 }
             }
-            ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
+            ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage);
             conn.startAssociationIfNeeded();
             if (stable) {
                 conn.stableCount = 1;
@@ -6418,8 +6418,8 @@
     }
 
     private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
-            String name, IBinder token, int callingUid, String callingTag, boolean stable,
-            int userId) {
+            String name, IBinder token, int callingUid, String callingPackage, String callingTag,
+            boolean stable, int userId) {
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
@@ -6542,7 +6542,8 @@
 
                 // In this case the provider instance already exists, so we can
                 // return it right away.
-                conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
+                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
+                        stable);
                 if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
                     if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                         // If this is a perceptible app accessing the provider,
@@ -6789,7 +6790,8 @@
                 }
 
                 mProviderMap.putProviderByName(name, cpr);
-                conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
+                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
+                        stable);
                 if (conn != null) {
                     conn.waiting = true;
                 }
@@ -6931,7 +6933,8 @@
 
     @Override
     public final ContentProviderHolder getContentProvider(
-            IApplicationThread caller, String name, int userId, boolean stable) {
+            IApplicationThread caller, String callingPackage, String name, int userId,
+            boolean stable) {
         enforceNotIsolatedCaller("getContentProvider");
         if (caller == null) {
             String msg = "null IApplicationThread when getting content provider "
@@ -6941,8 +6944,14 @@
         }
         // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
         // with cross-user grant.
-        return getContentProviderImpl(caller, name, null, Binder.getCallingUid(), null, stable,
-                userId);
+        final int callingUid = Binder.getCallingUid();
+        if (callingPackage != null && mAppOpsService.checkPackage(callingUid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
+            throw new SecurityException("Given calling package " + callingPackage
+                    + " does not match caller's uid " + callingUid);
+        }
+        return getContentProviderImpl(caller, name, null, callingUid, callingPackage,
+                null, stable, userId);
     }
 
     public ContentProviderHolder getContentProviderExternal(
@@ -6957,7 +6966,8 @@
 
     private ContentProviderHolder getContentProviderExternalUnchecked(String name,
             IBinder token, int callingUid, String callingTag, int userId) {
-        return getContentProviderImpl(null, name, token, callingUid, callingTag, true, userId);
+        return getContentProviderImpl(null, name, token, callingUid, null, callingTag,
+                true, userId);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index aa76b3d..af1031e 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -43,6 +43,7 @@
     final PendingIntent clientIntent; // How to launch the client.
     final int clientUid;            // The identity of this connection's client
     final String clientProcessName; // The source process of this connection's client
+    final String clientPackageName; // The source package of this connection's client
     public AssociationState.SourceState association; // Association tracking
     String stringName;              // Caching of toString.
     boolean serviceDead;            // Well is it?
@@ -96,7 +97,7 @@
             ActivityServiceConnectionsHolder<ConnectionRecord> _activity,
             IServiceConnection _conn, int _flags,
             int _clientLabel, PendingIntent _clientIntent,
-            int _clientUid, String _clientProcessName) {
+            int _clientUid, String _clientProcessName, String _clientPackageName) {
         binding = _binding;
         activity = _activity;
         conn = _conn;
@@ -105,6 +106,7 @@
         clientIntent = _clientIntent;
         clientUid = _clientUid;
         clientProcessName = _clientProcessName;
+        clientPackageName = _clientPackageName;
     }
 
     public void startAssociationIfNeeded() {
@@ -125,7 +127,7 @@
             } else {
                 association = holder.pkg.getAssociationStateLocked(holder.state,
                         binding.service.instanceName.getClassName()).startSource(clientUid,
-                        clientProcessName);
+                        clientProcessName, clientPackageName);
 
             }
         }
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index f2d4f73..5f184c2 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -32,6 +32,7 @@
 public final class ContentProviderConnection extends Binder {
     public final ContentProviderRecord provider;
     public final ProcessRecord client;
+    public final String clientPackage;
     public AssociationState.SourceState association;
     public final long createTime;
     public int stableCount;
@@ -46,9 +47,11 @@
     public int numStableIncs;
     public int numUnstableIncs;
 
-    public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client) {
+    public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client,
+            String _clientPackage) {
         provider = _provider;
         client = _client;
+        clientPackage = _clientPackage;
         createTime = SystemClock.elapsedRealtime();
     }
 
@@ -69,7 +72,8 @@
                         + provider.name.toShortString() + ": proc=" + provider.proc);
             } else {
                 association = holder.pkg.getAssociationStateLocked(holder.state,
-                        provider.name.getClassName()).startSource(client.uid, client.processName);
+                        provider.name.getClassName()).startSource(client.uid, client.processName,
+                        clientPackage);
 
             }
         }
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index 2fc4adc..46dfc7c 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -305,7 +305,7 @@
                 } else {
                     mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
                             provider.name.getClassName()).startSource(mOwningUid,
-                            mOwningProcessName);
+                            mOwningProcessName, null);
 
                 }
             }