Merge "Fixes the bug that can occur when StatsCompanionService calls StatsService to update UID data and overflows kernel transfer buffer." into qt-dev
am: 585422a5d2
Change-Id: I0f938610453b6181c877943ae80b40ed7d62981f
This commit is contained in:
@@ -52,6 +52,7 @@ cc_defaults {
|
||||
":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",
|
||||
|
||||
@@ -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 @@ bool StatsService::getUidFromString(const char* s, int32_t& uid) {
|
||||
|| (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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ public:
|
||||
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);
|
||||
|
||||
36
cmds/statsd/src/uid_data.proto
Normal file
36
cmds/statsd/src/uid_data.proto
Normal file
@@ -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;
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.os;
|
||||
|
||||
import android.os.IStatsPullerCallback;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
/**
|
||||
* Binder interface to communicate with the statistics management service.
|
||||
@@ -61,11 +62,12 @@ interface IStatsManager {
|
||||
void informDeviceShutdown();
|
||||
|
||||
/**
|
||||
* Inform statsd what the version and package are for each uid. Note that each array should
|
||||
* have the same number of elements, and version[i] and package[i] correspond to uid[i].
|
||||
* Inform statsd about a file descriptor for a pipe through which we will pipe version
|
||||
* and package information for each uid.
|
||||
* Versions and package information are supplied via UidData proto where info for each app
|
||||
* is captured in its own element of a repeated ApplicationInfo message.
|
||||
*/
|
||||
oneway void informAllUidData(in int[] uid, in long[] version, in String[] version_string,
|
||||
in String[] app, in String[] installer);
|
||||
oneway void informAllUidData(in ParcelFileDescriptor fd);
|
||||
|
||||
/**
|
||||
* Inform statsd what the uid, version, version_string, and installer are for one app that was
|
||||
|
||||
@@ -109,10 +109,12 @@ import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.StatsLog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.util.proto.ProtoStream;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.app.procstats.IProcessStats;
|
||||
import com.android.internal.app.procstats.ProcessStats;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
|
||||
@@ -184,6 +186,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
static final String TAG = "StatsCompanionService";
|
||||
static final boolean DEBUG = false;
|
||||
/**
|
||||
* Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto
|
||||
* to be used in ProtoOutputStream.
|
||||
*/
|
||||
private static final int APPLICATION_INFO_FIELD_ID = 1;
|
||||
private static final int UID_FIELD_ID = 1;
|
||||
private static final int VERSION_FIELD_ID = 2;
|
||||
private static final int VERSION_STRING_FIELD_ID = 3;
|
||||
private static final int PACKAGE_NAME_FIELD_ID = 4;
|
||||
private static final int INSTALLER_FIELD_ID = 5;
|
||||
|
||||
public static final int CODE_DATA_BROADCAST = 1;
|
||||
public static final int CODE_SUBSCRIBER_BROADCAST = 1;
|
||||
@@ -455,39 +467,71 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
Slog.d(TAG, "Iterating over " + users.size() + " profiles.");
|
||||
}
|
||||
|
||||
List<Integer> uids = new ArrayList<>();
|
||||
List<Long> versions = new ArrayList<>();
|
||||
List<String> apps = new ArrayList<>();
|
||||
List<String> versionStrings = new ArrayList<>();
|
||||
List<String> installers = new ArrayList<>();
|
||||
|
||||
// Add in all the apps for every user/profile.
|
||||
for (UserInfo profile : users) {
|
||||
List<PackageInfo> pi =
|
||||
pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
|
||||
for (int j = 0; j < pi.size(); j++) {
|
||||
if (pi.get(j).applicationInfo != null) {
|
||||
String installer;
|
||||
try {
|
||||
installer = pm.getInstallerPackageName(pi.get(j).packageName);
|
||||
} catch (IllegalArgumentException e) {
|
||||
installer = "";
|
||||
ParcelFileDescriptor[] fds;
|
||||
try {
|
||||
fds = ParcelFileDescriptor.createPipe();
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Failed to create a pipe to send uid map data.", e);
|
||||
return;
|
||||
}
|
||||
sStatsd.informAllUidData(fds[0]);
|
||||
try {
|
||||
fds[0].close();
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Failed to close the read side of the pipe.", e);
|
||||
}
|
||||
final ParcelFileDescriptor writeFd = fds[1];
|
||||
BackgroundThread.getHandler().post(() -> {
|
||||
FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd);
|
||||
try {
|
||||
ProtoOutputStream output = new ProtoOutputStream(fout);
|
||||
int numRecords = 0;
|
||||
// Add in all the apps for every user/profile.
|
||||
for (UserInfo profile : users) {
|
||||
List<PackageInfo> pi =
|
||||
pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES,
|
||||
profile.id);
|
||||
for (int j = 0; j < pi.size(); j++) {
|
||||
if (pi.get(j).applicationInfo != null) {
|
||||
String installer;
|
||||
try {
|
||||
installer = pm.getInstallerPackageName(pi.get(j).packageName);
|
||||
} catch (IllegalArgumentException e) {
|
||||
installer = "";
|
||||
}
|
||||
long applicationInfoToken =
|
||||
output.start(ProtoStream.FIELD_TYPE_MESSAGE
|
||||
| ProtoStream.FIELD_COUNT_REPEATED
|
||||
| APPLICATION_INFO_FIELD_ID);
|
||||
output.write(ProtoStream.FIELD_TYPE_INT32
|
||||
| ProtoStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
|
||||
pi.get(j).applicationInfo.uid);
|
||||
output.write(ProtoStream.FIELD_TYPE_INT64
|
||||
| ProtoStream.FIELD_COUNT_SINGLE
|
||||
| VERSION_FIELD_ID, pi.get(j).getLongVersionCode());
|
||||
output.write(ProtoStream.FIELD_TYPE_STRING
|
||||
| ProtoStream.FIELD_COUNT_SINGLE | VERSION_STRING_FIELD_ID,
|
||||
pi.get(j).versionName);
|
||||
output.write(ProtoStream.FIELD_TYPE_STRING
|
||||
| ProtoStream.FIELD_COUNT_SINGLE
|
||||
| PACKAGE_NAME_FIELD_ID, pi.get(j).packageName);
|
||||
output.write(ProtoStream.FIELD_TYPE_STRING
|
||||
| ProtoStream.FIELD_COUNT_SINGLE
|
||||
| INSTALLER_FIELD_ID,
|
||||
installer == null ? "" : installer);
|
||||
numRecords++;
|
||||
output.end(applicationInfoToken);
|
||||
}
|
||||
}
|
||||
installers.add(installer == null ? "" : installer);
|
||||
uids.add(pi.get(j).applicationInfo.uid);
|
||||
versions.add(pi.get(j).getLongVersionCode());
|
||||
versionStrings.add(pi.get(j).versionName);
|
||||
apps.add(pi.get(j).packageName);
|
||||
}
|
||||
output.flush();
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Sent data for " + numRecords + " apps");
|
||||
}
|
||||
} finally {
|
||||
IoUtils.closeQuietly(fout);
|
||||
}
|
||||
}
|
||||
sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions),
|
||||
versionStrings.toArray(new String[versionStrings.size()]),
|
||||
apps.toArray(new String[apps.size()]),
|
||||
installers.toArray(new String[installers.size()]));
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Sent data for " + uids.size() + " apps");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final static class AppUpdateReceiver extends BroadcastReceiver {
|
||||
|
||||
Reference in New Issue
Block a user