Make libincident into a stable C API.

Test: atest GtsIncidentConfirmationTestCases GtsIncidentManagerTestCases libincident_test
Bug: 144187174
Change-Id: I65b5a13cfb6a57aa56f738e25a76c5ecb8e7a1a8
This commit is contained in:
Joe Onorato
2020-01-17 01:30:02 -08:00
parent 374ba3fcff
commit 255ffff56d
14 changed files with 486 additions and 29 deletions

View File

@@ -26,7 +26,7 @@ cc_binary {
"libcutils",
"liblog",
"libutils",
"libincident",
"libincidentpriv",
],
static_libs: [

View File

@@ -54,7 +54,7 @@ cc_binary {
"libbinder",
"libdebuggerd_client",
"libdumputils",
"libincident",
"libincidentpriv",
"liblog",
"libprotoutil",
"libservices",
@@ -128,7 +128,7 @@ cc_test {
"libbinder",
"libdebuggerd_client",
"libdumputils",
"libincident",
"libincidentpriv",
"liblog",
"libprotobuf-cpp-full",
"libprotoutil",

View File

@@ -0,0 +1,13 @@
{
"presubmit": [
{
"name": "incidentd_test"
}
],
"postsubmit": [
],
"imports": [
]
}

View File

@@ -278,7 +278,6 @@ cc_test {
"tests/e2e/ValueMetric_pull_e2e_test.cpp",
"tests/e2e/WakelockDuration_e2e_test.cpp",
"tests/external/GpuStatsPuller_test.cpp",
"tests/external/IncidentReportArgs_test.cpp",
"tests/external/puller_util_test.cpp",
"tests/external/StatsCallbackPuller_test.cpp",
"tests/external/StatsPuller_test.cpp",

View File

@@ -21,10 +21,8 @@
#include "packages/UidMap.h"
#include "stats_log_util.h"
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
#include <android/util/ProtoOutputStream.h>
#include <binder/IServiceManager.h>
#include <incident/incident_report.h>
#include <vector>
@@ -132,7 +130,7 @@ bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int
return false;
}
IncidentReportArgs incidentReport;
android::os::IncidentReportRequest incidentReport;
vector<uint8_t> protoData;
getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey,
@@ -146,30 +144,21 @@ bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int
uint8_t dest;
switch (config.dest()) {
case IncidentdDetails_Destination_AUTOMATIC:
dest = android::os::PRIVACY_POLICY_AUTOMATIC;
dest = INCIDENT_REPORT_PRIVACY_POLICY_AUTOMATIC;
break;
case IncidentdDetails_Destination_EXPLICIT:
dest = android::os::PRIVACY_POLICY_EXPLICIT;
dest = INCIDENT_REPORT_PRIVACY_POLICY_EXPLICIT;
break;
default:
dest = android::os::PRIVACY_POLICY_AUTOMATIC;
dest = INCIDENT_REPORT_PRIVACY_POLICY_AUTOMATIC;
}
incidentReport.setPrivacyPolicy(dest);
incidentReport.setReceiverPkg(config.receiver_pkg());
incidentReport.setReceiverPackage(config.receiver_pkg());
incidentReport.setReceiverCls(config.receiver_cls());
incidentReport.setReceiverClass(config.receiver_cls());
sp<IIncidentManager> service = interface_cast<IIncidentManager>(
defaultServiceManager()->getService(android::String16("incident")));
if (service == nullptr) {
ALOGW("Failed to fetch incident service.");
return false;
}
VLOG("Calling incidentd %p", service.get());
binder::Status s = service->reportIncident(incidentReport);
VLOG("Report incident status: %s", s.toString8().string());
return s.isOk();
return incidentReport.takeReport() == NO_ERROR;
}
} // namespace statsd

View File

@@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
cc_library_shared {
name: "libincident",
cc_defaults {
name: "libincidentpriv_defaults",
cflags: [
"-Wall",
@@ -50,6 +51,70 @@ cc_library_shared {
":libincident_aidl",
"src/IncidentReportArgs.cpp",
],
}
cc_library_shared {
name: "libincidentpriv",
defaults: ["libincidentpriv_defaults"],
export_include_dirs: ["include_priv"],
}
cc_library_shared {
name: "libincident",
cflags: [
"-Wall",
"-Werror",
"-Wno-missing-field-initializers",
"-Wno-unused-variable",
"-Wunused-parameter",
],
shared_libs: [
"libbinder",
"liblog",
"libutils",
"libincidentpriv",
],
srcs: [
"src/incident_report.cpp",
],
export_include_dirs: ["include"],
stubs: {
symbol_file: "libincident.map.txt",
versions: [
"30",
],
},
}
cc_test {
name: "libincident_test",
defaults: ["libincidentpriv_defaults"],
test_suites: ["device-tests"],
include_dirs: [
"frameworks/base/libs/incident/include",
"frameworks/base/libs/incident/include_priv",
],
srcs: [
"tests/IncidentReportArgs_test.cpp",
"tests/IncidentReportRequest_test.cpp",
"tests/c_api_compile_test.c",
],
shared_libs: [
"libincident",
],
static_libs: [
"libgmock",
],
}

View File

@@ -0,0 +1,21 @@
{
"presubmit": [
{
"name": "libincident_c_api_test"
},
{
"name": "GtsIncidentConfirmationTestCases"
},
{
"name": "GtsIncidentManagerTestCases"
}
],
"postsubmit": [
],
"imports": [
{
"path": "frameworks/base/cmds/incidentd"
}
]
}

View File

@@ -0,0 +1,192 @@
/**
* Copyright (c) 2020, 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.
*/
/**
* @file incident_report.h
*/
#ifndef ANDROID_INCIDENT_INCIDENT_REPORT_H
#define ANDROID_INCIDENT_INCIDENT_REPORT_H
#include <stdbool.h>
#if __cplusplus
#include <set>
#include <string>
#include <vector>
extern "C" {
#endif // __cplusplus
struct AIncidentReportArgs;
/**
* Opaque class to represent the arguments to an incident report request.
* Incident reports contain debugging data about the device at runtime.
* For more information see the android.os.IncidentManager java class.
*/
typedef struct AIncidentReportArgs AIncidentReportArgs;
// Privacy policy enum value, sync with frameworks/base/core/proto/android/privacy.proto,
// IncidentReportArgs.h and IncidentReportArgs.java.
enum {
/**
* Flag marking fields and incident reports than can be taken
* off the device only via adb.
*/
INCIDENT_REPORT_PRIVACY_POLICY_LOCAL = 0,
/**
* Flag marking fields and incident reports than can be taken
* off the device with contemporary consent.
*/
INCIDENT_REPORT_PRIVACY_POLICY_EXPLICIT = 100,
/**
* Flag marking fields and incident reports than can be taken
* off the device with prior consent.
*/
INCIDENT_REPORT_PRIVACY_POLICY_AUTOMATIC = 200,
/**
* Flag to indicate that a given field has not been marked
* with a privacy policy.
*/
INCIDENT_REPORT_PRIVACY_POLICY_UNSET = 255
};
/**
* Allocate and initialize an AIncidentReportArgs object.
*/
AIncidentReportArgs* AIncidentReportArgs_init();
/**
* Duplicate an existing AIncidentReportArgs object.
*/
AIncidentReportArgs* AIncidentReportArgs_clone(AIncidentReportArgs* that);
/**
* Clean up and delete an AIncidentReportArgs object.
*/
void AIncidentReportArgs_delete(AIncidentReportArgs* args);
/**
* Set this incident report to include all sections.
*/
void AIncidentReportArgs_setAll(AIncidentReportArgs* args, bool all);
/**
* Set this incident report privacy policy spec.
*/
void AIncidentReportArgs_setPrivacyPolicy(AIncidentReportArgs* args, int privacyPolicy);
/**
* Add this section to the incident report. The section IDs are the field numbers
* from the android.os.IncidentProto protobuf message.
*/
void AIncidentReportArgs_addSection(AIncidentReportArgs* args, int section);
/**
* Set the apk package name that will be sent a broadcast when the incident
* report completes. Must be called in conjunction with AIncidentReportArgs_setReceiverClass.
*/
void AIncidentReportArgs_setReceiverPackage(AIncidentReportArgs* args, char const* pkg);
/**
* Set the fully qualified class name of the java BroadcastReceiver class that will be
* sent a broadcast when the report completes. Must be called in conjunction with
* AIncidentReportArgs_setReceiverPackage.
*/
void AIncidentReportArgs_setReceiverClass(AIncidentReportArgs* args, char const* cls);
/**
* Add protobuf data as a header to the incident report. The buffer should be a serialized
* android.os.IncidentHeaderProto object.
*/
void AIncidentReportArgs_addHeader(AIncidentReportArgs* args, uint8_t const* buf, size_t size);
/**
* Initiate taking the report described in the args object. Returns 0 on success,
* and non-zero otherwise.
*/
int AIncidentReportArgs_takeReport(AIncidentReportArgs* args);
#if __cplusplus
} // extern "C"
namespace android {
namespace os {
class IncidentReportRequest {
public:
inline IncidentReportRequest() {
mImpl = AIncidentReportArgs_init();
}
inline IncidentReportRequest(const IncidentReportRequest& that) {
mImpl = AIncidentReportArgs_clone(that.mImpl);
}
inline ~IncidentReportRequest() {
AIncidentReportArgs_delete(mImpl);
}
inline AIncidentReportArgs* getImpl() {
return mImpl;
}
inline void setAll(bool all) {
AIncidentReportArgs_setAll(mImpl, all);
}
inline void setPrivacyPolicy(int privacyPolicy) {
AIncidentReportArgs_setPrivacyPolicy(mImpl, privacyPolicy);
}
inline void addSection(int section) {
AIncidentReportArgs_addSection(mImpl, section);
}
inline void setReceiverPackage(const std::string& pkg) {
AIncidentReportArgs_setReceiverPackage(mImpl, pkg.c_str());
};
inline void setReceiverClass(const std::string& cls) {
AIncidentReportArgs_setReceiverClass(mImpl, cls.c_str());
};
inline void addHeader(const std::vector<uint8_t>& headerProto) {
AIncidentReportArgs_addHeader(mImpl, headerProto.data(), headerProto.size());
};
inline void addHeader(const uint8_t* buf, size_t size) {
AIncidentReportArgs_addHeader(mImpl, buf, size);
};
// returns a status_t
inline int takeReport() {
return AIncidentReportArgs_takeReport(mImpl);
}
private:
AIncidentReportArgs* mImpl;
};
} // namespace os
} // namespace android
#endif // __cplusplus
#endif // ANDROID_INCIDENT_INCIDENT_REPORT_H

View File

@@ -14,9 +14,10 @@
* limitations under the License.
*/
#ifndef ANDROID_OS_DUMPSTATE_ARGS_H_
#define ANDROID_OS_DUMPSTATE_ARGS_H_
#ifndef ANDROID_OS_INCIDENT_REPORT_ARGS_H
#define ANDROID_OS_INCIDENT_REPORT_ARGS_H
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
@@ -29,7 +30,8 @@ namespace os {
using namespace std;
// DESTINATION enum value, sync with frameworks/base/core/proto/android/privacy.proto
// DESTINATION enum value, sync with frameworks/base/core/proto/android/privacy.proto,
// incident/incident_report.h and IncidentReportArgs.java
const uint8_t PRIVACY_POLICY_LOCAL = 0;
const uint8_t PRIVACY_POLICY_EXPLICIT = 100;
const uint8_t PRIVACY_POLICY_AUTOMATIC = 200;
@@ -74,4 +76,4 @@ private:
}
}
#endif // ANDROID_OS_DUMPSTATE_ARGS_H_
#endif // ANDROID_OS_INCIDENT_REPORT_ARGS_H

View File

@@ -0,0 +1,15 @@
LIBINCIDENT {
global:
AIncidentReportArgs_init; # apex # introduced=30
AIncidentReportArgs_clone; # apex # introduced=30
AIncidentReportArgs_delete; # apex # introduced=30
AIncidentReportArgs_setAll; # apex # introduced=30
AIncidentReportArgs_setPrivacyPolicy; # apex # introduced=30
AIncidentReportArgs_addSection; # apex # introduced=30
AIncidentReportArgs_setReceiverPackage; # apex # introduced=30
AIncidentReportArgs_setReceiverClass; # apex # introduced=30
AIncidentReportArgs_addHeader; # apex # introduced=30
AIncidentReportArgs_takeReport; # apex # introduced=30
local:
*;
};

View File

@@ -0,0 +1,83 @@
/**
* Copyright (c) 2020, 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.
*/
#define LOG_TAG "libincident"
#include <incident/incident_report.h>
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <log/log.h>
using android::sp;
using android::binder::Status;
using android::os::IncidentReportArgs;
using android::os::IIncidentManager;
using std::string;
using std::vector;
AIncidentReportArgs* AIncidentReportArgs_init() {
return reinterpret_cast<AIncidentReportArgs*>(new IncidentReportArgs());
}
AIncidentReportArgs* AIncidentReportArgs_clone(AIncidentReportArgs* that) {
return reinterpret_cast<AIncidentReportArgs*>(
new IncidentReportArgs(*reinterpret_cast<IncidentReportArgs*>(that)));
}
void AIncidentReportArgs_delete(AIncidentReportArgs* args) {
delete reinterpret_cast<IncidentReportArgs*>(args);
}
void AIncidentReportArgs_setAll(AIncidentReportArgs* args, bool all) {
reinterpret_cast<IncidentReportArgs*>(args)->setAll(all);
}
void AIncidentReportArgs_setPrivacyPolicy(AIncidentReportArgs* args, int privacyPolicy) {
reinterpret_cast<IncidentReportArgs*>(args)->setPrivacyPolicy(privacyPolicy);
}
void AIncidentReportArgs_addSection(AIncidentReportArgs* args, int section) {
reinterpret_cast<IncidentReportArgs*>(args)->addSection(section);
}
void AIncidentReportArgs_setReceiverPackage(AIncidentReportArgs* args, char const* pkg) {
reinterpret_cast<IncidentReportArgs*>(args)->setReceiverPkg(string(pkg));
}
void AIncidentReportArgs_setReceiverClass(AIncidentReportArgs* args, char const* cls) {
reinterpret_cast<IncidentReportArgs*>(args)->setReceiverCls(string(cls));
}
void AIncidentReportArgs_addHeader(AIncidentReportArgs* args, uint8_t const* buf, size_t size) {
vector<uint8_t> vec(buf, buf+size);
reinterpret_cast<IncidentReportArgs*>(args)->addHeader(vec);
}
int AIncidentReportArgs_takeReport(AIncidentReportArgs* argp) {
IncidentReportArgs* args = reinterpret_cast<IncidentReportArgs*>(argp);
sp<IIncidentManager> service = android::interface_cast<IIncidentManager>(
android::defaultServiceManager()->getService(android::String16("incident")));
if (service == nullptr) {
ALOGW("Failed to fetch incident service.");
return false;
}
Status s = service->reportIncident(*args);
return s.transactionError();
}

View File

@@ -20,6 +20,8 @@ namespace android {
namespace os {
namespace statsd {
// Checks that all of the inline methods on IncidentReportRequest and the real C functions
// result in a working IncidentReportArgs.
TEST(IncidentReportArgsTest, testSerialization) {
IncidentReportArgs args;
args.setAll(0);

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2018 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.
#include <android/os/IncidentReportArgs.h>
#include <incident/incident_report.h>
#include <gtest/gtest.h>
namespace android {
namespace os {
namespace statsd {
TEST(IncidentReportRequestTest, testWrite) {
IncidentReportRequest request;
request.setAll(0);
request.addSection(1000);
request.addSection(1001);
vector<uint8_t> header1;
header1.push_back(0x1);
header1.push_back(0x2);
vector<uint8_t> header2;
header1.push_back(0x22);
header1.push_back(0x33);
request.addHeader(header1);
request.addHeader(header2);
request.setPrivacyPolicy(1);
request.setReceiverPackage("com.android.os");
request.setReceiverClass("com.android.os.Receiver");
IncidentReportArgs* args = reinterpret_cast<IncidentReportArgs*>(request.getImpl());
EXPECT_EQ(0, args->all());
set<int> sections;
sections.insert(1000);
sections.insert(1001);
EXPECT_EQ(sections, args->sections());
EXPECT_EQ(1, args->getPrivacyPolicy());
EXPECT_EQ(string("com.android.os"), args->receiverPkg());
EXPECT_EQ(string("com.android.os.Receiver"), args->receiverCls());
vector<vector<uint8_t>> headers;
headers.push_back(header1);
headers.push_back(header2);
EXPECT_EQ(headers, args->headers());
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,11 @@
#include <stdio.h>
#include <incident/incident_report.h>
/*
* This file ensures that incident/incident_report.h actually compiles with C,
* since there is no other place in the tree that actually uses it from C.
*/
int not_called() {
return 0;
}