Fixes the bug that can occur when StatsCompanionService calls
StatsService to update UID data and overflows kernel transfer buffer.

In this case, the IPC call silently fails. The issue was discovered in Android Automotive Embedded use case that employs multiuser setup. This causes more uid data being sent via one-way StatsCompanionService::informAllUidData call than usual and can trigger the issue. As the result, uid map on statsd side is empty and many metrics are not captured.

Bug: b/132444397
Fixes: b/132444397
Test: Did a clean build of master branch and flashed the device. adb
shell cmd stats print-uid-map returned without any result. Repeated the
steps after implementing the fix, print-uid-map returns the results now.

Change-Id: I1451c13b36696449c145c51618c68d10e29a596a
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 15d248f..d59d0e2 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -52,6 +52,7 @@
         ":statsd_aidl",
         "src/active_config_list.proto",
         "src/statsd_config.proto",
+        "src/uid_data.proto",
         "src/FieldValue.cpp",
         "src/hash.cpp",
         "src/stats_log_util.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8191d37..f646f19 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -35,6 +35,7 @@
 #include <cutils/multiuser.h>
 #include <dirent.h>
 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
+#include <frameworks/base/cmds/statsd/src/uid_data.pb.h>
 #include <private/android_filesystem_config.h>
 #include <statslog.h>
 #include <stdio.h>
@@ -953,16 +954,49 @@
             || (callingUid == AID_ROOT && goodUid == AID_SHELL); // ROOT can impersonate SHELL.
 }
 
-Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                      const vector<String16>& version_string,
-                                      const vector<String16>& app,
-                                      const vector<String16>& installer) {
+Status StatsService::informAllUidData(const ParcelFileDescriptor& fd) {
     ENFORCE_UID(AID_SYSTEM);
+    // Read stream into buffer.
+    string buffer;
+    if (!android::base::ReadFdToString(fd.get(), &buffer)) {
+        return exception(Status::EX_ILLEGAL_ARGUMENT, "Failed to read all data from the pipe.");
+    }
 
-    VLOG("StatsService::informAllUidData was called");
-    mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, version_string, app, installer);
-    VLOG("StatsService::informAllUidData succeeded");
+    // Parse buffer.
+    UidData uidData;
+    if (!uidData.ParseFromString(buffer)) {
+        return exception(Status::EX_ILLEGAL_ARGUMENT, "Error parsing proto stream for UidData.");
+    }
 
+    vector<String16> versionStrings;
+    vector<String16> installers;
+    vector<String16> packageNames;
+    vector<int32_t> uids;
+    vector<int64_t> versions;
+
+    const auto numEntries = uidData.app_info_size();
+    versionStrings.reserve(numEntries);
+    installers.reserve(numEntries);
+    packageNames.reserve(numEntries);
+    uids.reserve(numEntries);
+    versions.reserve(numEntries);
+
+    for (const auto& appInfo: uidData.app_info()) {
+        packageNames.emplace_back(String16(appInfo.package_name().c_str()));
+        uids.push_back(appInfo.uid());
+        versions.push_back(appInfo.version());
+        versionStrings.emplace_back(String16(appInfo.version_string().c_str()));
+        installers.emplace_back(String16(appInfo.installer().c_str()));
+    }
+
+    mUidMap->updateMap(getElapsedRealtimeNs(),
+                       uids,
+                       versions,
+                       versionStrings,
+                       packageNames,
+                       installers);
+
+    VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
     return Status::ok();
 }
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4e6d7f..9d50a003 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -33,6 +33,7 @@
 #include <android/os/IStatsCompanionService.h>
 #include <android/os/IStatsManager.h>
 #include <binder/IResultReceiver.h>
+#include <binder/ParcelFileDescriptor.h>
 #include <utils/Looper.h>
 
 #include <deque>
@@ -72,9 +73,7 @@
     virtual Status informPollAlarmFired();
     virtual Status informAlarmForSubscriberTriggeringFired();
 
-    virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                    const vector<String16>& version_string,
-                                    const vector<String16>& app, const vector<String16>& installer);
+    virtual Status informAllUidData(const ParcelFileDescriptor& fd);
     virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version,
                                     const String16& version_string, const String16& installer);
     virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
diff --git a/cmds/statsd/src/uid_data.proto b/cmds/statsd/src/uid_data.proto
new file mode 100644
index 0000000..a6fa26c
--- /dev/null
+++ b/cmds/statsd/src/uid_data.proto
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.os.statsd;
+
+option java_package = "com.android.internal.os";
+option java_outer_classname = "UidDataProto";
+
+message ApplicationInfo {
+  optional int32 uid = 1;
+  optional int64 version = 2;
+  optional string version_string = 3;
+  optional string package_name = 4;
+  optional string installer = 5;
+}
+
+// StatsServiceCompanion uses the proto to supply statsd with uid-package
+// mapping updates.
+message UidData {
+  repeated ApplicationInfo app_info = 1;
+}