Merge "Small cleanup in AppLaunch."
diff --git a/Android.mk b/Android.mk
index 3b8d6a8..58e21ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -793,6 +793,8 @@
$(call all-proto-files-under, core/proto) \
$(call all-proto-files-under, libs/incident/proto) \
$(call all-proto-files-under, cmds/statsd/src)
+# b/72714520
+LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
include $(BUILD_HOST_JAVA_LIBRARY)
# ==== java proto device library (for test only) ==============================
diff --git a/api/current.txt b/api/current.txt
index df18f10..a7a8f3e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36640,6 +36640,7 @@
field public static final deprecated java.lang.String RADIO_NFC = "nfc";
field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String RINGTONE = "ringtone";
+ field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
@@ -38449,6 +38450,7 @@
method public boolean isRandomizedEncryptionRequired();
method public boolean isStrongBoxBacked();
method public boolean isTrustedUserPresenceRequired();
+ method public boolean isUnlockedDeviceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
method public boolean isUserConfirmationRequired();
@@ -38476,6 +38478,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setTrustedUserPresenceRequired(boolean);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -38567,6 +38570,8 @@
method public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
+ method public boolean isTrustedUserPresenceRequired();
+ method public boolean isUnlockedDeviceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
method public boolean isUserConfirmationRequired();
@@ -38585,6 +38590,8 @@
method public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
+ method public android.security.keystore.KeyProtection.Builder setTrustedUserPresenceRequired(boolean);
+ method public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -40645,6 +40652,7 @@
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+ field public static final int PROPERTY_RTT = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
field public static final int PROPERTY_WIFI = 8; // 0x8
}
@@ -49795,6 +49803,8 @@
method public boolean isFieldClassificationEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
+ method public void notifyViewClicked(android.view.View);
+ method public void notifyViewClicked(android.view.View, int);
method public void notifyViewEntered(android.view.View);
method public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
method public void notifyViewExited(android.view.View);
diff --git a/api/test-current.txt b/api/test-current.txt
index 9bfc105..2e47e00 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1061,6 +1061,7 @@
public final class AutofillId implements android.os.Parcelable {
ctor public AutofillId(int);
+ ctor public AutofillId(android.view.autofill.AutofillId, int);
}
}
diff --git a/cmds/incidentd/.clang-format b/cmds/incidentd/.clang-format
new file mode 100644
index 0000000..6fa5b47
--- /dev/null
+++ b/cmds/incidentd/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+AccessModifierOffset: -4
+IncludeCategories:
+ - Regex: '^"Log\.h"'
+ Priority: -1
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 23cd2af..d2d24c8 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -32,7 +32,7 @@
src/Privacy.cpp \
src/Reporter.cpp \
src/Section.cpp \
- src/io_util.cpp \
+ src/incidentd_util.cpp \
src/main.cpp \
src/report_directory.cpp
@@ -116,7 +116,7 @@
src/Privacy.cpp \
src/Reporter.cpp \
src/Section.cpp \
- src/io_util.cpp \
+ src/incidentd_util.cpp \
src/report_directory.cpp \
tests/section_list.cpp \
tests/PrivacyBuffer_test.cpp \
diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md
index 71c6deb..1730a640 100644
--- a/cmds/incidentd/README.md
+++ b/cmds/incidentd/README.md
@@ -20,4 +20,8 @@
```
root$ atest incidentd_test
-```
\ No newline at end of file
+```
+
+Use clang-format to style the file
+
+clang-format -style=file -i <file list>
\ No newline at end of file
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 0fff4e6..883924c8 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "FdBuffer.h"
@@ -26,30 +25,16 @@
#include <unistd.h>
#include <wait.h>
-const bool DEBUG = false;
-const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
-const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
+const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
+const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
FdBuffer::FdBuffer()
- :mBuffer(BUFFER_SIZE),
- mStartTime(-1),
- mFinishTime(-1),
- mTimedOut(false),
- mTruncated(false)
-{
-}
+ : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
-FdBuffer::~FdBuffer()
-{
-}
+FdBuffer::~FdBuffer() {}
-status_t
-FdBuffer::read(int fd, int64_t timeout)
-{
- struct pollfd pfds = {
- .fd = fd,
- .events = POLLIN
- };
+status_t FdBuffer::read(int fd, int64_t timeout) {
+ struct pollfd pfds = {.fd = fd, .events = POLLIN};
mStartTime = uptimeMillis();
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
@@ -63,22 +48,22 @@
int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
if (remainingTime <= 0) {
- if (DEBUG) ALOGD("timed out due to long read");
+ VLOG("timed out due to long read");
mTimedOut = true;
break;
}
int count = poll(&pfds, 1, remainingTime);
if (count == 0) {
- if (DEBUG) ALOGD("timed out due to block calling poll");
+ VLOG("timed out due to block calling poll");
mTimedOut = true;
break;
} else if (count < 0) {
- if (DEBUG) ALOGD("poll failed: %s", strerror(errno));
+ VLOG("poll failed: %s", strerror(errno));
return -errno;
} else {
if ((pfds.revents & POLLERR) != 0) {
- if (DEBUG) ALOGD("return event has error %s", strerror(errno));
+ VLOG("return event has error %s", strerror(errno));
return errno != 0 ? -errno : UNKNOWN_ERROR;
} else {
ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
@@ -86,7 +71,7 @@
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
} else {
- if (DEBUG) ALOGD("Fail to read %d: %s", fd, strerror(errno));
+ VLOG("Fail to read %d: %s", fd, strerror(errno));
return -errno;
}
} else if (amt == 0) {
@@ -100,13 +85,12 @@
return NO_ERROR;
}
-status_t
-FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs)
-{
+status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
+ const bool isSysfs) {
struct pollfd pfds[] = {
- { .fd = fd, .events = POLLIN },
- { .fd = toFd, .events = POLLOUT },
- { .fd = fromFd, .events = POLLIN },
+ {.fd = fd, .events = POLLIN},
+ {.fd = toFd, .events = POLLOUT},
+ {.fd = fromFd, .events = POLLIN},
};
mStartTime = uptimeMillis();
@@ -131,7 +115,7 @@
int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
if (remainingTime <= 0) {
- if (DEBUG) ALOGD("timed out due to long read");
+ VLOG("timed out due to long read");
mTimedOut = true;
break;
}
@@ -139,11 +123,11 @@
// wait for any pfds to be ready to perform IO
int count = poll(pfds, 3, remainingTime);
if (count == 0) {
- if (DEBUG) ALOGD("timed out due to block calling poll");
+ VLOG("timed out due to block calling poll");
mTimedOut = true;
break;
} else if (count < 0) {
- if (DEBUG) ALOGD("Fail to poll: %s", strerror(errno));
+ VLOG("Fail to poll: %s", strerror(errno));
return -errno;
}
@@ -151,10 +135,10 @@
for (int i = 0; i < 3; ++i) {
if ((pfds[i].revents & POLLERR) != 0) {
if (i == 0 && isSysfs) {
- if (DEBUG) ALOGD("fd %d is sysfs, ignore its POLLERR return value", fd);
+ VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
continue;
}
- if (DEBUG) ALOGD("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
+ VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
return errno != 0 ? -errno : UNKNOWN_ERROR;
}
}
@@ -169,9 +153,9 @@
}
if (amt < 0) {
if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
- if (DEBUG) ALOGD("Fail to read fd %d: %s", fd, strerror(errno));
+ VLOG("Fail to read fd %d: %s", fd, strerror(errno));
return -errno;
- } // otherwise just continue
+ } // otherwise just continue
} else if (amt == 0) { // reach EOF so don't have to poll pfds[0].
::close(pfds[0].fd);
pfds[0].fd = -1;
@@ -191,9 +175,9 @@
}
if (amt < 0) {
if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
- if (DEBUG) ALOGD("Fail to write toFd %d: %s", toFd, strerror(errno));
+ VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
return -errno;
- } // otherwise just continue
+ } // otherwise just continue
} else {
wpos += amt;
cirSize -= amt;
@@ -218,9 +202,9 @@
ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
if (amt < 0) {
if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
- if (DEBUG) ALOGD("Fail to read fromFd %d: %s", fromFd, strerror(errno));
+ VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
return -errno;
- } // otherwise just continue
+ } // otherwise just continue
} else if (amt == 0) {
break;
} else {
@@ -232,14 +216,6 @@
return NO_ERROR;
}
-size_t
-FdBuffer::size() const
-{
- return mBuffer.size();
-}
+size_t FdBuffer::size() const { return mBuffer.size(); }
-EncodedBuffer::iterator
-FdBuffer::data() const
-{
- return mBuffer.begin();
-}
+EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index 48dc855..5bfa093 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef FD_BUFFER_H
#define FD_BUFFER_H
@@ -27,8 +28,7 @@
/**
* Reads a file into a buffer, and then writes that data to an FdSet.
*/
-class FdBuffer
-{
+class FdBuffer {
public:
FdBuffer();
~FdBuffer();
@@ -50,7 +50,8 @@
*
* Poll will return POLLERR if fd is from sysfs, handle this edge case.
*/
- status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs=false);
+ status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
+ const bool isSysfs = false);
/**
* Whether we timed out.
@@ -90,4 +91,4 @@
bool mTruncated;
};
-#endif // FD_BUFFER_H
+#endif // FD_BUFFER_H
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 654036e..9ae6240 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -13,15 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "IncidentService.h"
+#include "FdBuffer.h"
+#include "PrivacyBuffer.h"
#include "Reporter.h"
+#include "incidentd_util.h"
+#include "section_list.h"
#include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
+#include <binder/IShellCallback.h>
#include <cutils/log.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
@@ -29,11 +34,9 @@
#include <unistd.h>
using namespace android;
+using namespace android::base;
-enum {
- WHAT_RUN_REPORT = 1,
- WHAT_SEND_BACKLOG_TO_DROPBOX = 2
-};
+enum { WHAT_RUN_REPORT = 1, WHAT_SEND_BACKLOG_TO_DROPBOX = 2 };
//#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL * 60 * 5)
#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL)
@@ -42,9 +45,7 @@
String16 const DUMP_PERMISSION("android.permission.DUMP");
String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
-static Status
-checkIncidentPermissions(const IncidentReportArgs& args)
-{
+static Status checkIncidentPermissions(const IncidentReportArgs& args) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t callingPid = IPCThreadState::self()->getCallingPid();
if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
@@ -55,14 +56,16 @@
// checking calling permission.
if (!checkCallingPermission(DUMP_PERMISSION)) {
ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
- callingPid, callingUid);
- return Status::fromExceptionCode(Status::EX_SECURITY,
+ callingPid, callingUid);
+ return Status::fromExceptionCode(
+ Status::EX_SECURITY,
"Calling process does not have permission: android.permission.DUMP");
}
if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
- callingPid, callingUid);
- return Status::fromExceptionCode(Status::EX_SECURITY,
+ callingPid, callingUid);
+ return Status::fromExceptionCode(
+ Status::EX_SECURITY,
"Calling process does not have permission: android.permission.USAGE_STATS");
}
@@ -71,40 +74,34 @@
case DEST_LOCAL:
if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
- callingPid, callingUid);
- return Status::fromExceptionCode(Status::EX_SECURITY,
- "Calling process does not have permission to get local data.");
+ callingPid, callingUid);
+ return Status::fromExceptionCode(
+ Status::EX_SECURITY,
+ "Calling process does not have permission to get local data.");
}
case DEST_EXPLICIT:
- if (callingUid != AID_SHELL && callingUid != AID_ROOT &&
- callingUid != AID_STATSD && callingUid != AID_SYSTEM) {
+ if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
+ callingUid != AID_SYSTEM) {
ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
- callingPid, callingUid);
- return Status::fromExceptionCode(Status::EX_SECURITY,
- "Calling process does not have permission to get explicit data.");
+ callingPid, callingUid);
+ return Status::fromExceptionCode(
+ Status::EX_SECURITY,
+ "Calling process does not have permission to get explicit data.");
}
}
return Status::ok();
}
// ================================================================================
-ReportRequestQueue::ReportRequestQueue()
-{
-}
+ReportRequestQueue::ReportRequestQueue() {}
-ReportRequestQueue::~ReportRequestQueue()
-{
-}
+ReportRequestQueue::~ReportRequestQueue() {}
-void
-ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
-{
+void ReportRequestQueue::addRequest(const sp<ReportRequest>& request) {
unique_lock<mutex> lock(mLock);
mQueue.push_back(request);
}
-sp<ReportRequest>
-ReportRequestQueue::getNextRequest()
-{
+sp<ReportRequest> ReportRequestQueue::getNextRequest() {
unique_lock<mutex> lock(mLock);
if (mQueue.empty()) {
return NULL;
@@ -115,22 +112,13 @@
}
}
-
// ================================================================================
ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
- :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
- mHandlerLooper(handlerLooper),
- mQueue(queue)
-{
-}
+ : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), mHandlerLooper(handlerLooper), mQueue(queue) {}
-ReportHandler::~ReportHandler()
-{
-}
+ReportHandler::~ReportHandler() {}
-void
-ReportHandler::handleMessage(const Message& message)
-{
+void ReportHandler::handleMessage(const Message& message) {
switch (message.what) {
case WHAT_RUN_REPORT:
run_report();
@@ -141,33 +129,24 @@
}
}
-void
-ReportHandler::scheduleRunReport(const sp<ReportRequest>& request)
-{
+void ReportHandler::scheduleRunReport(const sp<ReportRequest>& request) {
mQueue->addRequest(request);
mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
}
-void
-ReportHandler::scheduleSendBacklogToDropbox()
-{
+void ReportHandler::scheduleSendBacklogToDropbox() {
unique_lock<mutex> lock(mLock);
mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
schedule_send_backlog_to_dropbox_locked();
}
-void
-ReportHandler::schedule_send_backlog_to_dropbox_locked()
-{
+void ReportHandler::schedule_send_backlog_to_dropbox_locked() {
mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
- mHandlerLooper->sendMessageDelayed(mBacklogDelay, this,
- Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
+ mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
}
-void
-ReportHandler::run_report()
-{
+void ReportHandler::run_report() {
sp<Reporter> reporter = new Reporter();
// Merge all of the requests into one that has all of the
@@ -190,15 +169,13 @@
}
}
-void
-ReportHandler::send_backlog_to_dropbox()
-{
+void ReportHandler::send_backlog_to_dropbox() {
if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
// There was a failure. Exponential backoff.
unique_lock<mutex> lock(mLock);
mBacklogDelay *= 2;
ALOGI("Error sending to dropbox. Trying again in %lld minutes",
- (mBacklogDelay / (1000000000LL * 60)));
+ (mBacklogDelay / (1000000000LL * 60)));
schedule_send_backlog_to_dropbox_locked();
} else {
mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
@@ -207,18 +184,13 @@
// ================================================================================
IncidentService::IncidentService(const sp<Looper>& handlerLooper)
- :mQueue(new ReportRequestQueue())
-{
+ : mQueue(new ReportRequestQueue()) {
mHandler = new ReportHandler(handlerLooper, mQueue);
}
-IncidentService::~IncidentService()
-{
-}
+IncidentService::~IncidentService() {}
-Status
-IncidentService::reportIncident(const IncidentReportArgs& args)
-{
+Status IncidentService::reportIncident(const IncidentReportArgs& args) {
ALOGI("reportIncident");
Status status = checkIncidentPermissions(args);
@@ -231,10 +203,9 @@
return Status::ok();
}
-Status
-IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
- const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream)
-{
+Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
+ const sp<IIncidentReportStatusListener>& listener,
+ const unique_fd& stream) {
ALOGI("reportIncidentToStream");
Status status = checkIncidentPermissions(args);
@@ -252,12 +223,10 @@
return Status::ok();
}
-Status
-IncidentService::systemRunning()
-{
+Status IncidentService::systemRunning() {
if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
return Status::fromExceptionCode(Status::EX_SECURITY,
- "Only system uid can call systemRunning");
+ "Only system uid can call systemRunning");
}
// When system_server is up and running, schedule the dropbox task to run.
@@ -266,3 +235,120 @@
return Status::ok();
}
+/**
+ * Implement our own because the default binder implementation isn't
+ * properly handling SHELL_COMMAND_TRANSACTION.
+ */
+status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ status_t err;
+
+ switch (code) {
+ case SHELL_COMMAND_TRANSACTION: {
+ int in = data.readFileDescriptor();
+ int out = data.readFileDescriptor();
+ int err = data.readFileDescriptor();
+ int argc = data.readInt32();
+ Vector<String8> args;
+ for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+ args.add(String8(data.readString16()));
+ }
+ sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
+ sp<IResultReceiver> resultReceiver =
+ IResultReceiver::asInterface(data.readStrongBinder());
+
+ FILE* fin = fdopen(in, "r");
+ FILE* fout = fdopen(out, "w");
+ FILE* ferr = fdopen(err, "w");
+
+ if (fin == NULL || fout == NULL || ferr == NULL) {
+ resultReceiver->send(NO_MEMORY);
+ } else {
+ err = command(fin, fout, ferr, args);
+ resultReceiver->send(err);
+ }
+
+ if (fin != NULL) {
+ fflush(fin);
+ fclose(fin);
+ }
+ if (fout != NULL) {
+ fflush(fout);
+ fclose(fout);
+ }
+ if (fout != NULL) {
+ fflush(ferr);
+ fclose(ferr);
+ }
+
+ return NO_ERROR;
+ }
+ default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
+ }
+}
+
+status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
+ const int argCount = args.size();
+
+ if (argCount >= 1) {
+ if (!args[0].compare(String8("privacy"))) {
+ return cmd_privacy(in, out, err, args);
+ }
+ }
+ return cmd_help(out);
+}
+
+status_t IncidentService::cmd_help(FILE* out) {
+ fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
+ fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
+ fprintf(out, " Prints/parses for the section id.\n");
+ return NO_ERROR;
+}
+
+static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
+ if (p == NULL) return;
+ fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.string(), p->field_id, p->type, p->dest);
+ if (p->children == NULL) return;
+ for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
+ printPrivacy(p->children[i], out, indent + " ");
+ }
+}
+
+status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
+ const int argCount = args.size();
+ if (argCount >= 3) {
+ String8 opt = args[1];
+ int sectionId = atoi(args[2].string());
+
+ const Privacy* p = get_privacy_of_section(sectionId);
+ if (p == NULL) {
+ fprintf(err, "Can't find section id %d\n", sectionId);
+ return NO_ERROR;
+ }
+ fprintf(err, "Get privacy for %d\n", sectionId);
+ if (opt == "print") {
+ printPrivacy(p, out, String8(""));
+ } else if (opt == "parse") {
+ FdBuffer buf;
+ status_t error = buf.read(fileno(in), 60000);
+ if (error != NO_ERROR) {
+ fprintf(err, "Error reading from stdin\n");
+ return error;
+ }
+ fprintf(err, "Read %zu bytes\n", buf.size());
+ auto data = buf.data();
+ PrivacyBuffer pBuf(p, data);
+
+ PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
+ error = pBuf.strip(spec);
+ if (error != NO_ERROR) {
+ fprintf(err, "Error strip pii fields with spec %d\n", spec.dest);
+ return error;
+ }
+ return pBuf.flush(fileno(out));
+ }
+ } else {
+ return cmd_help(out);
+ }
+ return NO_ERROR;
+}
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index d6f33df..3c66507 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef INCIDENT_SERVICE_H
#define INCIDENT_SERVICE_H
@@ -32,8 +33,7 @@
using namespace std;
// ================================================================================
-class ReportRequestQueue : public virtual RefBase
-{
+class ReportRequestQueue : public virtual RefBase {
public:
ReportRequestQueue();
virtual ~ReportRequestQueue();
@@ -46,10 +46,8 @@
deque<sp<ReportRequest> > mQueue;
};
-
// ================================================================================
-class ReportHandler : public MessageHandler
-{
+class ReportHandler : public MessageHandler {
public:
ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue);
virtual ~ReportHandler();
@@ -89,7 +87,6 @@
void send_backlog_to_dropbox();
};
-
// ================================================================================
class IncidentService : public BnIncidentManager {
public:
@@ -99,14 +96,29 @@
virtual Status reportIncident(const IncidentReportArgs& args);
virtual Status reportIncidentToStream(const IncidentReportArgs& args,
- const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream);
+ const sp<IIncidentReportStatusListener>& listener,
+ const unique_fd& stream);
virtual Status systemRunning();
+ // Implement commands for debugging purpose.
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) override;
+ virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
+
private:
sp<ReportRequestQueue> mQueue;
sp<ReportHandler> mHandler;
+
+ /**
+ * Commands print out help.
+ */
+ status_t cmd_help(FILE* out);
+
+ /**
+ * Commands related to privacy filtering.
+ */
+ status_t cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
};
-
-#endif // INCIDENT_SERVICE_H
+#endif // INCIDENT_SERVICE_H
diff --git a/cmds/incidentd/src/Log.h b/cmds/incidentd/src/Log.h
new file mode 100644
index 0000000..46efbd1
--- /dev/null
+++ b/cmds/incidentd/src/Log.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*
+ * This file must be included at the top of the file. Other header files
+ * occasionally include log.h, and if LOG_TAG isn't set when that happens
+ * we'll get a preprocesser error when we try to define it here.
+ */
+
+#pragma once
+
+#define LOG_TAG "incidentd"
+#define DEBUG false
+
+#include <log/log.h>
+
+// Use the local value to turn on/off debug logs instead of using log.tag.properties.
+// The advantage is that in production compiler can remove the logging code if the local
+// DEBUG/VERBOSE is false.
+#define VLOG(...) \
+ if (DEBUG) ALOGD(__VA_ARGS__);
\ No newline at end of file
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index c5078f0..c42a87b 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -21,10 +21,9 @@
uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; }
-const Privacy* lookup(const Privacy* p, uint32_t fieldId)
-{
+const Privacy* lookup(const Privacy* p, uint32_t fieldId) {
if (p->children == NULL) return NULL;
- for (int i=0; p->children[i] != NULL; i++) { // NULL-terminated.
+ for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
if (p->children[i]->field_id == fieldId) return p->children[i];
// Incident section gen tool guarantees field ids in ascending order.
if (p->children[i]->field_id > fieldId) return NULL;
@@ -32,41 +31,31 @@
return NULL;
}
-static bool allowDest(const uint8_t dest, const uint8_t policy)
-{
+static bool allowDest(const uint8_t dest, const uint8_t policy) {
switch (policy) {
- case android::os::DEST_LOCAL:
- return dest == android::os::DEST_LOCAL;
- case android::os::DEST_EXPLICIT:
- case DEST_UNSET:
- return dest == android::os::DEST_LOCAL ||
- dest == android::os::DEST_EXPLICIT ||
- dest == DEST_UNSET;
- case android::os::DEST_AUTOMATIC:
- return true;
- default:
- return false;
+ case android::os::DEST_LOCAL:
+ return dest == android::os::DEST_LOCAL;
+ case android::os::DEST_EXPLICIT:
+ case DEST_UNSET:
+ return dest == android::os::DEST_LOCAL || dest == android::os::DEST_EXPLICIT ||
+ dest == DEST_UNSET;
+ case android::os::DEST_AUTOMATIC:
+ return true;
+ default:
+ return false;
}
}
-bool
-PrivacySpec::operator<(const PrivacySpec& other) const
-{
- return dest < other.dest;
-}
+bool PrivacySpec::operator<(const PrivacySpec& other) const { return dest < other.dest; }
-bool
-PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const
-{
+bool PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const {
uint8_t policy = privacy != NULL ? privacy->dest : defaultDest;
return allowDest(dest, policy);
}
-bool
-PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
+bool PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
-PrivacySpec PrivacySpec::new_spec(int dest)
-{
+PrivacySpec PrivacySpec::new_spec(int dest) {
switch (dest) {
case android::os::DEST_AUTOMATIC:
case android::os::DEST_EXPLICIT:
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index ce1b8e9..6b6de9c 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef PRIVACY_H
#define PRIVACY_H
@@ -20,7 +21,7 @@
#include <stdint.h>
// This is the default value of DEST enum, sync with privacy.proto
-const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident
+const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident
const uint8_t DEST_DEFAULT_VALUE = DEST_UNSET;
/*
@@ -68,15 +69,17 @@
bool operator<(const PrivacySpec& other) const;
// check permission of a policy, if returns true, don't strip the data.
- bool CheckPremission(const Privacy* privacy, const uint8_t defaultDest = DEST_DEFAULT_VALUE) const;
+ bool CheckPremission(const Privacy* privacy,
+ const uint8_t defaultDest = DEST_DEFAULT_VALUE) const;
// if returns true, no data need to be stripped.
bool RequireAll() const;
// Constructs spec using static methods below.
static PrivacySpec new_spec(int dest);
+
private:
PrivacySpec(uint8_t dest) : dest(dest) {}
};
-#endif // PRIVACY_H
+#endif // PRIVACY_H
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index f53befe..e4128f4 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -13,29 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "PrivacyBuffer.h"
-#include "io_util.h"
+#include "incidentd_util.h"
+#include <android-base/file.h>
#include <android/util/protobuf.h>
#include <cutils/log.h>
using namespace android::util;
-const bool DEBUG = false;
-
/**
* Write the field to buf based on the wire type, iterator will point to next field.
* If skip is set to true, no data will be written to buf. Return number of bytes written.
*/
-void
-PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip)
-{
- if (DEBUG) ALOGD("%s field %d (wiretype = %d)", skip ? "skip" : "write",
- read_field_id(fieldTag), read_wire_type(fieldTag));
-
+void PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) {
uint8_t wireType = read_wire_type(fieldTag);
size_t bytesToWrite = 0;
uint32_t varint = 0;
@@ -54,18 +47,17 @@
break;
case WIRE_TYPE_LENGTH_DELIMITED:
bytesToWrite = mData.readRawVarint();
- if(!skip) mProto.writeLengthDelimitedHeader(read_field_id(fieldTag), bytesToWrite);
+ if (!skip) mProto.writeLengthDelimitedHeader(read_field_id(fieldTag), bytesToWrite);
break;
case WIRE_TYPE_FIXED32:
if (!skip) mProto.writeRawVarint(fieldTag);
bytesToWrite = 4;
break;
}
- if (DEBUG) ALOGD("%s %d bytes of data", skip ? "skip" : "write", (int)bytesToWrite);
if (skip) {
mData.rp()->move(bytesToWrite);
} else {
- for (size_t i=0; i<bytesToWrite; i++) {
+ for (size_t i = 0; i < bytesToWrite; i++) {
mProto.writeRawByte(mData.next());
}
}
@@ -78,28 +70,29 @@
* The iterator must point to the head of a protobuf formatted field for successful operation.
* After exit with NO_ERROR, iterator points to the next protobuf field's head.
*/
-status_t
-PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec)
-{
+status_t PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec,
+ int depth /* use as a counter for this recusive method. */) {
if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE;
uint32_t fieldTag = mData.readRawVarint();
- const Privacy* policy = lookup(parentPolicy, read_field_id(fieldTag));
+ uint32_t fieldId = read_field_id(fieldTag);
+ const Privacy* policy = lookup(parentPolicy, fieldId);
+ VLOG("[Depth %2d]Try to strip id %d, wiretype %d", depth, fieldId, read_wire_type(fieldTag));
if (policy == NULL || policy->children == NULL) {
- if (DEBUG) ALOGD("Not a message field %d: dest(%d)", read_field_id(fieldTag),
- policy != NULL ? policy->dest : parentPolicy->dest);
-
bool skip = !spec.CheckPremission(policy, parentPolicy->dest);
// iterator will point to head of next field
+ size_t currentAt = mData.rp()->pos();
writeFieldOrSkip(fieldTag, skip);
+ VLOG("[Depth %2d]Field %d %ss %d bytes", depth, fieldId, skip ? "skip" : "write",
+ (int)(get_varint_size(fieldTag) + mData.rp()->pos() - currentAt));
return NO_ERROR;
}
// current field is message type and its sub-fields have extra privacy policies
uint32_t msgSize = mData.readRawVarint();
- EncodedBuffer::Pointer start = mData.rp()->copy();
+ size_t start = mData.rp()->pos();
long long token = mProto.start(encode_field_id(policy));
- while (mData.rp()->pos() - start.pos() != msgSize) {
- status_t err = stripField(policy, spec);
+ while (mData.rp()->pos() - start != msgSize) {
+ status_t err = stripField(policy, spec, depth + 1);
if (err != NO_ERROR) return err;
}
mProto.end(token);
@@ -108,53 +101,39 @@
// ================================================================================
PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data)
- :mPolicy(policy),
- mData(data),
- mProto(),
- mSize(0)
-{
-}
+ : mPolicy(policy), mData(data), mProto(), mSize(0) {}
-PrivacyBuffer::~PrivacyBuffer()
-{
-}
+PrivacyBuffer::~PrivacyBuffer() {}
-status_t
-PrivacyBuffer::strip(const PrivacySpec& spec)
-{
- if (DEBUG) ALOGD("Strip with spec %d", spec.dest);
+status_t PrivacyBuffer::strip(const PrivacySpec& spec) {
+ VLOG("Strip with spec %d", spec.dest);
// optimization when no strip happens
if (mPolicy == NULL || mPolicy->children == NULL || spec.RequireAll()) {
if (spec.CheckPremission(mPolicy)) mSize = mData.size();
return NO_ERROR;
}
while (mData.hasNext()) {
- status_t err = stripField(mPolicy, spec);
+ status_t err = stripField(mPolicy, spec, 0);
if (err != NO_ERROR) return err;
}
if (mData.bytesRead() != mData.size()) return BAD_VALUE;
mSize = mProto.size();
- mData.rp()->rewind(); // rewind the read pointer back to beginning after the strip.
+ mData.rp()->rewind(); // rewind the read pointer back to beginning after the strip.
return NO_ERROR;
}
-void
-PrivacyBuffer::clear()
-{
+void PrivacyBuffer::clear() {
mSize = 0;
mProto.clear();
}
-size_t
-PrivacyBuffer::size() const { return mSize; }
+size_t PrivacyBuffer::size() const { return mSize; }
-status_t
-PrivacyBuffer::flush(int fd)
-{
+status_t PrivacyBuffer::flush(int fd) {
status_t err = NO_ERROR;
EncodedBuffer::iterator iter = size() == mData.size() ? mData : mProto.data();
while (iter.readBuffer() != NULL) {
- err = write_all(fd, iter.readBuffer(), iter.currentToRead());
+ err = WriteFully(fd, iter.readBuffer(), iter.currentToRead()) ? NO_ERROR : -errno;
iter.rp()->move(iter.currentToRead());
if (err != NO_ERROR) return err;
}
diff --git a/cmds/incidentd/src/PrivacyBuffer.h b/cmds/incidentd/src/PrivacyBuffer.h
index c9ca9a7..92e1a25 100644
--- a/cmds/incidentd/src/PrivacyBuffer.h
+++ b/cmds/incidentd/src/PrivacyBuffer.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef PRIVACY_BUFFER_H
#define PRIVACY_BUFFER_H
@@ -31,14 +32,14 @@
* PrivacyBuffer holds the original protobuf data and strips PII-sensitive fields
* based on the request and holds stripped data in its own buffer for output.
*/
-class PrivacyBuffer
-{
+class PrivacyBuffer {
public:
PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data);
~PrivacyBuffer();
/**
- * Strip based on the request and hold data in its own buffer. Return NO_ERROR if strip succeeds.
+ * Strip based on the request and hold data in its own buffer. Return NO_ERROR if strip
+ * succeeds.
*/
status_t strip(const PrivacySpec& spec);
@@ -64,8 +65,8 @@
ProtoOutputStream mProto;
size_t mSize;
- status_t stripField(const Privacy* parentPolicy, const PrivacySpec& spec);
+ status_t stripField(const Privacy* parentPolicy, const PrivacySpec& spec, int depth);
void writeFieldOrSkip(uint32_t fieldTag, bool skip);
};
-#endif // PRIVACY_BUFFER_H
\ No newline at end of file
+#endif // PRIVACY_BUFFER_H
\ No newline at end of file
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 06baeba..c0b5358 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "Reporter.h"
@@ -26,11 +25,11 @@
#include <private/android_filesystem_config.h>
#include <utils/SystemClock.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
-#include <fcntl.h>
#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
/**
* The directory where the incident reports are stored.
@@ -39,62 +38,37 @@
// ================================================================================
ReportRequest::ReportRequest(const IncidentReportArgs& a,
- const sp<IIncidentReportStatusListener> &l, int f)
- :args(a),
- listener(l),
- fd(f),
- err(NO_ERROR)
-{
-}
+ const sp<IIncidentReportStatusListener>& l, int f)
+ : args(a), listener(l), fd(f), err(NO_ERROR) {}
-ReportRequest::~ReportRequest()
-{
+ReportRequest::~ReportRequest() {
if (fd >= 0) {
// clean up the opened file descriptor
close(fd);
}
}
-bool
-ReportRequest::ok()
-{
- return fd >= 0 && err == NO_ERROR;
-}
+bool ReportRequest::ok() { return fd >= 0 && err == NO_ERROR; }
// ================================================================================
ReportRequestSet::ReportRequestSet()
- :mRequests(),
- mSections(),
- mMainFd(-1),
- mMainDest(-1),
- mMetadata(),
- mSectionStats()
-{
-}
+ : mRequests(), mSections(), mMainFd(-1), mMainDest(-1), mMetadata(), mSectionStats() {}
-ReportRequestSet::~ReportRequestSet()
-{
-}
+ReportRequestSet::~ReportRequestSet() {}
// TODO: dedup on exact same args and fd, report the status back to listener!
-void
-ReportRequestSet::add(const sp<ReportRequest>& request)
-{
+void ReportRequestSet::add(const sp<ReportRequest>& request) {
mRequests.push_back(request);
mSections.merge(request->args);
mMetadata.set_request_size(mMetadata.request_size() + 1);
}
-void
-ReportRequestSet::setMainFd(int fd)
-{
+void ReportRequestSet::setMainFd(int fd) {
mMainFd = fd;
mMetadata.set_use_dropbox(fd > 0);
}
-void
-ReportRequestSet::setMainDest(int dest)
-{
+void ReportRequestSet::setMainDest(int dest) {
mMainDest = dest;
PrivacySpec spec = PrivacySpec::new_spec(dest);
switch (spec.dest) {
@@ -110,13 +84,9 @@
}
}
-bool
-ReportRequestSet::containsSection(int id) {
- return mSections.containsSection(id);
-}
+bool ReportRequestSet::containsSection(int id) { return mSections.containsSection(id); }
-IncidentMetadata::SectionStats*
-ReportRequestSet::sectionStats(int id) {
+IncidentMetadata::SectionStats* ReportRequestSet::sectionStats(int id) {
if (mSectionStats.find(id) == mSectionStats.end()) {
auto stats = mMetadata.add_sections();
stats->set_id(id);
@@ -128,9 +98,7 @@
// ================================================================================
Reporter::Reporter() : Reporter(INCIDENT_DIRECTORY) { isTest = false; };
-Reporter::Reporter(const char* directory)
- :batch()
-{
+Reporter::Reporter(const char* directory) : batch() {
char buf[100];
// TODO: Make the max size smaller for user builds.
@@ -148,13 +116,9 @@
mFilename = mIncidentDirectory + buf;
}
-Reporter::~Reporter()
-{
-}
+Reporter::~Reporter() {}
-Reporter::run_report_status_t
-Reporter::runReport()
-{
+Reporter::run_report_status_t Reporter::runReport() {
status_t err = NO_ERROR;
bool needMainFd = false;
int mainFd = -1;
@@ -163,7 +127,7 @@
MetadataSection metadataSection;
// See if we need the main file
- for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+ for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
if ((*it)->fd < 0 && mainFd < 0) {
needMainFd = true;
mainDest = (*it)->args.dest();
@@ -194,7 +158,7 @@
}
// Tell everyone that we're starting.
- for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+ for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
if ((*it)->listener != NULL) {
(*it)->listener->onReportStarted();
}
@@ -205,15 +169,14 @@
// For each of the report fields, see if we need it, and if so, execute the command
// and report to those that care that we're doing it.
- for (const Section** section=SECTION_LIST; *section; section++) {
+ for (const Section** section = SECTION_LIST; *section; section++) {
const int id = (*section)->id;
if (this->batch.containsSection(id)) {
ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string());
- // Notify listener of starting.
- for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+ for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
- (*it)->listener->onReportSectionStatus(id,
- IIncidentReportStatusListener::STATUS_STARTING);
+ (*it)->listener->onReportSectionStatus(
+ id, IIncidentReportStatusListener::STATUS_STARTING);
}
}
@@ -227,15 +190,15 @@
stats->set_exec_duration_ms(endTime - startTime);
if (err != NO_ERROR) {
ALOGW("Incident section %s (%d) failed: %s. Stopping report.",
- (*section)->name.string(), id, strerror(-err));
+ (*section)->name.string(), id, strerror(-err));
goto DONE;
}
- // Notify listener of ending.
- for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+ // Notify listener of starting
+ for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
- (*it)->listener->onReportSectionStatus(id,
- IIncidentReportStatusListener::STATUS_FINISHED);
+ (*it)->listener->onReportSectionStatus(
+ id, IIncidentReportStatusListener::STATUS_FINISHED);
}
}
ALOGD("Finish incident report section %d '%s'", id, (*section)->name.string());
@@ -252,7 +215,7 @@
}
// Tell everyone that we're done.
- for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+ for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
if ((*it)->listener != NULL) {
if (err == NO_ERROR) {
(*it)->listener->onReportFinished();
@@ -274,7 +237,7 @@
// If the status was ok, delete the file. If not, leave it around until the next
// boot or the next checkin. If the directory gets too big older files will
// be rotated out.
- if(!isTest) unlink(mFilename.c_str());
+ if (!isTest) unlink(mFilename.c_str());
}
return REPORT_FINISHED;
@@ -283,9 +246,7 @@
/**
* Create our output file and set the access permissions to -rw-rw----
*/
-status_t
-Reporter::create_file(int* fd)
-{
+status_t Reporter::create_file(int* fd) {
const char* filename = mFilename.c_str();
*fd = open(filename, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0660);
@@ -307,9 +268,7 @@
return NO_ERROR;
}
-Reporter::run_report_status_t
-Reporter::upload_backlog()
-{
+Reporter::run_report_status_t Reporter::upload_backlog() {
DIR* dir;
struct dirent* entry;
struct stat st;
@@ -360,4 +319,3 @@
return REPORT_FINISHED;
}
-
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index 6058068..0f3f221 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef REPORTER_H
#define REPORTER_H
@@ -33,23 +34,21 @@
using namespace std;
// ================================================================================
-struct ReportRequest : public virtual RefBase
-{
+struct ReportRequest : public virtual RefBase {
IncidentReportArgs args;
sp<IIncidentReportStatusListener> listener;
int fd;
status_t err;
- ReportRequest(const IncidentReportArgs& args,
- const sp<IIncidentReportStatusListener> &listener, int fd);
+ ReportRequest(const IncidentReportArgs& args, const sp<IIncidentReportStatusListener>& listener,
+ int fd);
virtual ~ReportRequest();
- bool ok(); // returns true if the request is ok for write.
+ bool ok(); // returns true if the request is ok for write.
};
// ================================================================================
-class ReportRequestSet
-{
+class ReportRequestSet {
public:
ReportRequestSet();
~ReportRequestSet();
@@ -81,18 +80,14 @@
};
// ================================================================================
-class Reporter : public virtual RefBase
-{
+class Reporter : public virtual RefBase {
public:
- enum run_report_status_t {
- REPORT_FINISHED = 0,
- REPORT_NEEDS_DROPBOX = 1
- };
+ enum run_report_status_t { REPORT_FINISHED = 0, REPORT_NEEDS_DROPBOX = 1 };
ReportRequestSet batch;
- Reporter(); // PROD must use this constructor.
- Reporter(const char* directory); // For testing purpose only.
+ Reporter(); // PROD must use this constructor.
+ Reporter(const char* directory); // For testing purpose only.
virtual ~Reporter();
// Run the report as described in the batch and args parameters.
@@ -110,8 +105,7 @@
status_t create_file(int* fd);
- bool isTest = true; // default to true for testing
+ bool isTest = true; // default to true for testing
};
-
-#endif // REPORTER_H
+#endif // REPORTER_H
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 3c76298..2e4e980 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "Section.h"
@@ -26,20 +25,21 @@
#include <memory>
#include <mutex>
+#include <android-base/file.h>
#include <android/util/protobuf.h>
#include <binder/IServiceManager.h>
#include <log/log_event_list.h>
-#include <log/logprint.h>
#include <log/log_read.h>
+#include <log/logprint.h>
#include <private/android_logger.h>
#include "FdBuffer.h"
-#include "frameworks/base/core/proto/android/util/log.proto.h"
-#include "io_util.h"
#include "Privacy.h"
#include "PrivacyBuffer.h"
-#include "section_list.h"
+#include "frameworks/base/core/proto/android/util/log.proto.h"
+#include "incidentd_util.h"
+using namespace android::base;
using namespace android::util;
using namespace std;
@@ -48,21 +48,18 @@
const int FIELD_ID_INCIDENT_METADATA = 2;
// incident section parameters
-const int WAIT_MAX = 5;
+const int WAIT_MAX = 5;
const struct timespec WAIT_INTERVAL_NS = {0, 200 * 1000 * 1000};
const char INCIDENT_HELPER[] = "/system/bin/incident_helper";
-static pid_t
-fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe)
-{
- const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL };
+static pid_t fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe,
+ Fpipe& c2pPipe) {
+ const char* ihArgs[]{INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL};
// fork used in multithreaded environment, avoid adding unnecessary code in child process
pid_t pid = fork();
if (pid == 0) {
- if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(), STDIN_FILENO)) != 0
- || !p2cPipe.close()
- || TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1
- || !c2pPipe.close()) {
+ if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(), STDIN_FILENO)) != 0 || !p2cPipe.close() ||
+ TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1 || !c2pPipe.close()) {
ALOGW("%s can't setup stdin and stdout for incident helper", name);
_exit(EXIT_FAILURE);
}
@@ -73,7 +70,7 @@
execv(INCIDENT_HELPER, const_cast<char**>(ihArgs));
ALOGW("%s failed in incident helper process: %s", name, strerror(errno));
- _exit(EXIT_FAILURE); // always exits with failure if any
+ _exit(EXIT_FAILURE); // always exits with failure if any
}
// close the fds used in incident helper
close(p2cPipe.readFd());
@@ -84,18 +81,18 @@
// ================================================================================
static status_t statusCode(int status) {
if (WIFSIGNALED(status)) {
- ALOGD("return by signal: %s", strerror(WTERMSIG(status)));
- return -WTERMSIG(status);
+ VLOG("return by signal: %s", strerror(WTERMSIG(status)));
+ return -WTERMSIG(status);
} else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
- ALOGD("return by exit: %s", strerror(WEXITSTATUS(status)));
- return -WEXITSTATUS(status);
+ VLOG("return by exit: %s", strerror(WEXITSTATUS(status)));
+ return -WEXITSTATUS(status);
}
return NO_ERROR;
}
static status_t kill_child(pid_t pid) {
int status;
- ALOGD("try to kill child process %d", pid);
+ VLOG("try to kill child process %d", pid);
kill(pid, SIGKILL);
if (waitpid(pid, &status, 0) == -1) return -1;
return statusCode(status);
@@ -105,7 +102,7 @@
int status;
bool died = false;
// wait for child to report status up to 1 seconds
- for(int loop = 0; !died && loop < WAIT_MAX; loop++) {
+ for (int loop = 0; !died && loop < WAIT_MAX; loop++) {
if (waitpid(pid, &status, WNOHANG) == pid) died = true;
// sleep for 0.2 second
nanosleep(&WAIT_INTERVAL_NS, NULL);
@@ -114,38 +111,14 @@
return statusCode(status);
}
// ================================================================================
-static const Privacy*
-get_privacy_of_section(int id)
-{
- int l = 0;
- int r = PRIVACY_POLICY_COUNT - 1;
- while (l <= r) {
- int mid = (l + r) >> 1;
- const Privacy* p = PRIVACY_POLICY_LIST[mid];
-
- if (p->field_id < (uint32_t)id) {
- l = mid + 1;
- } else if (p->field_id > (uint32_t)id) {
- r = mid - 1;
- } else {
- return p;
- }
- }
- return NULL;
-}
-
-// ================================================================================
-static status_t
-write_section_header(int fd, int sectionId, size_t size)
-{
+static status_t write_section_header(int fd, int sectionId, size_t size) {
uint8_t buf[20];
- uint8_t *p = write_length_delimited_tag_header(buf, sectionId, size);
- return write_all(fd, buf, p-buf);
+ uint8_t* p = write_length_delimited_tag_header(buf, sectionId, size);
+ return WriteFully(fd, buf, p - buf) ? NO_ERROR : -errno;
}
-static status_t
-write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* requests)
-{
+static status_t write_report_requests(const int id, const FdBuffer& buffer,
+ ReportRequestSet* requests) {
status_t err = -EBADF;
EncodedBuffer::iterator data = buffer.data();
PrivacyBuffer privacyBuffer(get_privacy_of_section(id), data);
@@ -171,18 +144,24 @@
for (auto mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) {
PrivacySpec spec = mit->first;
err = privacyBuffer.strip(spec);
- if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted.
+ if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted.
if (privacyBuffer.size() == 0) continue;
for (auto it = mit->second.begin(); it != mit->second.end(); it++) {
sp<ReportRequest> request = *it;
err = write_section_header(request->fd, id, privacyBuffer.size());
- if (err != NO_ERROR) { request->err = err; continue; }
+ if (err != NO_ERROR) {
+ request->err = err;
+ continue;
+ }
err = privacyBuffer.flush(request->fd);
- if (err != NO_ERROR) { request->err = err; continue; }
+ if (err != NO_ERROR) {
+ request->err = err;
+ continue;
+ }
writeable++;
- ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id,
- privacyBuffer.size(), request->fd, spec.dest);
+ VLOG("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(),
+ request->fd, spec.dest);
}
privacyBuffer.clear();
}
@@ -191,16 +170,22 @@
if (requests->mainFd() >= 0) {
PrivacySpec spec = PrivacySpec::new_spec(requests->mainDest());
err = privacyBuffer.strip(spec);
- if (err != NO_ERROR) return err; // the buffer data is corrupted.
+ if (err != NO_ERROR) return err; // the buffer data is corrupted.
if (privacyBuffer.size() == 0) goto DONE;
err = write_section_header(requests->mainFd(), id, privacyBuffer.size());
- if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
+ if (err != NO_ERROR) {
+ requests->setMainFd(-1);
+ goto DONE;
+ }
err = privacyBuffer.flush(requests->mainFd());
- if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
+ if (err != NO_ERROR) {
+ requests->setMainFd(-1);
+ goto DONE;
+ }
writeable++;
- ALOGD("Section %d flushed %zu bytes to dropbox %d with spec %d", id,
- privacyBuffer.size(), requests->mainFd(), spec.dest);
+ VLOG("Section %d flushed %zu bytes to dropbox %d with spec %d", id, privacyBuffer.size(),
+ requests->mainFd(), spec.dest);
stats->set_report_size_bytes(privacyBuffer.size());
}
@@ -210,40 +195,28 @@
}
// ================================================================================
-Section::Section(int i, const int64_t timeoutMs)
- :id(i),
- timeoutMs(timeoutMs)
-{
-}
+Section::Section(int i, const int64_t timeoutMs) : id(i), timeoutMs(timeoutMs) {}
-Section::~Section()
-{
-}
+Section::~Section() {}
// ================================================================================
-HeaderSection::HeaderSection()
- :Section(FIELD_ID_INCIDENT_HEADER, 0)
-{
-}
+HeaderSection::HeaderSection() : Section(FIELD_ID_INCIDENT_HEADER, 0) {}
-HeaderSection::~HeaderSection()
-{
-}
+HeaderSection::~HeaderSection() {}
-status_t
-HeaderSection::Execute(ReportRequestSet* requests) const
-{
- for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) {
+status_t HeaderSection::Execute(ReportRequestSet* requests) const {
+ for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
const sp<ReportRequest> request = *it;
const vector<vector<uint8_t>>& headers = request->args.headers();
- for (vector<vector<uint8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) {
+ for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
+ buf++) {
if (buf->empty()) continue;
// So the idea is only requests with negative fd are written to dropbox file.
int fd = request->fd >= 0 ? request->fd : requests->mainFd();
write_section_header(fd, id, buf->size());
- write_all(fd, (uint8_t const*)buf->data(), buf->size());
+ WriteFully(fd, (uint8_t const*)buf->data(), buf->size());
// If there was an error now, there will be an error later and we will remove
// it from the list then.
}
@@ -251,54 +224,49 @@
return NO_ERROR;
}
// ================================================================================
-MetadataSection::MetadataSection()
- :Section(FIELD_ID_INCIDENT_METADATA, 0)
-{
-}
+MetadataSection::MetadataSection() : Section(FIELD_ID_INCIDENT_METADATA, 0) {}
-MetadataSection::~MetadataSection()
-{
-}
+MetadataSection::~MetadataSection() {}
-status_t
-MetadataSection::Execute(ReportRequestSet* requests) const
-{
+status_t MetadataSection::Execute(ReportRequestSet* requests) const {
std::string metadataBuf;
requests->metadata().SerializeToString(&metadataBuf);
- for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) {
+ for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
const sp<ReportRequest> request = *it;
if (metadataBuf.empty() || request->fd < 0 || request->err != NO_ERROR) {
continue;
}
write_section_header(request->fd, id, metadataBuf.size());
- write_all(request->fd, (uint8_t const*)metadataBuf.data(), metadataBuf.size());
+ if (!WriteFully(request->fd, (uint8_t const*)metadataBuf.data(), metadataBuf.size())) {
+ ALOGW("Failed to write metadata to fd %d", request->fd);
+ // we don't fail if we can't write to a single request's fd.
+ }
}
if (requests->mainFd() >= 0 && !metadataBuf.empty()) {
write_section_header(requests->mainFd(), id, metadataBuf.size());
- write_all(requests->mainFd(), (uint8_t const*)metadataBuf.data(), metadataBuf.size());
+ if (!WriteFully(requests->mainFd(), (uint8_t const*)metadataBuf.data(), metadataBuf.size())) {
+ ALOGW("Failed to write metadata to dropbox fd %d", requests->mainFd());
+ return -1;
+ }
}
return NO_ERROR;
}
// ================================================================================
FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
- :Section(id, timeoutMs),
- mFilename(filename)
-{
+ : Section(id, timeoutMs), mFilename(filename) {
name = filename;
mIsSysfs = strncmp(filename, "/sys/", 5) == 0;
}
FileSection::~FileSection() {}
-status_t
-FileSection::Execute(ReportRequestSet* requests) const
-{
+status_t FileSection::Execute(ReportRequestSet* requests) const {
// read from mFilename first, make sure the file is available
// add O_CLOEXEC to make sure it is closed when exec incident helper
int fd = open(mFilename, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
- ALOGW("FileSection '%s' failed to open file", this->name.string());
- return -errno;
+ ALOGW("FileSection '%s' failed to open file", this->name.string());
+ return -errno;
}
FdBuffer buffer;
@@ -318,22 +286,23 @@
// parent process
status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
- this->timeoutMs, mIsSysfs);
+ this->timeoutMs, mIsSysfs);
if (readStatus != NO_ERROR || buffer.timedOut()) {
ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s",
- this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+ this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
kill_child(pid);
return readStatus;
}
status_t ihStatus = wait_child(pid);
if (ihStatus != NO_ERROR) {
- ALOGW("FileSection '%s' abnormal child process: %s", this->name.string(), strerror(-ihStatus));
+ ALOGW("FileSection '%s' abnormal child process: %s", this->name.string(),
+ strerror(-ihStatus));
return ihStatus;
}
- ALOGD("FileSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
- (int)buffer.durationMs());
+ VLOG("FileSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
+ (int)buffer.durationMs());
status_t err = write_report_requests(this->id, buffer, requests);
if (err != NO_ERROR) {
ALOGW("FileSection '%s' failed writing: %s", this->name.string(), strerror(-err));
@@ -344,8 +313,7 @@
}
// ================================================================================
-struct WorkerThreadData : public virtual RefBase
-{
+struct WorkerThreadData : public virtual RefBase {
const WorkerThreadSection* section;
int fds[2];
@@ -362,31 +330,19 @@
};
WorkerThreadData::WorkerThreadData(const WorkerThreadSection* sec)
- :section(sec),
- workerDone(false),
- workerError(NO_ERROR)
-{
+ : section(sec), workerDone(false), workerError(NO_ERROR) {
fds[0] = -1;
fds[1] = -1;
}
-WorkerThreadData::~WorkerThreadData()
-{
-}
+WorkerThreadData::~WorkerThreadData() {}
// ================================================================================
-WorkerThreadSection::WorkerThreadSection(int id)
- :Section(id)
-{
-}
+WorkerThreadSection::WorkerThreadSection(int id) : Section(id) {}
-WorkerThreadSection::~WorkerThreadSection()
-{
-}
+WorkerThreadSection::~WorkerThreadSection() {}
-static void*
-worker_thread_func(void* cookie)
-{
+static void* worker_thread_func(void* cookie) {
WorkerThreadData* data = (WorkerThreadData*)cookie;
status_t err = data->section->BlockingCall(data->writeFd());
@@ -402,9 +358,7 @@
return NULL;
}
-status_t
-WorkerThreadSection::Execute(ReportRequestSet* requests) const
-{
+status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const {
status_t err = NO_ERROR;
pthread_t thread;
pthread_attr_t attr;
@@ -447,7 +401,7 @@
if (err != NO_ERROR) {
// TODO: Log this error into the incident report.
ALOGW("WorkerThreadSection '%s' reader failed with error '%s'", this->name.string(),
- strerror(-err));
+ strerror(-err));
}
// Done with the read fd. The worker thread closes the write one so
@@ -466,7 +420,7 @@
err = data->workerError;
// TODO: Log this error into the incident report.
ALOGW("WorkerThreadSection '%s' worker failed with error '%s'", this->name.string(),
- strerror(-err));
+ strerror(-err));
}
}
}
@@ -484,13 +438,13 @@
// just exit with a log messasge.
if (err != NO_ERROR) {
ALOGW("WorkerThreadSection '%s' failed with error '%s'", this->name.string(),
- strerror(-err));
+ strerror(-err));
return NO_ERROR;
}
// Write the data that was collected
- ALOGD("WorkerThreadSection '%s' wrote %zd bytes in %d ms", name.string(), buffer.size(),
- (int)buffer.durationMs());
+ VLOG("WorkerThreadSection '%s' wrote %zd bytes in %d ms", name.string(), buffer.size(),
+ (int)buffer.durationMs());
err = write_report_requests(this->id, buffer, requests);
if (err != NO_ERROR) {
ALOGW("WorkerThreadSection '%s' failed writing: '%s'", this->name.string(), strerror(-err));
@@ -501,14 +455,12 @@
}
// ================================================================================
-void
-CommandSection::init(const char* command, va_list args)
-{
+void CommandSection::init(const char* command, va_list args) {
va_list copied_args;
int numOfArgs = 0;
va_copy(copied_args, args);
- while(va_arg(copied_args, const char*) != NULL) {
+ while (va_arg(copied_args, const char*) != NULL) {
numOfArgs++;
}
va_end(copied_args);
@@ -518,41 +470,33 @@
mCommand[0] = command;
name = command;
- for (int i=0; i<numOfArgs; i++) {
+ for (int i = 0; i < numOfArgs; i++) {
const char* arg = va_arg(args, const char*);
- mCommand[i+1] = arg;
+ mCommand[i + 1] = arg;
name += " ";
name += arg;
}
- mCommand[numOfArgs+1] = NULL;
+ mCommand[numOfArgs + 1] = NULL;
}
CommandSection::CommandSection(int id, const int64_t timeoutMs, const char* command, ...)
- :Section(id, timeoutMs)
-{
+ : Section(id, timeoutMs) {
va_list args;
va_start(args, command);
init(command, args);
va_end(args);
}
-CommandSection::CommandSection(int id, const char* command, ...)
- :Section(id)
-{
+CommandSection::CommandSection(int id, const char* command, ...) : Section(id) {
va_list args;
va_start(args, command);
init(command, args);
va_end(args);
}
-CommandSection::~CommandSection()
-{
- free(mCommand);
-}
+CommandSection::~CommandSection() { free(mCommand); }
-status_t
-CommandSection::Execute(ReportRequestSet* requests) const
-{
+status_t CommandSection::Execute(ReportRequestSet* requests) const {
FdBuffer buffer;
Fpipe cmdPipe;
Fpipe ihPipe;
@@ -571,13 +515,15 @@
if (cmdPid == 0) {
// replace command's stdout with ihPipe's write Fd
if (dup2(cmdPipe.writeFd(), STDOUT_FILENO) != 1 || !ihPipe.close() || !cmdPipe.close()) {
- ALOGW("CommandSection '%s' failed to set up stdout: %s", this->name.string(), strerror(errno));
+ ALOGW("CommandSection '%s' failed to set up stdout: %s", this->name.string(),
+ strerror(errno));
_exit(EXIT_FAILURE);
}
- execvp(this->mCommand[0], (char *const *) this->mCommand);
- int err = errno; // record command error code
- ALOGW("CommandSection '%s' failed in executing command: %s", this->name.string(), strerror(errno));
- _exit(err); // exit with command error code
+ execvp(this->mCommand[0], (char* const*)this->mCommand);
+ int err = errno; // record command error code
+ ALOGW("CommandSection '%s' failed in executing command: %s", this->name.string(),
+ strerror(errno));
+ _exit(err); // exit with command error code
}
pid_t ihPid = fork_execute_incident_helper(this->id, this->name.string(), cmdPipe, ihPipe);
if (ihPid == -1) {
@@ -589,24 +535,26 @@
status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs);
if (readStatus != NO_ERROR || buffer.timedOut()) {
ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s",
- this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+ this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
kill_child(cmdPid);
kill_child(ihPid);
return readStatus;
}
- // TODO: wait for command here has one trade-off: the failed status of command won't be detected until
+ // TODO: wait for command here has one trade-off: the failed status of command won't be detected
+ // until
// buffer timeout, but it has advatage on starting the data stream earlier.
status_t cmdStatus = wait_child(cmdPid);
- status_t ihStatus = wait_child(ihPid);
+ status_t ihStatus = wait_child(ihPid);
if (cmdStatus != NO_ERROR || ihStatus != NO_ERROR) {
- ALOGW("CommandSection '%s' abnormal child processes, return status: command: %s, incident helper: %s",
- this->name.string(), strerror(-cmdStatus), strerror(-ihStatus));
+ ALOGW("CommandSection '%s' abnormal child processes, return status: command: %s, incident "
+ "helper: %s",
+ this->name.string(), strerror(-cmdStatus), strerror(-ihStatus));
return cmdStatus != NO_ERROR ? cmdStatus : ihStatus;
}
- ALOGD("CommandSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
- (int)buffer.durationMs());
+ VLOG("CommandSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
+ (int)buffer.durationMs());
status_t err = write_report_requests(this->id, buffer, requests);
if (err != NO_ERROR) {
ALOGW("CommandSection '%s' failed writing: %s", this->name.string(), strerror(-err));
@@ -617,9 +565,7 @@
// ================================================================================
DumpsysSection::DumpsysSection(int id, const char* service, ...)
- :WorkerThreadSection(id),
- mService(service)
-{
+ : WorkerThreadSection(id), mService(service) {
name = "dumpsys ";
name += service;
@@ -637,13 +583,9 @@
va_end(args);
}
-DumpsysSection::~DumpsysSection()
-{
-}
+DumpsysSection::~DumpsysSection() {}
-status_t
-DumpsysSection::BlockingCall(int pipeWriteFd) const
-{
+status_t DumpsysSection::BlockingCall(int pipeWriteFd) const {
// checkService won't wait for the service to show up like getService will.
sp<IBinder> service = defaultServiceManager()->checkService(mService);
@@ -667,30 +609,23 @@
// initialization only once in Section.cpp.
map<log_id_t, log_time> LogSection::gLastLogsRetrieved;
-LogSection::LogSection(int id, log_id_t logID)
- :WorkerThreadSection(id),
- mLogID(logID)
-{
+LogSection::LogSection(int id, log_id_t logID) : WorkerThreadSection(id), mLogID(logID) {
name += "logcat ";
name += android_log_id_to_name(logID);
switch (logID) {
- case LOG_ID_EVENTS:
- case LOG_ID_STATS:
- case LOG_ID_SECURITY:
- mBinary = true;
- break;
- default:
- mBinary = false;
+ case LOG_ID_EVENTS:
+ case LOG_ID_STATS:
+ case LOG_ID_SECURITY:
+ mBinary = true;
+ break;
+ default:
+ mBinary = false;
}
}
-LogSection::~LogSection()
-{
-}
+LogSection::~LogSection() {}
-static size_t
-trimTail(char const* buf, size_t len)
-{
+static size_t trimTail(char const* buf, size_t len) {
while (len > 0) {
char c = buf[len - 1];
if (c == '\0' || c == ' ' || c == '\n' || c == '\r' || c == ':') {
@@ -706,17 +641,15 @@
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}
-status_t
-LogSection::BlockingCall(int pipeWriteFd) const
-{
+status_t LogSection::BlockingCall(int pipeWriteFd) const {
status_t err = NO_ERROR;
// Open log buffer and getting logs since last retrieved time if any.
unique_ptr<logger_list, void (*)(logger_list*)> loggers(
- gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end() ?
- android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0) :
- android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- gLastLogsRetrieved[mLogID], 0),
- android_logger_list_free);
+ gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end()
+ ? android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0)
+ : android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+ gLastLogsRetrieved[mLogID], 0),
+ android_logger_list_free);
if (android_logger_open(loggers.get(), mLogID) == NULL) {
ALOGW("LogSection %s: Can't get logger.", this->name.string());
@@ -727,7 +660,7 @@
log_time lastTimestamp(0);
ProtoOutputStream proto;
- while (true) { // keeps reading until logd buffer is fully read.
+ while (true) { // keeps reading until logd buffer is fully read.
status_t err = android_logger_list_read(loggers.get(), &msg);
// err = 0 - no content, unexpected connection drop or EOF.
// err = +ive number - size of retrieved data from logger
@@ -742,7 +675,8 @@
if (mBinary) {
// remove the first uint32 which is tag's index in event log tags
android_log_context context = create_android_log_parser(msg.msg() + sizeof(uint32_t),
- msg.len() - sizeof(uint32_t));;
+ msg.len() - sizeof(uint32_t));
+ ;
android_log_list_element elem;
lastTimestamp.tv_sec = msg.entry_v1.sec;
@@ -752,38 +686,46 @@
long long token = proto.start(LogProto::BINARY_LOGS);
proto.write(BinaryLogEntry::SEC, msg.entry_v1.sec);
proto.write(BinaryLogEntry::NANOSEC, msg.entry_v1.nsec);
- proto.write(BinaryLogEntry::UID, (int) msg.entry_v4.uid);
+ proto.write(BinaryLogEntry::UID, (int)msg.entry_v4.uid);
proto.write(BinaryLogEntry::PID, msg.entry_v1.pid);
proto.write(BinaryLogEntry::TID, msg.entry_v1.tid);
- proto.write(BinaryLogEntry::TAG_INDEX, get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
+ proto.write(BinaryLogEntry::TAG_INDEX,
+ get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
do {
elem = android_log_read_next(context);
long long elemToken = proto.start(BinaryLogEntry::ELEMS);
switch (elem.type) {
case EVENT_TYPE_INT:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_INT);
- proto.write(BinaryLogEntry::Elem::VAL_INT32, (int) elem.data.int32);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_INT);
+ proto.write(BinaryLogEntry::Elem::VAL_INT32, (int)elem.data.int32);
break;
case EVENT_TYPE_LONG:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LONG);
- proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long) elem.data.int64);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_LONG);
+ proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long)elem.data.int64);
break;
case EVENT_TYPE_STRING:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_STRING);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_STRING);
proto.write(BinaryLogEntry::Elem::VAL_STRING, elem.data.string, elem.len);
break;
case EVENT_TYPE_FLOAT:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
proto.write(BinaryLogEntry::Elem::VAL_FLOAT, elem.data.float32);
break;
case EVENT_TYPE_LIST:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_LIST);
break;
case EVENT_TYPE_LIST_STOP:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
break;
case EVENT_TYPE_UNKNOWN:
- proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
+ proto.write(BinaryLogEntry::Elem::TYPE,
+ BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
break;
}
proto.end(elemToken);
@@ -811,7 +753,8 @@
proto.write(TextLogEntry::PID, entry.pid);
proto.write(TextLogEntry::TID, entry.tid);
proto.write(TextLogEntry::TAG, entry.tag, trimTail(entry.tag, entry.tagLen));
- proto.write(TextLogEntry::LOG, entry.message, trimTail(entry.message, entry.messageLen));
+ proto.write(TextLogEntry::LOG, entry.message,
+ trimTail(entry.message, entry.messageLen));
proto.end(token);
}
}
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 80cc033..d644681 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -13,31 +13,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef SECTIONS_H
#define SECTIONS_H
#include "Reporter.h"
-#include <map>
#include <stdarg.h>
+#include <map>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
#include <utils/Vector.h>
using namespace android;
-const int64_t REMOTE_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds
+const int64_t REMOTE_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds
/**
* Base class for sections
*/
-class Section
-{
+class Section {
public:
const int id;
- const int64_t timeoutMs; // each section must have a timeout
+ const int64_t timeoutMs; // each section must have a timeout
String8 name;
Section(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
@@ -49,8 +49,7 @@
/**
* Section that generates incident headers.
*/
-class HeaderSection : public Section
-{
+class HeaderSection : public Section {
public:
HeaderSection();
virtual ~HeaderSection();
@@ -61,8 +60,7 @@
/**
* Section that generates incident metadata.
*/
-class MetadataSection : public Section
-{
+class MetadataSection : public Section {
public:
MetadataSection();
virtual ~MetadataSection();
@@ -73,8 +71,7 @@
/**
* Section that reads in a file.
*/
-class FileSection : public Section
-{
+class FileSection : public Section {
public:
FileSection(int id, const char* filename, const int64_t timeoutMs = 5000 /* 5 seconds */);
virtual ~FileSection();
@@ -83,14 +80,13 @@
private:
const char* mFilename;
- bool mIsSysfs; // sysfs files are pollable but return POLLERR by default, handle it separately
+ bool mIsSysfs; // sysfs files are pollable but return POLLERR by default, handle it separately
};
/**
* Base class for sections that call a command that might need a timeout.
*/
-class WorkerThreadSection : public Section
-{
+class WorkerThreadSection : public Section {
public:
WorkerThreadSection(int id);
virtual ~WorkerThreadSection();
@@ -103,8 +99,7 @@
/**
* Section that forks and execs a command, and puts stdout as the section.
*/
-class CommandSection : public Section
-{
+class CommandSection : public Section {
public:
CommandSection(int id, const int64_t timeoutMs, const char* command, ...);
@@ -123,8 +118,7 @@
/**
* Section that calls dumpsys on a system service.
*/
-class DumpsysSection : public WorkerThreadSection
-{
+class DumpsysSection : public WorkerThreadSection {
public:
DumpsysSection(int id, const char* service, ...);
virtual ~DumpsysSection();
@@ -139,8 +133,7 @@
/**
* Section that reads from logd.
*/
-class LogSection : public WorkerThreadSection
-{
+class LogSection : public WorkerThreadSection {
// global last log retrieved timestamp for each log_id_t.
static map<log_id_t, log_time> gLastLogsRetrieved;
@@ -155,5 +148,4 @@
bool mBinary;
};
-#endif // SECTIONS_H
-
+#endif // SECTIONS_H
diff --git a/cmds/incidentd/src/incidentd_util.cpp b/cmds/incidentd/src/incidentd_util.cpp
new file mode 100644
index 0000000..2415860
--- /dev/null
+++ b/cmds/incidentd/src/incidentd_util.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 "incidentd_util.h"
+
+#include "section_list.h"
+
+const Privacy* get_privacy_of_section(int id) {
+ int l = 0;
+ int r = PRIVACY_POLICY_COUNT - 1;
+ while (l <= r) {
+ int mid = (l + r) >> 1;
+ const Privacy* p = PRIVACY_POLICY_LIST[mid];
+
+ if (p->field_id < (uint32_t)id) {
+ l = mid + 1;
+ } else if (p->field_id > (uint32_t)id) {
+ r = mid - 1;
+ } else {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+// ================================================================================
+Fpipe::Fpipe() : mRead(), mWrite() {}
+
+Fpipe::~Fpipe() { close(); }
+
+bool Fpipe::close() {
+ mRead.reset();
+ mWrite.reset();
+ return true;
+}
+
+bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
+
+int Fpipe::readFd() const { return mRead.get(); }
+
+int Fpipe::writeFd() const { return mWrite.get(); }
\ No newline at end of file
diff --git a/cmds/incidentd/src/io_util.h b/cmds/incidentd/src/incidentd_util.h
similarity index 74%
rename from cmds/incidentd/src/io_util.h
rename to cmds/incidentd/src/incidentd_util.h
index 320dd6c..09aa040 100644
--- a/cmds/incidentd/src/io_util.h
+++ b/cmds/incidentd/src/incidentd_util.h
@@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
-#ifndef IO_UTIL_H
-#define IO_UTIL_H
+#ifndef INCIDENTD_UTIL_H
+#define INCIDENTD_UTIL_H
-#include <stdint.h>
-#include <utils/Errors.h>
+#include <android-base/unique_fd.h>
-using namespace android;
+#include "Privacy.h"
-status_t write_all(int fd, uint8_t const* buf, size_t size);
+using namespace android::base;
+
+const Privacy* get_privacy_of_section(int id);
class Fpipe {
public:
@@ -35,7 +37,8 @@
int writeFd() const;
private:
- int mFds[2];
+ unique_fd mRead;
+ unique_fd mWrite;
};
-#endif // IO_UTIL_H
\ No newline at end of file
+#endif // INCIDENTD_UTIL_H
\ No newline at end of file
diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp
deleted file mode 100644
index 90f543e..0000000
--- a/cmds/incidentd/src/io_util.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2017 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 "incidentd"
-
-#include "io_util.h"
-
-#include <unistd.h>
-
-status_t write_all(int fd, uint8_t const* buf, size_t size)
-{
- while (size > 0) {
- ssize_t amt = TEMP_FAILURE_RETRY(::write(fd, buf, size));
- if (amt < 0) {
- return -errno;
- }
- size -= amt;
- buf += amt;
- }
- return NO_ERROR;
-}
-
-Fpipe::Fpipe() {}
-
-Fpipe::~Fpipe() { close(); }
-
-bool Fpipe::close() { return !(::close(mFds[0]) || ::close(mFds[1])); }
-
-bool Fpipe::init() { return pipe(mFds) != -1; }
-
-int Fpipe::readFd() const { return mFds[0]; }
-
-int Fpipe::writeFd() const { return mFds[1]; }
diff --git a/cmds/incidentd/src/main.cpp b/cmds/incidentd/src/main.cpp
index 3a7511d..38b7449 100644
--- a/cmds/incidentd/src/main.cpp
+++ b/cmds/incidentd/src/main.cpp
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "IncidentService.h"
@@ -23,25 +22,22 @@
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/Status.h>
-#include <cutils/log.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
using namespace android;
// ================================================================================
-int
-main(int /*argc*/, char** /*argv*/)
-{
+int main(int /*argc*/, char** /*argv*/) {
// Set up the looper
sp<Looper> looper(Looper::prepare(0 /* opts */));
// Set up the binder
sp<ProcessState> ps(ProcessState::self());
- ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram
+ ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->disableBackgroundScheduling(true);
diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp
index 20111d8..b71c066 100644
--- a/cmds/incidentd/src/report_directory.cpp
+++ b/cmds/incidentd/src/report_directory.cpp
@@ -13,19 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
#include "report_directory.h"
-#include <cutils/log.h>
#include <private/android_filesystem_config.h>
#include <utils/String8.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
#include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include <vector>
@@ -33,9 +31,7 @@
using namespace android;
using namespace std;
-status_t
-create_directory(const char* directory)
-{
+status_t create_directory(const char* directory) {
struct stat st;
status_t err = NO_ERROR;
char* dir = strdup(directory);
@@ -75,14 +71,14 @@
goto done;
}
if ((st.st_mode & 0777) != 0770) {
- ALOGE("No incident reports today. Mode is %0o on report directory %s",
- st.st_mode, directory);
+ ALOGE("No incident reports today. Mode is %0o on report directory %s", st.st_mode,
+ directory);
err = BAD_VALUE;
goto done;
}
if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) {
ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s",
- st.st_uid, st.st_gid, directory);
+ st.st_uid, st.st_gid, directory);
err = BAD_VALUE;
goto done;
}
@@ -92,20 +88,17 @@
return err;
}
-static bool
-stat_mtime_cmp(const pair<String8,struct stat>& a, const pair<String8,struct stat>& b)
-{
+static bool stat_mtime_cmp(const pair<String8, struct stat>& a,
+ const pair<String8, struct stat>& b) {
return a.second.st_mtime < b.second.st_mtime;
}
-void
-clean_directory(const char* directory, off_t maxSize, size_t maxCount)
-{
+void clean_directory(const char* directory, off_t maxSize, size_t maxCount) {
DIR* dir;
struct dirent* entry;
struct stat st;
- vector<pair<String8,struct stat>> files;
+ vector<pair<String8, struct stat>> files;
if ((dir = opendir(directory)) == NULL) {
ALOGE("Couldn't open incident directory: %s", directory);
@@ -131,7 +124,7 @@
if (!S_ISREG(st.st_mode)) {
continue;
}
- files.push_back(pair<String8,struct stat>(filename, st));
+ files.push_back(pair<String8, struct stat>(filename, st));
totalSize += st.st_size;
totalCount++;
@@ -148,8 +141,8 @@
sort(files.begin(), files.end(), stat_mtime_cmp);
// Remove files until we're under our limits.
- for (vector<pair<String8,struct stat>>::iterator it = files.begin();
- it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) {
+ for (vector<pair<String8, struct stat>>::iterator it = files.begin();
+ it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) {
remove(it->first.string());
totalSize -= it->second.st_size;
totalCount--;
diff --git a/cmds/incidentd/src/report_directory.h b/cmds/incidentd/src/report_directory.h
index bed4f86..2a3cf4c 100644
--- a/cmds/incidentd/src/report_directory.h
+++ b/cmds/incidentd/src/report_directory.h
@@ -13,17 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef DIRECTORY_CLEANER_H
#define DIRECTORY_CLEANER_H
+#include <sys/types.h>
#include <utils/Errors.h>
-#include <sys/types.h>
-
-using namespace android;
-
-status_t create_directory(const char* directory);
+android::status_t create_directory(const char* directory);
void clean_directory(const char* directory, off_t maxSize, size_t maxCount);
-#endif // DIRECTORY_CLEANER_H
+#endif // DIRECTORY_CLEANER_H
diff --git a/cmds/incidentd/src/section_list.h b/cmds/incidentd/src/section_list.h
index ddc0505..697e66f 100644
--- a/cmds/incidentd/src/section_list.h
+++ b/cmds/incidentd/src/section_list.h
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
#ifndef SECTION_LIST_H
#define SECTION_LIST_H
-#include <log/log_event_list.h> // include log_id_t enums.
+#include <log/log_event_list.h> // include log_id_t enums.
#include "Privacy.h"
#include "Section.h"
@@ -36,5 +37,4 @@
extern const int PRIVACY_POLICY_COUNT;
-#endif // SECTION_LIST_H
-
+#endif // SECTION_LIST_H
diff --git a/cmds/incidentd/tests/FdBuffer_test.cpp b/cmds/incidentd/tests/FdBuffer_test.cpp
index 3fd2ed8..956c8d3 100644
--- a/cmds/incidentd/tests/FdBuffer_test.cpp
+++ b/cmds/incidentd/tests/FdBuffer_test.cpp
@@ -11,11 +11,10 @@
// 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 "incidentd"
+#include "Log.h"
#include "FdBuffer.h"
-#include "io_util.h"
+#include "incidentd_util.h"
#include <android-base/file.h>
#include <android-base/test_utils.h>
@@ -48,7 +47,7 @@
}
void AssertBufferContent(const char* expected) {
- int i=0;
+ int i = 0;
EncodedBuffer::iterator it = buffer.data();
while (it.hasNext()) {
ASSERT_EQ(it.next(), expected[i++]);
@@ -100,7 +99,7 @@
ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
- int i=0;
+ int i = 0;
EncodedBuffer::iterator it = buffer.data();
while (it.hasNext()) {
EXPECT_EQ(it.next(), (uint8_t)testdata[i++]);
@@ -118,7 +117,7 @@
if (pid == 0) {
close(c2pPipe.readFd());
- while(true) {
+ while (true) {
write(c2pPipe.writeFd(), "poo", 3);
sleep(1);
}
@@ -130,7 +129,7 @@
ASSERT_EQ(NO_ERROR, status);
EXPECT_TRUE(buffer.timedOut());
- kill(pid, SIGKILL); // reap the child process
+ kill(pid, SIGKILL); // reap the child process
}
}
@@ -155,8 +154,8 @@
close(p2cPipe.readFd());
close(c2pPipe.writeFd());
- ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
- p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+ ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+ c2pPipe.readFd(), READ_TIMEOUT));
AssertBufferReadSuccessful(HEAD.size() + testdata.size());
AssertBufferContent(expected.c_str());
wait(&pid);
@@ -187,8 +186,8 @@
close(p2cPipe.readFd());
close(c2pPipe.writeFd());
- ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
- p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+ ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+ c2pPipe.readFd(), READ_TIMEOUT));
AssertBufferReadSuccessful(HEAD.size() + testdata.size());
AssertBufferContent(expected.c_str());
wait(&pid);
@@ -212,8 +211,8 @@
close(p2cPipe.readFd());
close(c2pPipe.writeFd());
- ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
- p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+ ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+ c2pPipe.readFd(), READ_TIMEOUT));
AssertBufferReadSuccessful(0);
AssertBufferContent("");
wait(&pid);
@@ -222,7 +221,7 @@
TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
const std::string testFile = kTestDataPath + "morethan4MB.txt";
- size_t fourMB = (size_t) 4 * 1024 * 1024;
+ size_t fourMB = (size_t)4 * 1024 * 1024;
int fd = open(testFile.c_str(), O_RDONLY | O_CLOEXEC);
ASSERT_NE(fd, -1);
int pid = fork();
@@ -239,8 +238,8 @@
close(p2cPipe.readFd());
close(c2pPipe.writeFd());
- ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd,
- p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+ ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(),
+ c2pPipe.readFd(), READ_TIMEOUT));
EXPECT_EQ(buffer.size(), fourMB);
EXPECT_FALSE(buffer.timedOut());
EXPECT_TRUE(buffer.truncated());
@@ -276,9 +275,9 @@
close(p2cPipe.readFd());
close(c2pPipe.writeFd());
- ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
- p2cPipe.writeFd(), c2pPipe.readFd(), QUICK_TIMEOUT_MS));
+ ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+ c2pPipe.readFd(), QUICK_TIMEOUT_MS));
EXPECT_TRUE(buffer.timedOut());
- kill(pid, SIGKILL); // reap the child process
+ kill(pid, SIGKILL); // reap the child process
}
}
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index c7bfe55..7ea9bbf 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -11,8 +11,7 @@
// 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 "incidentd"
+#include "Log.h"
#include "FdBuffer.h"
#include "PrivacyBuffer.h"
@@ -37,13 +36,12 @@
const uint8_t STRING_TYPE = 9;
const uint8_t MESSAGE_TYPE = 11;
const string STRING_FIELD_0 = "\x02\viamtestdata";
-const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
+const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
const string STRING_FIELD_2 = "\x12\vwhatthefuck";
-const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
-const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff"; // -1
+const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
+const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff"; // -1
const string MESSAGE_FIELD_5 = "\x2a\x10" + VARINT_FIELD_1 + STRING_FIELD_2;
-
class PrivacyBufferTest : public Test {
public:
virtual ~PrivacyBufferTest() {
@@ -55,9 +53,7 @@
}
}
- virtual void SetUp() override {
- ASSERT_NE(tf.fd, -1);
- }
+ virtual void SetUp() override { ASSERT_NE(tf.fd, -1); }
void writeToFdBuffer(string str) {
ASSERT_TRUE(WriteStringToFile(str, tf.path));
@@ -81,11 +77,11 @@
}
void assertStripByFields(uint8_t dest, string expected, int size, Privacy* privacy, ...) {
- Privacy* list[size+1];
+ Privacy* list[size + 1];
list[0] = privacy;
va_list args;
va_start(args, privacy);
- for (int i=1; i<size; i++) {
+ for (int i = 1; i < size; i++) {
Privacy* p = va_arg(args, Privacy*);
list[i] = p;
}
@@ -115,13 +111,14 @@
}
FdBuffer buffer;
+
private:
TemporaryFile tf;
// Littering this code with unique_ptr (or similar) is ugly, so we just
// mass-free everything after the test completes.
- std::vector<Privacy *> privacies;
+ std::vector<Privacy*> privacies;
- Privacy *new_uninit_privacy() {
+ Privacy* new_uninit_privacy() {
Privacy* p = new Privacy;
privacies.push_back(p);
return p;
@@ -165,63 +162,69 @@
TEST_F(PrivacyBufferTest, NoStripVarintField) {
writeToFdBuffer(VARINT_FIELD_1);
- assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1, create_privacy(1, OTHER_TYPE, DEST_AUTOMATIC));
+ assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1,
+ create_privacy(1, OTHER_TYPE, DEST_AUTOMATIC));
}
TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_String) {
writeToFdBuffer(STRING_FIELD_2);
- assertStripByFields(DEST_EXPLICIT, STRING_FIELD_2, 1, create_privacy(2, STRING_TYPE, DEST_AUTOMATIC));
+ assertStripByFields(DEST_EXPLICIT, STRING_FIELD_2, 1,
+ create_privacy(2, STRING_TYPE, DEST_AUTOMATIC));
}
TEST_F(PrivacyBufferTest, NoStripFixed64Field) {
writeToFdBuffer(FIX64_FIELD_3);
- assertStripByFields(DEST_EXPLICIT, FIX64_FIELD_3, 1, create_privacy(3, OTHER_TYPE, DEST_AUTOMATIC));
+ assertStripByFields(DEST_EXPLICIT, FIX64_FIELD_3, 1,
+ create_privacy(3, OTHER_TYPE, DEST_AUTOMATIC));
}
TEST_F(PrivacyBufferTest, NoStripFixed32Field) {
writeToFdBuffer(FIX32_FIELD_4);
- assertStripByFields(DEST_EXPLICIT, FIX32_FIELD_4, 1, create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC));
+ assertStripByFields(DEST_EXPLICIT, FIX32_FIELD_4, 1,
+ create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC));
}
TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_Message) {
writeToFdBuffer(MESSAGE_FIELD_5);
- assertStripByFields(DEST_EXPLICIT, MESSAGE_FIELD_5, 1, create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
+ assertStripByFields(DEST_EXPLICIT, MESSAGE_FIELD_5, 1,
+ create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
}
TEST_F(PrivacyBufferTest, StripVarintAndString) {
- writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
- + FIX64_FIELD_3 + FIX32_FIELD_4);
+ writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3 +
+ FIX32_FIELD_4);
string expected = STRING_FIELD_0 + FIX64_FIELD_3 + FIX32_FIELD_4;
- assertStripByFields(DEST_EXPLICIT, expected, 2,
- create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(2, STRING_TYPE, DEST_LOCAL));
+ assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(1, OTHER_TYPE, DEST_LOCAL),
+ create_privacy(2, STRING_TYPE, DEST_LOCAL));
}
TEST_F(PrivacyBufferTest, StripVarintAndFixed64) {
- writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
- + FIX64_FIELD_3 + FIX32_FIELD_4);
+ writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3 +
+ FIX32_FIELD_4);
string expected = STRING_FIELD_0 + STRING_FIELD_2 + FIX32_FIELD_4;
- assertStripByFields(DEST_EXPLICIT, expected, 2,
- create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(3, OTHER_TYPE, DEST_LOCAL));
+ assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(1, OTHER_TYPE, DEST_LOCAL),
+ create_privacy(3, OTHER_TYPE, DEST_LOCAL));
}
TEST_F(PrivacyBufferTest, StripVarintInNestedMessage) {
writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5);
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
assertStripByFields(DEST_EXPLICIT, expected, 1, create_message_privacy(5, list));
}
TEST_F(PrivacyBufferTest, StripFix64AndVarintInNestedMessage) {
writeToFdBuffer(STRING_FIELD_0 + FIX64_FIELD_3 + MESSAGE_FIELD_5);
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
- assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, DEST_LOCAL), create_message_privacy(5, list));
+ assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, DEST_LOCAL),
+ create_message_privacy(5, list));
}
TEST_F(PrivacyBufferTest, ClearAndStrip) {
string data = STRING_FIELD_0 + VARINT_FIELD_1;
writeToFdBuffer(data);
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
EncodedBuffer::iterator bufData = buffer.data();
PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
PrivacySpec spec1 = PrivacySpec::new_spec(DEST_EXPLICIT);
@@ -235,7 +238,7 @@
TEST_F(PrivacyBufferTest, BadDataInFdBuffer) {
writeToFdBuffer("iambaddata");
- Privacy* list[] = { create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC), NULL };
+ Privacy* list[] = {create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC), NULL};
EncodedBuffer::iterator bufData = buffer.data();
PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
PrivacySpec spec;
@@ -244,8 +247,8 @@
TEST_F(PrivacyBufferTest, BadDataInNestedMessage) {
writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5 + "aoeoe");
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
- Privacy* field5[] = { create_message_privacy(5, list), NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
+ Privacy* field5[] = {create_message_privacy(5, list), NULL};
EncodedBuffer::iterator bufData = buffer.data();
PrivacyBuffer privacyBuf(create_message_privacy(300, field5), bufData);
PrivacySpec spec;
@@ -256,7 +259,7 @@
string input = "\x2a\"" + VARINT_FIELD_1 + STRING_FIELD_2 + MESSAGE_FIELD_5;
writeToFdBuffer(input);
Privacy* field5 = create_message_privacy(5, NULL);
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), field5, NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), field5, NULL};
field5->children = list;
string expected = "\x2a\x1c" + STRING_FIELD_2 + "\x2a\xd" + STRING_FIELD_2;
assertStrip(DEST_EXPLICIT, expected, field5);
@@ -264,7 +267,7 @@
TEST_F(PrivacyBufferTest, AutoMessage) {
writeToFdBuffer(STRING_FIELD_2 + MESSAGE_FIELD_5);
- Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+ Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
Privacy* autoMsg = create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC);
autoMsg->children = list;
string expected = "\x2a\xd" + STRING_FIELD_2;
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index a1e3c34..bd359ac 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -11,8 +11,7 @@
// 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 "incidentd"
+#include "Log.h"
#include "Reporter.h"
@@ -26,7 +25,6 @@
#include <gtest/gtest.h>
#include <string.h>
-
using namespace android;
using namespace android::base;
using namespace android::binder;
@@ -35,8 +33,7 @@
using ::testing::StrEq;
using ::testing::Test;
-class TestListener : public IIncidentReportStatusListener
-{
+class TestListener : public IIncidentReportStatusListener {
public:
int startInvoked;
int finishInvoked;
@@ -44,8 +41,8 @@
map<int, int> startSections;
map<int, int> finishSections;
- TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0) {};
- virtual ~TestListener() {};
+ TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0){};
+ virtual ~TestListener(){};
virtual Status onReportStarted() {
startInvoked++;
@@ -53,16 +50,14 @@
};
virtual Status onReportSectionStatus(int section, int status) {
switch (status) {
- case IIncidentReportStatusListener::STATUS_STARTING:
- if (startSections.count(section) == 0)
- startSections[section] = 0;
- startSections[section] = startSections[section] + 1;
- break;
- case IIncidentReportStatusListener::STATUS_FINISHED:
- if (finishSections.count(section) == 0)
- finishSections[section] = 0;
- finishSections[section] = finishSections[section] + 1;
- break;
+ case IIncidentReportStatusListener::STATUS_STARTING:
+ if (startSections.count(section) == 0) startSections[section] = 0;
+ startSections[section] = startSections[section] + 1;
+ break;
+ case IIncidentReportStatusListener::STATUS_FINISHED:
+ if (finishSections.count(section) == 0) finishSections[section] = 0;
+ finishSections[section] = finishSections[section] + 1;
+ break;
}
return Status::ok();
};
@@ -156,7 +151,8 @@
string result;
ReadFileToString(tf.path, &result);
- EXPECT_THAT(result, StrEq("\n\x2" "\b\f"));
+ EXPECT_THAT(result, StrEq("\n\x2"
+ "\b\f"));
EXPECT_EQ(l->startInvoked, 2);
EXPECT_EQ(l->finishInvoked, 2);
@@ -178,7 +174,11 @@
ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
vector<string> results = InspectFiles();
ASSERT_EQ((int)results.size(), 1);
- EXPECT_EQ(results[0], "\n\x2" "\b\f\n\x6" "\x12\x4" "abcd");
+ EXPECT_EQ(results[0],
+ "\n\x2"
+ "\b\f\n\x6"
+ "\x12\x4"
+ "abcd");
}
TEST_F(ReporterTest, ReportMetadata) {
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 5752a67..a1f4fdc 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -11,8 +11,7 @@
// 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 "incidentd"
+#include "Log.h"
#include "Section.h"
@@ -30,9 +29,9 @@
const int QUICK_TIMEOUT_MS = 100;
-const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
+const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
const string STRING_FIELD_2 = "\x12\vwhatthefuck";
-const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
+const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
using namespace android::base;
using namespace android::binder;
@@ -44,11 +43,10 @@
// NOTICE: this test requires /system/bin/incident_helper is installed.
-class SimpleListener : public IIncidentReportStatusListener
-{
+class SimpleListener : public IIncidentReportStatusListener {
public:
- SimpleListener() {};
- virtual ~SimpleListener() {};
+ SimpleListener(){};
+ virtual ~SimpleListener(){};
virtual Status onReportStarted() { return Status::ok(); };
virtual Status onReportSectionStatus(int /*section*/, int /*status*/) { return Status::ok(); };
@@ -84,7 +82,9 @@
string content;
CaptureStdout();
ASSERT_EQ(NO_ERROR, hs.Execute(&requests));
- EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5" "\x12\x3" "axe\n\x05\x12\x03pup"));
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5"
+ "\x12\x3"
+ "axe\n\x05\x12\x03pup"));
EXPECT_TRUE(ReadFileToString(output2.path, &content));
EXPECT_THAT(content, StrEq("\n\x05\x12\x03pup"));
@@ -271,12 +271,12 @@
string content, expect;
expect = VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3;
- char c = (char) expect.size();
+ char c = (char)expect.size();
EXPECT_TRUE(ReadFileToString(output1.path, &content));
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
expect = STRING_FIELD_2 + FIX64_FIELD_3;
- c = (char) expect.size();
+ c = (char)expect.size();
EXPECT_TRUE(ReadFileToString(output2.path, &content));
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
@@ -315,7 +315,7 @@
string content, expect;
expect = STRING_FIELD_2 + FIX64_FIELD_3;
- char c = (char) expect.size();
+ char c = (char)expect.size();
// output1 and output2 are the same
EXPECT_TRUE(ReadFileToString(output1.path, &content));
@@ -324,7 +324,7 @@
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
// output3 has only auto field
- c = (char) STRING_FIELD_2.size();
+ c = (char)STRING_FIELD_2.size();
EXPECT_TRUE(ReadFileToString(output3.path, &content));
EXPECT_THAT(content, StrEq(string("\x02") + c + STRING_FIELD_2));
}
\ No newline at end of file
diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp
index 1d6213f..bd2d15c 100644
--- a/cmds/incidentd/tests/section_list.cpp
+++ b/cmds/incidentd/tests/section_list.cpp
@@ -1,25 +1,17 @@
// This file is a dummy section_list.cpp used for test only.
#include "section_list.h"
-const Section* SECTION_LIST[] = {
- NULL
-};
+const Section* SECTION_LIST[] = {NULL};
-Privacy sub_field_1 { 1, 1, NULL, DEST_LOCAL, NULL };
-Privacy sub_field_2 { 2, 9, NULL, DEST_AUTOMATIC, NULL };
+Privacy sub_field_1{1, 1, NULL, DEST_LOCAL, NULL};
+Privacy sub_field_2{2, 9, NULL, DEST_AUTOMATIC, NULL};
-Privacy* list[] = {
- &sub_field_1,
- &sub_field_2,
- NULL };
+Privacy* list[] = {&sub_field_1, &sub_field_2, NULL};
-Privacy field_0 { 0, 11, list, DEST_EXPLICIT, NULL };
-Privacy field_1 { 1, 9, NULL, DEST_AUTOMATIC, NULL };
+Privacy field_0{0, 11, list, DEST_EXPLICIT, NULL};
+Privacy field_1{1, 9, NULL, DEST_AUTOMATIC, NULL};
-Privacy* final_list[] = {
- &field_0,
- &field_1
-};
+Privacy* final_list[] = {&field_0, &field_1};
const Privacy** PRIVACY_POLICY_LIST = const_cast<const Privacy**>(final_list);
diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS
new file mode 100644
index 0000000..d6bb71b
--- /dev/null
+++ b/core/java/android/annotation/OWNERS
@@ -0,0 +1 @@
+tnorbye@google.com
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6c3d248..8a9efe8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,7 @@
package android.app;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+
import static java.lang.Character.MIN_VALUE;
import android.annotation.CallSuper;
@@ -135,6 +136,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1898,7 +1900,7 @@
if (isFinishing()) {
if (mAutoFillResetNeeded) {
- getAutofillManager().onActivityFinished();
+ getAutofillManager().onActivityFinishing();
} else if (mIntent != null
&& mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
// Activity was launched when user tapped a link in the Autofill Save UI - since
@@ -7689,6 +7691,9 @@
}
}
}
+ if (android.view.autofill.Helper.sVerbose) {
+ Log.v(TAG, "autofillClientGetViewVisibility(): " + Arrays.toString(visible));
+ }
return visible;
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4c9fb74..1026550 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -543,7 +543,6 @@
OP_CAMERA,
// Body sensors
OP_BODY_SENSORS,
- OP_REQUEST_DELETE_PACKAGES,
// APPOP PERMISSIONS
OP_ACCESS_NOTIFICATIONS,
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index a788989..b072ee6 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1000,7 +1000,7 @@
*/
@Override
public boolean isAutofillCompatibilityEnabled() {
- return mBase.isAutofillCompatibilityEnabled();
+ return mBase != null && mBase.isAutofillCompatibilityEnabled();
}
/**
@@ -1008,6 +1008,8 @@
*/
@Override
public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
- mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+ if (mBase != null) {
+ mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+ }
}
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index cf01451..424fa83 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,9 +27,11 @@
import android.annotation.StyleableRes;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
+import android.content.res.AssetManager.AssetInputStream;
import android.content.res.Configuration.NativeConfig;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
+import android.graphics.ImageDecoder;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -752,6 +754,26 @@
}
/**
+ * Loads a Drawable from an encoded image stream, or null.
+ *
+ * This call will handle closing ais.
+ */
+ private Drawable decodeImageDrawable(@NonNull AssetInputStream ais,
+ @NonNull Resources wrapper, @NonNull TypedValue value) {
+ ImageDecoder.Source src = new ImageDecoder.AssetInputStreamSource(ais,
+ wrapper, value);
+ try {
+ return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
+ } catch (IOException ioe) {
+ // This is okay. This may be something that ImageDecoder does not
+ // support, like SVG.
+ return null;
+ }
+ }
+
+ /**
* Loads a drawable from XML or resources stream.
*/
@NonNull
@@ -811,8 +833,8 @@
} else {
final InputStream is = mAssets.openNonAsset(
value.assetCookie, file, AssetManager.ACCESS_STREAMING);
- dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
- is.close();
+ AssetInputStream ais = (AssetInputStream) is;
+ dr = decodeImageDrawable(ais, wrapper, value);
}
} finally {
stack.pop();
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 931b5c9..f08e1cc 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -242,6 +242,9 @@
/**
* Returns the number of physical cameras available on this device.
+ * The return value of this method might change dynamically if the device
+ * supports external cameras and an external camera is connected or
+ * disconnected.
*
* @return total number of accessible camera devices, or 0 if there are no
* cameras or an error was encountered enumerating them.
@@ -3542,8 +3545,8 @@
/**
* Gets the horizontal angle of view in degrees.
*
- * @return horizontal angle of view. This method will always return a
- * valid value.
+ * @return horizontal angle of view. Returns -1.0 when the device
+ * doesn't report view angle information.
*/
public float getHorizontalViewAngle() {
return Float.parseFloat(get(KEY_HORIZONTAL_VIEW_ANGLE));
@@ -3552,8 +3555,8 @@
/**
* Gets the vertical angle of view in degrees.
*
- * @return vertical angle of view. This method will always return a
- * valid value.
+ * @return vertical angle of view. Returns -1.0 when the device
+ * doesn't report view angle information.
*/
public float getVerticalViewAngle() {
return Float.parseFloat(get(KEY_VERTICAL_VIEW_ANGLE));
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 732f6a5..e558b7e 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -829,19 +829,24 @@
* <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
* </ul>
* </li>
+ * <li>The SENSOR_INFO_TIMESTAMP_SOURCE of the logical device and physical devices must be
+ * the same.</li>
* <li>The logical camera device must be LIMITED or higher device.</li>
* </ul>
* <p>Both the logical camera device and its underlying physical devices support the
* mandatory stream combinations required for their device levels.</p>
* <p>Additionally, for each guaranteed stream combination, the logical camera supports:</p>
* <ul>
- * <li>Replacing one logical {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}
+ * <li>For each guaranteed stream combination, the logical camera supports replacing one
+ * logical {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}
* or raw stream with two physical streams of the same size and format, each from a
* separate physical camera, given that the size and format are supported by both
* physical cameras.</li>
- * <li>Adding two raw streams, each from one physical camera, if the logical camera doesn't
- * advertise RAW capability, but the underlying physical cameras do. This is usually
- * the case when the physical cameras have different sensor sizes.</li>
+ * <li>If the logical camera doesn't advertise RAW capability, but the underlying physical
+ * cameras do, the logical camera will support guaranteed stream combinations for RAW
+ * capability, except that the RAW streams will be physical streams, each from a separate
+ * physical camera. This is usually the case when the physical cameras have different
+ * sensor sizes.</li>
* </ul>
* <p>Using physical streams in place of a logical stream of the same size and format will
* not slow down the frame rate of the capture, as long as the minimum frame duration
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index b205e2c..a040a09 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -82,11 +82,9 @@
*
* </ul>
*
- * <p>Please note that surface sharing is currently only enabled for outputs that use the
- * {@link ImageFormat#PRIVATE} format. This includes surface sources like
- * {@link android.view.SurfaceView}, {@link android.media.MediaRecorder},
- * {@link android.graphics.SurfaceTexture} and {@link android.media.ImageReader}, configured using
- * the aforementioned format.</p>
+ * <p> As of {@link android.os.Build.VERSION_CODES#P Android P}, all formats can be used for
+ * sharing, subject to device support. On prior API levels, only {@link ImageFormat#PRIVATE}
+ * format may be used.</p>
*
* @see CameraDevice#createCaptureSessionByOutputConfigurations
*
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7dde2ed..91c99be 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2662,7 +2662,7 @@
* A {@code NetworkCallback} is registered by calling
* {@link #requestNetwork(NetworkRequest, NetworkCallback)},
* {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)},
- * or {@link #registerDefaultNetworkCallback(NetworkCallback). A {@code NetworkCallback} is
+ * or {@link #registerDefaultNetworkCallback(NetworkCallback)}. A {@code NetworkCallback} is
* unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
* A {@code NetworkCallback} should be registered at most once at any time.
* A {@code NetworkCallback} that has been unregistered can be registered again.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 05ab486..c53d005 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3692,18 +3692,15 @@
new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
/**
- * User-selected RTT mode
+ * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
+ * calls when supported by the device and carrier. Boolean value.
* 0 = OFF
- * 1 = FULL
- * 2 = VCO
- * 3 = HCO
- * Uses the same constants as TTY (e.g. {@link android.telecom.TelecomManager#TTY_MODE_OFF})
- * @hide
+ * 1 = ON
*/
public static final String RTT_CALLING_MODE = "rtt_calling_mode";
/** @hide */
- public static final Validator RTT_CALLING_MODE_VALIDATOR = TTY_MODE_VALIDATOR;
+ public static final Validator RTT_CALLING_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
* Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 1d13335..f4dcce1 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -75,6 +75,7 @@
public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
+ public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
@@ -216,6 +217,7 @@
public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
+ public static final int KM_ERROR_DEVICE_LOCKED = -72;
public static final int KM_ERROR_UNIMPLEMENTED = -100;
public static final int KM_ERROR_VERSION_MISMATCH = -101;
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -262,6 +264,7 @@
sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
"Invalid MAC or authentication tag length");
sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
+ sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
}
diff --git a/core/java/android/text/OWNERS b/core/java/android/text/OWNERS
index 9f2182e..e561371 100644
--- a/core/java/android/text/OWNERS
+++ b/core/java/android/text/OWNERS
@@ -1,3 +1,5 @@
+set noparent
+
siyamed@google.com
nona@google.com
clarabayarri@google.com
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 3fd4696..8cb46b7 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -23,6 +23,10 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -396,6 +400,33 @@
return true;
}
+ /**
+ * Get the Bitmap from the Drawable.
+ *
+ * If the Bitmap needed to be scaled up to account for density, BitmapDrawable
+ * handles this at draw time. But this class doesn't actually draw the Bitmap;
+ * it is just a holder for native code to access its SkBitmap. So this needs to
+ * get a version that is scaled to account for density.
+ */
+ private Bitmap getBitmapFromDrawable(BitmapDrawable bitmapDrawable) {
+ Bitmap bitmap = bitmapDrawable.getBitmap();
+ final int scaledWidth = bitmapDrawable.getIntrinsicWidth();
+ final int scaledHeight = bitmapDrawable.getIntrinsicHeight();
+ if (scaledWidth == bitmap.getWidth() && scaledHeight == bitmap.getHeight()) {
+ return bitmap;
+ }
+
+ Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ RectF dst = new RectF(0, 0, scaledWidth, scaledHeight);
+
+ Bitmap scaled = Bitmap.createBitmap(scaledWidth, scaledHeight, bitmap.getConfig());
+ Canvas canvas = new Canvas(scaled);
+ Paint paint = new Paint();
+ paint.setFilterBitmap(true);
+ canvas.drawBitmap(bitmap, src, dst, paint);
+ return scaled;
+ }
+
private void loadResource(Context context, Resources resources, @XmlRes int resourceId) {
final XmlResourceParser parser = resources.getXml(resourceId);
final int bitmapRes;
@@ -452,7 +483,8 @@
+ "is different. All frames should have the exact same size and "
+ "share the same hotspot.");
}
- mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap();
+ BitmapDrawable bitmapDrawableFrame = (BitmapDrawable) drawableFrame;
+ mBitmapFrames[i - 1] = getBitmapFromDrawable(bitmapDrawableFrame);
}
}
}
@@ -461,7 +493,8 @@
+ "refer to a bitmap drawable.");
}
- final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+ final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable);
validateHotSpot(bitmap, hotSpotX, hotSpotY);
// Set the properties now that we have successfully loaded the icon.
mBitmap = bitmap;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2af2467..3ff3c97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7272,7 +7272,7 @@
// becomes true where it should issue notifyViewEntered().
afm.notifyViewEntered(this);
}
- } else if (!isFocused()) {
+ } else if (!enter && !isFocused()) {
afm.notifyViewExited(this);
}
}
@@ -8010,6 +8010,9 @@
* <li>Call {@link
* android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
* when the visibility of a virtual child changed.
+ * <li>Call
+ * {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
+ * child is clicked.
* <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
* changed and the current context should be committed (for example, when the user tapped
* a {@code SUBMIT} button in an HTML page).
@@ -8807,6 +8810,9 @@
/**
* Computes whether this virtual autofill view is visible to the user.
*
+ * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
+ * view must override it.
+ *
* @return Whether the view is visible on the screen.
*/
public boolean isVisibleToUserForAutofill(int virtualId) {
@@ -8819,7 +8825,7 @@
}
}
}
- return false;
+ return true;
}
/**
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 5ce2421..cb1d89c 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -38,6 +38,7 @@
}
/** @hide */
+ @TestApi
public AutofillId(AutofillId parent, int virtualChildId) {
mVirtual = true;
mViewId = parent.mViewId;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index cf81b97..134dc1f 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -71,10 +71,9 @@
import java.util.List;
import java.util.Objects;
+//TODO: use java.lang.ref.Cleaner once Android supports Java 9
import sun.misc.Cleaner;
-// TODO: use java.lang.ref.Cleaner once Android supports Java 9
-
/**
* The {@link AutofillManager} provides ways for apps and custom views to integrate with the
* Autofill Framework lifecycle.
@@ -1065,16 +1064,34 @@
}
/**
- * Called when a {@link View} is clicked. Currently only used by views that should trigger save.
+ * Called to indicate a {@link View} is clicked.
*
- * @hide
+ * @param view view that has been clicked.
*/
- public void notifyViewClicked(View view) {
- final AutofillId id = view.getAutofillId();
+ public void notifyViewClicked(@NonNull View view) {
+ notifyViewClicked(view.getAutofillId());
+ }
+ /**
+ * Called to indicate a virtual view has been clicked.
+ *
+ * @param view the virtual view parent.
+ * @param virtualId id identifying the virtual child inside the parent view.
+ */
+ public void notifyViewClicked(@NonNull View view, int virtualId) {
+ notifyViewClicked(getAutofillId(view, virtualId));
+ }
+
+ private void notifyViewClicked(AutofillId id) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
if (sVerbose) Log.v(TAG, "notifyViewClicked(): id=" + id + ", trigger=" + mSaveTriggerId);
synchronized (mLock) {
+ if (!mEnabled || !isActiveLocked()) {
+ return;
+ }
if (mSaveTriggerId != null && mSaveTriggerId.equals(id)) {
if (sDebug) Log.d(TAG, "triggering commit by click of " + id);
commitLocked();
@@ -1089,16 +1106,16 @@
*
* @hide
*/
- public void onActivityFinished() {
+ public void onActivityFinishing() {
if (!hasAutofillFeature()) {
return;
}
synchronized (mLock) {
if (mSaveOnFinish) {
- if (sDebug) Log.d(TAG, "Committing session on finish() as requested by service");
+ if (sDebug) Log.d(TAG, "onActivityFinishing(): calling commitLocked()");
commitLocked();
} else {
- if (sDebug) Log.d(TAG, "Cancelling session on finish() as requested by service");
+ if (sDebug) Log.d(TAG, "onActivityFinishing(): calling cancelLocked()");
cancelLocked();
}
}
@@ -1119,6 +1136,7 @@
if (!hasAutofillFeature()) {
return;
}
+ if (sVerbose) Log.v(TAG, "commit() called by app");
synchronized (mLock) {
commitLocked();
}
@@ -2332,6 +2350,7 @@
final boolean[] isVisible;
if (client.autofillClientIsVisibleForAutofill()) {
+ if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
isVisible = client.autofillClientGetViewVisibility(trackedIds);
} else {
// All false
@@ -2351,7 +2370,7 @@
}
if (sVerbose) {
- Log.v(TAG, "TrackedViews(trackedIds=" + trackedIds + "): "
+ Log.v(TAG, "TrackedViews(trackedIds=" + Arrays.toString(trackedIds) + "): "
+ " mVisibleTrackedIds=" + mVisibleTrackedIds
+ " mInvisibleTrackedIds=" + mInvisibleTrackedIds);
}
@@ -2457,6 +2476,9 @@
}
if (mVisibleTrackedIds == null) {
+ if (sVerbose) {
+ Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
+ }
finishSessionLocked();
}
}
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 2789bae..e4b2930 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1,9 +1,11 @@
per-file TextView.java = siyamed@google.com
per-file TextView.java = nona@google.com
per-file TextView.java = clarabayarri@google.com
+
per-file EditText.java = siyamed@google.com
per-file EditText.java = nona@google.com
per-file EditText.java = clarabayarri@google.com
+
per-file Editor.java = siyamed@google.com
per-file Editor.java = nona@google.com
per-file Editor.java = clarabayarri@google.com
diff --git a/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java b/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
index 500c028..bf151c3 100644
--- a/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
+++ b/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
@@ -57,6 +57,8 @@
private int mMainColor;
private int mSecondaryColor;
private ValueAnimator mColorAnimation;
+ private int mMainColorTo;
+ private int mSecondaryColorTo;
public GradientDrawable(@NonNull Context context) {
mDensity = context.getResources().getDisplayMetrics().density;
@@ -76,7 +78,7 @@
}
public void setColors(int mainColor, int secondaryColor, boolean animated) {
- if (mainColor == mMainColor && secondaryColor == mSecondaryColor) {
+ if (mainColor == mMainColorTo && secondaryColor == mSecondaryColorTo) {
return;
}
@@ -84,6 +86,9 @@
mColorAnimation.cancel();
}
+ mMainColorTo = mainColor;
+ mSecondaryColorTo = mainColor;
+
if (animated) {
final int mainFrom = mMainColor;
final int secFrom = mSecondaryColor;
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index d6f8dc4..61d5031 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -604,6 +604,7 @@
CameraInfo cameraInfo;
status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
if (rc != NO_ERROR) {
+ ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
return rc;
}
int defaultOrientation = 0;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e994d37..0911298 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -999,7 +999,7 @@
<integer name="config_shortPressOnSleepBehavior">0</integer>
<!-- Time to wait while a button is pressed before triggering a very long press. -->
- <integer name="config_veryLongPressTimeout">6000</integer>
+ <integer name="config_veryLongPressTimeout">3500</integer>
<!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
<string name="widget_default_package_name" translatable="false"></string>
diff --git a/core/tests/coretests/src/android/text/OWNERS b/core/tests/coretests/src/android/text/OWNERS
index 9f2182e..a35c604 100644
--- a/core/tests/coretests/src/android/text/OWNERS
+++ b/core/tests/coretests/src/android/text/OWNERS
@@ -1,3 +1,5 @@
+set noparent
+
siyamed@google.com
nona@google.com
-clarabayarri@google.com
+clarabayarri@google.com
\ No newline at end of file
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index ee7abc5..3cca47b 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -25,7 +25,7 @@
import android.annotation.RawRes;
import android.content.ContentResolver;
import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
+import android.content.res.AssetManager.AssetInputStream;
import android.content.res.Resources;
import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.Drawable;
@@ -263,6 +263,63 @@
}
}
+ /**
+ * Takes ownership of the AssetInputStream.
+ *
+ * @hide
+ */
+ public static class AssetInputStreamSource extends Source {
+ public AssetInputStreamSource(@NonNull AssetInputStream ais,
+ @NonNull Resources res, @NonNull TypedValue value) {
+ mAssetInputStream = ais;
+ mResources = res;
+
+ if (value.density == TypedValue.DENSITY_DEFAULT) {
+ mDensity = DisplayMetrics.DENSITY_DEFAULT;
+ } else if (value.density != TypedValue.DENSITY_NONE) {
+ mDensity = value.density;
+ } else {
+ mDensity = Bitmap.DENSITY_NONE;
+ }
+ }
+
+ private AssetInputStream mAssetInputStream;
+ private final Resources mResources;
+ private final int mDensity;
+
+ @Override
+ public Resources getResources() { return mResources; }
+
+ @Override
+ public int getDensity() {
+ return mDensity;
+ }
+
+ @Override
+ public ImageDecoder createImageDecoder() throws IOException {
+ ImageDecoder decoder = null;
+ synchronized (this) {
+ if (mAssetInputStream == null) {
+ throw new IOException("Cannot reuse AssetInputStreamSource");
+ }
+ AssetInputStream ais = mAssetInputStream;
+ mAssetInputStream = null;
+ try {
+ long asset = ais.getNativeAsset();
+ decoder = nCreate(asset);
+ } finally {
+ if (decoder == null) {
+ IoUtils.closeQuietly(ais);
+ } else {
+ decoder.mInputStream = ais;
+ decoder.mOwnsInputStream = true;
+ }
+ }
+ return decoder;
+ }
+ }
+ }
+
private static class ResourceSource extends Source {
ResourceSource(@NonNull Resources res, int resId) {
mResources = res;
@@ -296,11 +353,7 @@
mResDensity = value.density;
}
- if (!(is instanceof AssetManager.AssetInputStream)) {
- // This should never happen.
- throw new RuntimeException("Resource is not an asset?");
- }
- long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
+ long asset = ((AssetInputStream) is).getNativeAsset();
decoder = nCreate(asset);
} finally {
if (decoder == null) {
@@ -444,6 +497,7 @@
private boolean mPreferRamOverQuality = false;
private boolean mAsAlphaMask = false;
private Rect mCropRect;
+ private Rect mOutPaddingRect;
private Source mSource;
private PostProcessor mPostProcessor;
@@ -782,6 +836,18 @@
}
/**
+ * Set a Rect for retrieving nine patch padding.
+ *
+ * If the image is a nine patch, this Rect will be set to the padding
+ * rectangle during decode. Otherwise it will not be modified.
+ *
+ * @hide
+ */
+ public void setOutPaddingRect(@NonNull Rect outPadding) {
+ mOutPaddingRect = outPadding;
+ }
+
+ /**
* Specify whether the {@link Bitmap} should be mutable.
*
* <p>By default, a {@link Bitmap} created will be immutable, but that can
@@ -892,7 +958,6 @@
postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
mMutable, mAllocator, mRequireUnpremultiplied,
mPreferRamOverQuality, mAsAlphaMask);
-
}
private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -965,7 +1030,10 @@
if (np != null && NinePatch.isNinePatchChunk(np)) {
Rect opticalInsets = new Rect();
bm.getOpticalInsets(opticalInsets);
- Rect padding = new Rect();
+ Rect padding = decoder.mOutPaddingRect;
+ if (padding == null) {
+ padding = new Rect();
+ }
nGetPadding(decoder.mNativePtr, padding);
return new NinePatchDrawable(res, bm, np, padding,
opticalInsets, null);
@@ -1008,6 +1076,15 @@
final int srcDensity = computeDensity(src, decoder);
Bitmap bm = decoder.decodeBitmap();
bm.setDensity(srcDensity);
+
+ Rect padding = decoder.mOutPaddingRect;
+ if (padding != null) {
+ byte[] np = bm.getNinePatchChunk();
+ if (np != null && NinePatch.isNinePatchChunk(np)) {
+ nGetPadding(decoder.mNativePtr, padding);
+ }
+ }
+
return bm;
}
}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 7ad062a..44b783b 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -27,6 +27,7 @@
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Outline;
@@ -49,6 +50,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -111,7 +113,7 @@
*/
@Deprecated
public BitmapDrawable() {
- mBitmapState = new BitmapState((Bitmap) null);
+ init(new BitmapState((Bitmap) null), null);
}
/**
@@ -124,8 +126,7 @@
@SuppressWarnings("unused")
@Deprecated
public BitmapDrawable(Resources res) {
- mBitmapState = new BitmapState((Bitmap) null);
- mBitmapState.mTargetDensity = mTargetDensity;
+ init(new BitmapState((Bitmap) null), res);
}
/**
@@ -135,7 +136,7 @@
*/
@Deprecated
public BitmapDrawable(Bitmap bitmap) {
- this(new BitmapState(bitmap), null);
+ init(new BitmapState(bitmap), null);
}
/**
@@ -143,8 +144,7 @@
* the display metrics of the resources.
*/
public BitmapDrawable(Resources res, Bitmap bitmap) {
- this(new BitmapState(bitmap), res);
- mBitmapState.mTargetDensity = mTargetDensity;
+ init(new BitmapState(bitmap), res);
}
/**
@@ -154,10 +154,7 @@
*/
@Deprecated
public BitmapDrawable(String filepath) {
- this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
- if (mBitmapState.mBitmap == null) {
- android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
- }
+ this(null, filepath);
}
/**
@@ -165,10 +162,21 @@
*/
@SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
public BitmapDrawable(Resources res, String filepath) {
- this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
- mBitmapState.mTargetDensity = mTargetDensity;
- if (mBitmapState.mBitmap == null) {
- android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+ Bitmap bitmap = null;
+ try (FileInputStream stream = new FileInputStream(filepath)) {
+ bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream),
+ (decoder, info, src) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
+ } catch (Exception e) {
+ /* do nothing. This matches the behavior of BitmapFactory.decodeFile()
+ If the exception happened on decode, mBitmapState.mBitmap will be null.
+ */
+ } finally {
+ init(new BitmapState(bitmap), res);
+ if (mBitmapState.mBitmap == null) {
+ android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+ }
}
}
@@ -179,10 +187,7 @@
*/
@Deprecated
public BitmapDrawable(java.io.InputStream is) {
- this(new BitmapState(BitmapFactory.decodeStream(is)), null);
- if (mBitmapState.mBitmap == null) {
- android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
- }
+ this(null, is);
}
/**
@@ -190,10 +195,21 @@
*/
@SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
public BitmapDrawable(Resources res, java.io.InputStream is) {
- this(new BitmapState(BitmapFactory.decodeStream(is)), null);
- mBitmapState.mTargetDensity = mTargetDensity;
- if (mBitmapState.mBitmap == null) {
- android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+ Bitmap bitmap = null;
+ try {
+ bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is),
+ (decoder, info, src) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
+ } catch (Exception e) {
+ /* do nothing. This matches the behavior of BitmapFactory.decodeStream()
+ If the exception happened on decode, mBitmapState.mBitmap will be null.
+ */
+ } finally {
+ init(new BitmapState(bitmap), res);
+ if (mBitmapState.mBitmap == null) {
+ android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+ }
}
}
@@ -812,9 +828,19 @@
}
}
+ int density = Bitmap.DENSITY_NONE;
+ if (value.density == TypedValue.DENSITY_DEFAULT) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ } else if (value.density != TypedValue.DENSITY_NONE) {
+ density = value.density;
+ }
+
Bitmap bitmap = null;
try (InputStream is = r.openRawResource(srcResId, value)) {
- bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
+ ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
+ bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
} catch (Exception e) {
// Do nothing and pick up the error below.
}
@@ -1013,14 +1039,21 @@
}
}
+ private BitmapDrawable(BitmapState state, Resources res) {
+ init(state, res);
+ }
+
/**
- * The one constructor to rule them all. This is called by all public
+ * The one helper to rule them all. This is called by all public & private
* constructors to set the state and initialize local properties.
*/
- private BitmapDrawable(BitmapState state, Resources res) {
+ private void init(BitmapState state, Resources res) {
mBitmapState = state;
-
updateLocalState(res);
+
+ if (mBitmapState != null && res != null) {
+ mBitmapState.mTargetDensity = mTargetDensity;
+ }
}
/**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 05533d7..8af2fd8 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,6 +37,7 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.NinePatch;
import android.graphics.Outline;
@@ -50,11 +51,13 @@
import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
import android.view.View;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
@@ -1179,6 +1182,10 @@
return null;
}
+ if (opts == null) {
+ return getBitmapDrawable(res, value, is);
+ }
+
/* ugh. The decodeStream contract is that we have already allocated
the pad rect, but if the bitmap does not had a ninepatch chunk,
then the pad will be ignored. If we could change this to lazily
@@ -1194,7 +1201,6 @@
// an application in compatibility mode, without scaling those down
// to the compatibility density only to have them scaled back up when
// drawn to the screen.
- if (opts == null) opts = new BitmapFactory.Options();
opts.inScreenDensity = Drawable.resolveDensity(res, 0);
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
if (bm != null) {
@@ -1211,6 +1217,33 @@
return null;
}
+ private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) {
+ try {
+ ImageDecoder.Source source = null;
+ if (value != null) {
+ int density = Bitmap.DENSITY_NONE;
+ if (value.density == TypedValue.DENSITY_DEFAULT) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ } else if (value.density != TypedValue.DENSITY_NONE) {
+ density = value.density;
+ }
+ source = ImageDecoder.createSource(res, is, density);
+ } else {
+ source = ImageDecoder.createSource(res, is);
+ }
+
+ return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
+ } catch (IOException e) {
+ /* do nothing.
+ If the exception happened on decode, the drawable will be null.
+ */
+ Log.e("Drawable", "Unable to decode stream: " + e);
+ }
+ return null;
+ }
+
/**
* Create a drawable from an XML document. For more information on how to
* create resources in XML, see
@@ -1310,11 +1343,10 @@
}
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
- try {
- Bitmap bm = BitmapFactory.decodeFile(pathName);
- if (bm != null) {
- return drawableFromBitmap(null, bm, null, null, null, pathName);
- }
+ try (FileInputStream stream = new FileInputStream(pathName)) {
+ return getBitmapDrawable(null, null, stream);
+ } catch(IOException e) {
+ // Do nothing; we will just return null if the FileInputStream had an error
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 1790020..66f2a31 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -24,9 +24,9 @@
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
import android.graphics.Insets;
import android.graphics.NinePatch;
import android.graphics.Outline;
@@ -211,7 +211,8 @@
restoreAlpha = -1;
}
- final boolean needsDensityScaling = canvas.getDensity() == 0;
+ final boolean needsDensityScaling = canvas.getDensity() == 0
+ && Bitmap.DENSITY_NONE != state.mNinePatch.getDensity();
if (needsDensityScaling) {
restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
@@ -421,10 +422,6 @@
final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0);
if (srcResId != 0) {
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inDither = !state.mDither;
- options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
-
final Rect padding = new Rect();
final Rect opticalInsets = new Rect();
Bitmap bitmap = null;
@@ -433,7 +430,17 @@
final TypedValue value = new TypedValue();
final InputStream is = r.openRawResource(srcResId, value);
- bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
+ int density = Bitmap.DENSITY_NONE;
+ if (value.density == TypedValue.DENSITY_DEFAULT) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ } else if (value.density != TypedValue.DENSITY_NONE) {
+ density = value.density;
+ }
+ ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
+ bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
+ decoder.setOutPaddingRect(padding);
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ });
is.close();
} catch (IOException e) {
@@ -660,8 +667,9 @@
return;
}
- final int sourceDensity = ninePatch.getDensity();
final int targetDensity = mTargetDensity;
+ final int sourceDensity = ninePatch.getDensity() == Bitmap.DENSITY_NONE ?
+ targetDensity : ninePatch.getDensity();
final Insets sourceOpticalInsets = mNinePatchState.mOpticalInsets;
if (sourceOpticalInsets != Insets.NONE) {
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index ded427e..e2aba04 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -545,7 +545,9 @@
try {
args = args != null ? args : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
- return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+ OperationResult res = mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+ // This result is -26 (KEY_USER_NOT_AUTHENTICATED) but why??
+ return res;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
@@ -563,7 +565,8 @@
try {
arguments = arguments != null ? arguments : new KeymasterArguments();
input = input != null ? input : new byte[0];
- return mBinder.update(token, arguments, input);
+ OperationResult res = mBinder.update(token, arguments, input);
+ return res;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
@@ -618,9 +621,9 @@
* @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
* a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
*/
- public int addAuthToken(byte[] authToken) {
+ public int addAuthToken(byte[] authToken, int userId) {
try {
- return mBinder.addAuthToken(authToken);
+ return mBinder.addAuthToken(authToken, userId);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
@@ -832,14 +835,14 @@
public InvalidKeyException getInvalidKeyException(
String keystoreKeyAlias, int uid, KeyStoreException e) {
switch (e.getErrorCode()) {
- case LOCKED:
+ case LOCKED: // 2
return new UserNotAuthenticatedException();
- case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
+ case KeymasterDefs.KM_ERROR_KEY_EXPIRED: // -25
return new KeyExpiredException();
- case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
+ case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: // -2
return new KeyNotYetValidException();
- case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
- case OP_AUTH_NEEDED:
+ case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: // -26
+ case OP_AUTH_NEEDED: // 15
{
// We now need to determine whether the key/operation can become usable if user
// authentication is performed, or whether it can never become usable again.
@@ -879,7 +882,7 @@
// None of the key's SIDs can ever be authenticated
return new KeyPermanentlyInvalidatedException();
}
- case UNINITIALIZED:
+ case UNINITIALIZED: // 3
return new KeyPermanentlyInvalidatedException();
default:
return new InvalidKeyException("Keystore operation failed", e);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 09b3b9b..419eb24 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -243,13 +243,7 @@
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
// not set up).
- KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- spec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -285,16 +279,7 @@
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
- KeymasterUtils.addUserAuthArgs(args,
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- spec.isUserConfirmationRequired());
- if (spec.isTrustedUserPresenceRequired()) {
- args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
- }
+ KeymasterUtils.addUserAuthArgs(args, spec);
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index e33e3cd..d68a33d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -344,13 +344,7 @@
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
// not set up).
- KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
- mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- mSpec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -541,13 +535,7 @@
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
- KeymasterUtils.addUserAuthArgs(args,
- mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
- mSpec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(args, mSpec);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 05cc74a..fc86ca0 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -497,13 +497,7 @@
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
- KeymasterUtils.addUserAuthArgs(importArgs,
- spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment(),
- spec.getBoundToSpecificSecureUserId(),
- spec.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(importArgs, spec);
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -700,13 +694,7 @@
int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
params.getEncryptionPaddings());
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
- KeymasterUtils.addUserAuthArgs(args,
- params.isUserAuthenticationRequired(),
- params.getUserAuthenticationValidityDurationSeconds(),
- params.isUserAuthenticationValidWhileOnBody(),
- params.isInvalidatedByBiometricEnrollment(),
- params.getBoundToSpecificSecureUserId(),
- params.isUserConfirmationRequired());
+ KeymasterUtils.addUserAuthArgs(args, params);
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index da23c70..d0814c6 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.security.GateKeeper;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -232,7 +233,7 @@
* key = (SecretKey) keyStore.getKey("key2", null);
* }</pre>
*/
-public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
+public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs {
private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake");
private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1");
@@ -265,6 +266,7 @@
private final boolean mInvalidatedByBiometricEnrollment;
private final boolean mIsStrongBoxBacked;
private final boolean mUserConfirmationRequired;
+ private final boolean mUnlockedDeviceRequired;
/**
* @hide should be built with Builder
@@ -295,7 +297,8 @@
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
boolean isStrongBoxBacked,
- boolean userConfirmationRequired) {
+ boolean userConfirmationRequired,
+ boolean unlockedDeviceRequired) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -344,6 +347,7 @@
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mIsStrongBoxBacked = isStrongBoxBacked;
mUserConfirmationRequired = userConfirmationRequired;
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
}
/**
@@ -669,6 +673,22 @@
}
/**
+ * Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+ *
+ * @see Builder#SetUnlockedDeviceRequired(boolean)
+ */
+ public boolean isUnlockedDeviceRequired() {
+ return mUnlockedDeviceRequired;
+ }
+
+ /**
+ * @hide
+ */
+ public long getBoundToSpecificSecureUserId() {
+ return GateKeeper.INVALID_SECURE_USER_ID;
+ }
+
+ /**
* Builder of {@link KeyGenParameterSpec} instances.
*/
public final static class Builder {
@@ -699,6 +719,7 @@
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mIsStrongBoxBacked = false;
private boolean mUserConfirmationRequired;
+ private boolean mUnlockedDeviceRequired = false;
/**
* Creates a new instance of the {@code Builder}.
@@ -1267,6 +1288,18 @@
}
/**
+ * Sets whether the keystore requires the screen to be unlocked before allowing decryption
+ * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+ * while the screen is locked will fail. A locked device requires a PIN, password,
+ * fingerprint, or other trusted factor to access.
+ */
+ @NonNull
+ public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
+ return this;
+ }
+
+ /**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@NonNull
@@ -1297,7 +1330,8 @@
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mIsStrongBoxBacked,
- mUserConfirmationRequired);
+ mUserConfirmationRequired,
+ mUnlockedDeviceRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index b5b3281..7f8259b 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -212,7 +212,7 @@
* ...
* }</pre>
*/
-public final class KeyProtection implements ProtectionParameter {
+public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
private final Date mKeyValidityStart;
private final Date mKeyValidityForOriginationEnd;
private final Date mKeyValidityForConsumptionEnd;
@@ -229,6 +229,8 @@
private final long mBoundToSecureUserId;
private final boolean mCriticalToDeviceEncryption;
private final boolean mUserConfirmationRequired;
+ private final boolean mTrustedUserPresenceRequired;
+ private final boolean mUnlockedDeviceRequired;
private KeyProtection(
Date keyValidityStart,
@@ -242,11 +244,13 @@
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
+ boolean trustedUserPresenceRequired,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
long boundToSecureUserId,
boolean criticalToDeviceEncryption,
- boolean userConfirmationRequired) {
+ boolean userConfirmationRequired,
+ boolean unlockedDeviceRequired) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -265,6 +269,8 @@
mBoundToSecureUserId = boundToSecureUserId;
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
mUserConfirmationRequired = userConfirmationRequired;
+ mTrustedUserPresenceRequired = trustedUserPresenceRequired;
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
}
/**
@@ -437,6 +443,14 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only if a test of user presence has
+ * been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
+ */
+ public boolean isTrustedUserPresenceRequired() {
+ return mTrustedUserPresenceRequired;
+ }
+
+ /**
* Returns {@code true} if the key will be de-authorized when the device is removed from the
* user's body. This option has no effect on keys that don't have an authentication validity
* duration, and has no effect if the device lacks an on-body sensor.
@@ -494,6 +508,15 @@
}
/**
+ * Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+ *
+ * @see Builder#SetRequireDeviceUnlocked(boolean)
+ */
+ public boolean isUnlockedDeviceRequired() {
+ return mUnlockedDeviceRequired;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -512,6 +535,9 @@
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mUserConfirmationRequired;
+ private boolean mTrustedUserPresenceRequired = false;
+ private boolean mUnlockedDeviceRequired = false;
+
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
@@ -811,6 +837,16 @@
}
/**
+ * Sets whether a test of user presence is required to be performed between the
+ * {@code Signature.initSign()} and {@code Signature.sign()} method calls.
+ */
+ @NonNull
+ public Builder setTrustedUserPresenceRequired(boolean required) {
+ mTrustedUserPresenceRequired = required;
+ return this;
+ }
+
+ /**
* Sets whether the key will remain authorized only until the device is removed from the
* user's body up to the limit of the authentication validity period (see
* {@link #setUserAuthenticationValidityDurationSeconds} and
@@ -892,6 +928,18 @@
}
/**
+ * Sets whether the keystore requires the screen to be unlocked before allowing decryption
+ * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+ * while the screen is locked will fail. A locked device requires a PIN, password,
+ * fingerprint, or other trusted factor to access.
+ */
+ @NonNull
+ public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -910,11 +958,13 @@
mRandomizedEncryptionRequired,
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds,
+ mTrustedUserPresenceRequired,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mBoundToSecureUserId,
mCriticalToDeviceEncryption,
- mUserConfirmationRequired);
+ mUserConfirmationRequired,
+ mUnlockedDeviceRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 4e28601..5bd0e74 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -18,6 +18,7 @@
import android.util.Log;
import android.hardware.fingerprint.FingerprintManager;
+import android.os.UserHandle;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeymasterArguments;
@@ -101,22 +102,27 @@
* require user authentication.
*/
public static void addUserAuthArgs(KeymasterArguments args,
- boolean userAuthenticationRequired,
- int userAuthenticationValidityDurationSeconds,
- boolean userAuthenticationValidWhileOnBody,
- boolean invalidatedByBiometricEnrollment,
- long boundToSpecificSecureUserId,
- boolean userConfirmationRequired) {
- if (userConfirmationRequired) {
+ UserAuthArgs spec) {
+ if (spec.isTrustedUserPresenceRequired()) {
+ args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+ }
+
+ if (spec.isUserConfirmationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
}
- if (!userAuthenticationRequired) {
+ if (spec.isUnlockedDeviceRequired()) {
+ args.addBoolean(KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED);
+ // Once keymaster is properly ignoring this tag, it should be added to every auth list
+ args.addUnsignedInt(KeymasterDefs.KM_TAG_USER_ID, UserHandle.getCallingUserId());
+ }
+
+ if (!spec.isUserAuthenticationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
}
- if (userAuthenticationValidityDurationSeconds == -1) {
+ if (spec.getUserAuthenticationValidityDurationSeconds() == -1) {
// Every use of this key needs to be authorized by the user. This currently means
// fingerprint-only auth.
FingerprintManager fingerprintManager =
@@ -132,9 +138,9 @@
}
long sid;
- if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
- sid = boundToSpecificSecureUserId;
- } else if (invalidatedByBiometricEnrollment) {
+ if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = spec.getBoundToSpecificSecureUserId();
+ } else if (spec.isInvalidatedByBiometricEnrollment()) {
// The fingerprint-only SID will change on fingerprint enrollment or removal of all,
// enrolled fingerprints, invalidating the key.
sid = fingerprintOnlySid;
@@ -147,14 +153,14 @@
args.addUnsignedLong(
KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
- if (userAuthenticationValidWhileOnBody) {
+ if (spec.isUserAuthenticationValidWhileOnBody()) {
throw new ProviderException("Key validity extension while device is on-body is not "
+ "supported for keys requiring fingerprint authentication");
}
} else {
long sid;
- if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
- sid = boundToSpecificSecureUserId;
+ if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = spec.getBoundToSpecificSecureUserId();
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
@@ -165,8 +171,8 @@
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
- userAuthenticationValidityDurationSeconds);
- if (userAuthenticationValidWhileOnBody) {
+ spec.getUserAuthenticationValidityDurationSeconds());
+ if (spec.isUserAuthenticationValidWhileOnBody()) {
args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
}
}
diff --git a/keystore/java/android/security/keystore/UserAuthArgs.java b/keystore/java/android/security/keystore/UserAuthArgs.java
new file mode 100644
index 0000000..3a7017e
--- /dev/null
+++ b/keystore/java/android/security/keystore/UserAuthArgs.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package android.security.keystore;
+
+/**
+ * @hide
+ *
+ * This is an interface to encapsulate the user authentication arguments that
+ * are passed to KeymasterUtils.addUserAuthArgs. Classes that represent
+ * authorization characteristics for new or imported keys can implement this
+ * interface to be passed to that method.
+ */
+public interface UserAuthArgs {
+
+ boolean isUserAuthenticationRequired();
+ int getUserAuthenticationValidityDurationSeconds();
+ boolean isUserAuthenticationValidWhileOnBody();
+ boolean isInvalidatedByBiometricEnrollment();
+ boolean isTrustedUserPresenceRequired();
+ boolean isUnlockedDeviceRequired();
+ boolean isUserConfirmationRequired();
+ long getBoundToSpecificSecureUserId();
+
+}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 823410f..9ad5cd9 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -17,6 +17,7 @@
package android.media;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.hardware.Camera;
@@ -278,6 +279,7 @@
* third-party applications.
* </p>
*/
+ @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)
public static final int REMOTE_SUBMIX = 8;
/** Microphone audio source tuned for unprocessed (raw) sound if available, behaves like
@@ -303,6 +305,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
public static final int HOTWORD = 1999;
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 2190635..343bbda 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -400,6 +400,7 @@
new AudioAttributes.Builder()
.setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
.addTag(addressForTag(mix))
+ .addTag(AudioRecord.SUBMIX_FIXED_VOLUME)
.build(),
mixFormat,
AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
diff --git a/telephony/java/android/telephony/OWNERS b/packages/CarrierDefaultApp/OWNERS
similarity index 92%
rename from telephony/java/android/telephony/OWNERS
rename to packages/CarrierDefaultApp/OWNERS
index 68dedce..7057ce6 100644
--- a/telephony/java/android/telephony/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -1,14 +1,12 @@
-set noparent
-
-amitmahajan@google.com
+tgunn@google.com
breadley@google.com
-fionaxu@google.com
-jackyu@google.com
hallliu@google.com
rgreenwalt@google.com
-tgunn@google.com
-jminjie@google.com
mpq@google.com
+amitmahajan@google.com
+fionaxu@google.com
+jackyu@google.com
+jminjie@google.com
+satk@google.com
shuoq@google.com
-refuhoo@google.com
-
+refuhoo@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..d7f9449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..7c65703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..eea819a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..504ceb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..8e7d8cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..456a68f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..fb854ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..75d184a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..9e0af28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..7c00bd5d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..81b4466
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..724aa9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..7ba0d1b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..a175ccb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..45ce1d4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..6da0c9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..71e8959
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..bb7ae26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..32b9ded
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..ed1949c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..d888869
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..dc3b25c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..d4e5a94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..0e693f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..0757799
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..4f07ec1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..ba5b457
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..a55ea1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..407ef28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..39cfbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..a7fd3a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..f2a1255
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..5a7eec6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..f7abb54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..a1f44dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..175a9ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..0fb93ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..1052940
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/res/values/arrays_tv.xml
index 7541b0e..9197bb5 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/packages/SystemUI/res/values/arrays_tv.xml
@@ -30,7 +30,7 @@
<item>com.google.android.apps.mediashell/.settings.CastSettingsActivity</item>
<item>com.google.android.katniss.setting/.SpeechSettingsActivity</item>
<item>com.google.android.katniss.setting/.SearchSettingsActivity</item>
- <item>com.google.android.gsf.notouch/.UsageDiagnosticsSettingActivity</item>
+ <item>com.google.android.tungsten.setupwraith/.settings.usage.UsageDiagnosticsSettingActivity</item>
<item>com.google.android.tvlauncher/.notifications.NotificationsSidePanelActivity</item>
</string-array>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 6205e9a..2d31669 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -240,6 +240,7 @@
public void handleSetListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
+ if (mController == null) return;
if (mListening) {
mController.addCallback(mZenCallback);
Prefs.registerListener(mContext, mPrefListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index b3ff4e5b..12daff1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -98,6 +98,8 @@
protected void handleUpdateState(BooleanState state, Object arg) {
final Drawable mEnable = mContext.getDrawable(R.drawable.ic_qs_nfc_enabled);
final Drawable mDisable = mContext.getDrawable(R.drawable.ic_qs_nfc_disabled);
+
+ if (getAdapter() == null) return;
state.value = getAdapter().isEnabled();
state.label = mContext.getString(R.string.quick_settings_nfc_label);
state.icon = new DrawableIcon(state.value ? mEnable : mDisable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index cd4eb23..c047670 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -403,14 +403,18 @@
}
private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
+ final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
if (oldConfig.orientation != newConfig.orientation
|| oldConfig.densityDpi != newConfig.densityDpi) {
mDockedIcon = getDrawable(ctx,
R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
+ mHomeDefaultIcon = quickStepEnabled
+ ? getDrawable(ctx, R.drawable.ic_sysbar_home_quick_step,
+ R.drawable.ic_sysbar_home_quick_step_dark)
+ : getDrawable(ctx, R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
}
if (oldConfig.densityDpi != newConfig.densityDpi
|| oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
- final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
mBackIcon = quickStepEnabled
? getDrawable(ctx, R.drawable.ic_sysbar_back_quick_step,
R.drawable.ic_sysbar_back_quick_step_dark)
@@ -422,11 +426,6 @@
: getDrawable(ctx, R.drawable.ic_sysbar_back_ime,
R.drawable.ic_sysbar_back_ime_dark);
mBackAltLandIcon = mBackAltIcon;
-
- mHomeDefaultIcon = quickStepEnabled
- ? getDrawable(ctx, R.drawable.ic_sysbar_home_quick_step,
- R.drawable.ic_sysbar_home_quick_step_dark)
- : getDrawable(ctx, R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
mRecentIcon = getDrawable(ctx,
R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
@@ -909,6 +908,11 @@
Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
}
+ // Resolve layout direction if not resolved since components changing layout direction such
+ // as changing languages will recreate this view and the direction will be resolved later
+ if (!isLayoutDirectionResolved()) {
+ resolveLayoutDirection();
+ }
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index 0bf01b0..378858a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -224,6 +224,10 @@
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
+ // End any existing quickscrub animations before starting the new transition
+ if (mQuickScrubEndAnimator != null) {
+ mQuickScrubEndAnimator.end();
+ }
mHomeButtonView = homeButton.getCurrentView();
if (mNavigationBarView.isQuickScrubEnabled()
&& mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 320c37f..abf1de5 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5257,6 +5257,23 @@
// OS: P
FIELD_END_BATTERY_PERCENT = 1308;
+ // ACTION: Settings > Display > Night Light
+ // SUBTYPE: com.android.server.display.ColorDisplayService.AutoMode value
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_NIGHT_DISPLAY_AUTO_MODE_CHANGED = 1309;
+
+ // ACTION: Settings > Display > Night Light
+ // CATEGORY: SETTINGS
+ // SUBTYPE: 0 is starting time, 1 is ending time
+ // OS: P
+ ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED = 1310;
+
+ // FIELD: Current mode corresponding to a QS tile
+ // CATEGORY: QUICK SETTINGS
+ // OS: P
+ FIELD_QS_MODE = 1311;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/rs/OWNERS b/rs/OWNERS
new file mode 100644
index 0000000..61853d3
--- /dev/null
+++ b/rs/OWNERS
@@ -0,0 +1,5 @@
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+miaowang@google.com
+yangni@google.com
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index c023efb..c504465 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -153,8 +153,8 @@
mWindow = null;
return;
}
- content.setFocusable(true);
- content.setOnClickListener(v -> mCallback.onResponsePicked(response));
+ decor.setFocusable(true);
+ decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
Point maxSize = mTempPoint;
resolveMaxWindowSize(context, maxSize);
diff --git a/services/core/java/com/android/server/audio/OWNERS b/services/core/java/com/android/server/audio/OWNERS
new file mode 100644
index 0000000..b70de29
--- /dev/null
+++ b/services/core/java/com/android/server/audio/OWNERS
@@ -0,0 +1,2 @@
+jmtrivi@google.com
+elaurent@google.com
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index d87a1bb..79450a0 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2078,8 +2078,33 @@
protected void dumpSyncState(PrintWriter pw) {
final StringBuilder sb = new StringBuilder();
- pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
- pw.print("auto sync: ");
+ pw.print("Data connected: "); pw.println(mDataConnectionIsConnected);
+ pw.print("Battery saver: ");
+ pw.println((mPowerManager != null) && mPowerManager.isPowerSaveMode());
+
+ pw.print("Background network restriction: ");
+ {
+ final ConnectivityManager cm = getConnectivityManager();
+ final int status = (cm == null) ? -1 : cm.getRestrictBackgroundStatus();
+ switch (status) {
+ case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED:
+ pw.println(" disabled");
+ break;
+ case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED:
+ pw.println(" whitelisted");
+ break;
+ case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED:
+ pw.println(" enabled");
+ break;
+ default:
+ pw.print("Unknown(");
+ pw.print(status);
+ pw.println(")");
+ break;
+ }
+ }
+
+ pw.print("Auto sync: ");
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
@@ -2088,26 +2113,26 @@
}
pw.println();
}
- pw.print("memory low: "); pw.println(mStorageIsLow);
- pw.print("device idle: "); pw.println(mDeviceIsIdle);
- pw.print("reported active: "); pw.println(mReportedSyncActive);
+ pw.print("Memory low: "); pw.println(mStorageIsLow);
+ pw.print("Device idle: "); pw.println(mDeviceIsIdle);
+ pw.print("Reported active: "); pw.println(mReportedSyncActive);
final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();
- pw.print("accounts: ");
+ pw.print("Accounts: ");
if (accounts != INITIAL_ACCOUNTS_ARRAY) {
pw.println(accounts.length);
} else {
pw.println("not known yet");
}
final long now = SystemClock.elapsedRealtime();
- pw.print("now: "); pw.print(now);
+ pw.print("Now: "); pw.print(now);
pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
sb.setLength(0);
- pw.print("uptime: "); pw.print(formatDurationHMS(sb, now));
+ pw.print("Uptime: "); pw.print(formatDurationHMS(sb, now));
pw.println();
- pw.print("time spent syncing: ");
+ pw.print("Time spent syncing: ");
sb.setLength(0);
pw.print(formatDurationHMS(sb,
diff --git a/services/core/java/com/android/server/content/SyncManagerConstants.java b/services/core/java/com/android/server/content/SyncManagerConstants.java
index 3139d54..061e4ca 100644
--- a/services/core/java/com/android/server/content/SyncManagerConstants.java
+++ b/services/core/java/com/android/server/content/SyncManagerConstants.java
@@ -55,7 +55,6 @@
protected SyncManagerConstants(Context context) {
super(null);
mContext = context;
- refresh();
}
public void start() {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 3da3551..692535c 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -421,7 +421,7 @@
byteToken[i] = token.get(i);
}
// Send to Keystore
- KeyStore.getInstance().addAuthToken(byteToken);
+ KeyStore.getInstance().addAuthToken(byteToken, mCurrentUserId);
}
if (client != null && client.onAuthenticated(fingerId, groupId)) {
removeClient(client);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
old mode 100644
new mode 100755
index e5f4282..0cba76b
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -660,7 +660,8 @@
@ServiceThreadOnly
void startQueuedActions() {
assertRunOnServiceThread();
- for (HdmiCecFeatureAction action : mActions) {
+ // Use copied action list in that start() may remove itself.
+ for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) {
if (!action.started()) {
Slog.i(TAG, "Starting queued action:" + action);
action.start();
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
new file mode 100644
index 0000000..6f8d823
--- /dev/null
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -0,0 +1,2 @@
+lajos@google.com
+elaurent@google.com
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 941cd44..efcadad 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -19,6 +19,8 @@
import android.app.ActivityManager;
import android.content.Context;
import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
@@ -51,11 +53,16 @@
private final LockPatternUtils mLockPatternUtils;
private final StateCallback mCallback;
+ IKeystoreService mKeystoreService;
+
public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
mLockPatternUtils = new LockPatternUtils(context);
mCurrentUserId = ActivityManager.getCurrentUser();
mCallback = callback;
+ mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
+ .getService("android.security.keystore"));
+
try {
service.addStateMonitorCallback(this);
} catch (RemoteException e) {
@@ -86,6 +93,12 @@
@Override // Binder interface
public void onShowingStateChanged(boolean showing) {
mIsShowing = showing;
+
+ if (showing) try {
+ mKeystoreService.lock(mCurrentUserId); // as long as this doesn't recur...
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error locking keystore", e);
+ }
}
@Override // Binder interface
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 75bb5e4..61c8b79 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -196,7 +196,7 @@
private static final String THERMAL_OBSERVER_CLASS =
"com.google.android.clockwork.ThermalObserver";
private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
- "com.google.android.clockwork.connectivity.WearConnectivityService";
+ "com.android.clockwork.connectivity.WearConnectivityService";
private static final String WEAR_SIDEKICK_SERVICE_CLASS =
"com.google.android.clockwork.sidekick.SidekickService";
private static final String WEAR_DISPLAY_SERVICE_CLASS =
diff --git a/services/usb/OWNERS b/services/usb/OWNERS
new file mode 100644
index 0000000..7897a0c
--- /dev/null
+++ b/services/usb/OWNERS
@@ -0,0 +1,4 @@
+badhri@google.com
+elaurent@google.com
+moltmann@google.com
+zhangjerry@google.com
diff --git a/telecomm/OWNERS b/telecomm/OWNERS
new file mode 100644
index 0000000..a3bcfb2
--- /dev/null
+++ b/telecomm/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
+rgreenwalt@google.com
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 8c18518..0c92c20 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -425,8 +425,14 @@
*/
public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
+ /**
+ * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
+ * {@link RttCall} object that is used to send and receive text.
+ */
+ public static final int PROPERTY_RTT = 0x00000400;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00000400
+ // Next PROPERTY value: 0x00000800
//******************************************************************************************
private final String mTelecomCallId;
@@ -1189,6 +1195,23 @@
return null;
}
}
+
+ /**
+ * Closes the underlying file descriptors
+ * @hide
+ */
+ public void close() {
+ try {
+ mReceiveStream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ try {
+ mTransmitStream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
}
/**
@@ -1664,7 +1687,7 @@
* @return true if there is a connection, false otherwise.
*/
public boolean isRttActive() {
- return mRttCall != null;
+ return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
}
/**
@@ -1867,7 +1890,8 @@
boolean isRttChanged = false;
boolean rttModeChanged = false;
- if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
+ if (parcelableCall.getIsRttCallChanged()
+ && mDetails.hasProperty(Details.PROPERTY_RTT)) {
ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
InputStreamReader receiveStream = new InputStreamReader(
new ParcelFileDescriptor.AutoCloseInputStream(
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3229705..26a2f1c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -41,6 +41,8 @@
import android.util.ArraySet;
import android.view.Surface;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
@@ -860,18 +862,19 @@
mFdFromInCall = fromInCall;
mFdToInCall = toInCall;
mPipeFromInCall = new InputStreamReader(
- new ParcelFileDescriptor.AutoCloseInputStream(fromInCall));
+ new FileInputStream(fromInCall.getFileDescriptor()));
mPipeToInCall = new OutputStreamWriter(
- new ParcelFileDescriptor.AutoCloseOutputStream(toInCall));
+ new FileOutputStream(toInCall.getFileDescriptor()));
}
/**
* Writes the string {@param input} into the text stream to the UI for this RTT call. Since
* RTT transmits text in real-time, this method should be called as often as text snippets
* are received from the remote user, even if it is only one character.
- *
+ * <p>
* This method is not thread-safe -- calling it from multiple threads simultaneously may
* lead to interleaved text.
+ *
* @param input The message to send to the in-call app.
*/
public void write(String input) throws IOException {
@@ -884,9 +887,10 @@
* Reads a string from the in-call app, blocking if there is no data available. Returns
* {@code null} if the RTT conversation has been terminated and there is no further data
* to read.
- *
+ * <p>
* This method is not thread-safe -- calling it from multiple threads simultaneously may
* lead to interleaved text.
+ *
* @return A string containing text entered by the user, or {@code null} if the
* conversation has been terminated or if there was an error while reading.
*/
@@ -901,6 +905,7 @@
/**
* Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
* be read.
+ *
* @return A string containing text entered by the user, or {@code null} if the user has
* not entered any new text yet.
*/
@@ -2635,7 +2640,6 @@
* {@link #onStartRtt(RttTextStream)} has succeeded.
*/
public final void sendRttInitiationSuccess() {
- setRttProperty();
mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this));
}
@@ -2647,7 +2651,6 @@
* exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
*/
public final void sendRttInitiationFailure(int reason) {
- unsetRttProperty();
mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason));
}
@@ -2656,7 +2659,6 @@
* side of the coll.
*/
public final void sendRttSessionRemotelyTerminated() {
- unsetRttProperty();
mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this));
}
@@ -2956,22 +2958,6 @@
*/
public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
- /**
- * Internal method to set {@link #PROPERTY_IS_RTT}.
- * @hide
- */
- void setRttProperty() {
- setConnectionProperties(getConnectionProperties() | PROPERTY_IS_RTT);
- }
-
- /**
- * Internal method to un-set {@link #PROPERTY_IS_RTT}.
- * @hide
- */
- void unsetRttProperty() {
- setConnectionProperties(getConnectionProperties() & (~PROPERTY_IS_RTT));
- }
-
static String toLogSafePhoneNumber(String number) {
// For unknown number, log empty string.
if (number == null) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 658b473..b6e6b0e 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -143,6 +143,8 @@
private final boolean mShouldShowIncomingCallUi;
private final ParcelFileDescriptor mRttPipeToInCall;
private final ParcelFileDescriptor mRttPipeFromInCall;
+ // Cached return value of getRttTextStream -- we don't want to wrap it more than once.
+ private Connection.RttTextStream mRttTextStream;
/**
* @param accountHandle The accountHandle which should be used to place the call.
@@ -312,7 +314,10 @@
*/
public Connection.RttTextStream getRttTextStream() {
if (isRequestingRtt()) {
- return new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+ if (mRttTextStream == null) {
+ mRttTextStream = new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+ }
+ return mRttTextStream;
} else {
return null;
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 1547857..ffa0c94 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -143,6 +143,7 @@
private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
private static final String SESSION_START_RTT = "CS.+RTT";
+ private static final String SESSION_UPDATE_RTT_PIPES = "CS.uRTT";
private static final String SESSION_STOP_RTT = "CS.-RTT";
private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
@@ -1864,7 +1865,6 @@
Log.d(this, "stopRtt(%s)", callId);
if (mConnectionById.containsKey(callId)) {
findConnectionForAction(callId, "stopRtt").onStopRtt();
- findConnectionForAction(callId, "stopRtt").unsetRttProperty();
} else if (mConferenceById.containsKey(callId)) {
Log.w(this, "stopRtt called on a conference.");
}
diff --git a/telephony/java/android/telephony/OWNERS b/telephony/OWNERS
similarity index 92%
copy from telephony/java/android/telephony/OWNERS
copy to telephony/OWNERS
index 68dedce..6f67bc2 100644
--- a/telephony/java/android/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,14 +1,14 @@
set noparent
-amitmahajan@google.com
+tgunn@google.com
breadley@google.com
-fionaxu@google.com
-jackyu@google.com
hallliu@google.com
rgreenwalt@google.com
-tgunn@google.com
-jminjie@google.com
mpq@google.com
+amitmahajan@google.com
+fionaxu@google.com
+jackyu@google.com
+jminjie@google.com
+satk@google.com
shuoq@google.com
refuhoo@google.com
-
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index f009fb1..7e86966 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -172,7 +172,7 @@
}
/**
- * Get the timing advance value for LTE, as a value between 0..63.
+ * Get the timing advance value for LTE, as a value in range of 0..1282.
* Integer.MAX_VALUE is reported when there is no active RRC
* connection. Refer to 3GPP 36.213 Sec 4.2.3
* @return the LTE timing advance, if available.
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index cb867ab..ec348df 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1526,7 +1526,9 @@
*/
@SystemApi
public List<NetworkRegistrationState> getNetworkRegistrationStates() {
- return mNetworkRegistrationStates;
+ synchronized (mNetworkRegistrationStates) {
+ return new ArrayList<>(mNetworkRegistrationStates);
+ }
}
/**
@@ -1539,11 +1541,15 @@
@SystemApi
public List<NetworkRegistrationState> getNetworkRegistrationStates(int transportType) {
List<NetworkRegistrationState> list = new ArrayList<>();
- for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
- if (networkRegistrationState.getTransportType() == transportType) {
- list.add(networkRegistrationState);
+
+ synchronized (mNetworkRegistrationStates) {
+ for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
+ if (networkRegistrationState.getTransportType() == transportType) {
+ list.add(networkRegistrationState);
+ }
}
}
+
return list;
}
@@ -1557,12 +1563,36 @@
*/
@SystemApi
public NetworkRegistrationState getNetworkRegistrationStates(int transportType, int domain) {
- for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
- if (networkRegistrationState.getTransportType() == transportType
- && networkRegistrationState.getDomain() == domain) {
- return networkRegistrationState;
+ synchronized (mNetworkRegistrationStates) {
+ for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
+ if (networkRegistrationState.getTransportType() == transportType
+ && networkRegistrationState.getDomain() == domain) {
+ return networkRegistrationState;
+ }
}
}
+
return null;
}
+
+ /**
+ * @hide
+ */
+ public void addNetworkRegistrationState(NetworkRegistrationState regState) {
+ if (regState == null) return;
+
+ synchronized (mNetworkRegistrationStates) {
+ for (int i = 0; i < mNetworkRegistrationStates.size(); i++) {
+ NetworkRegistrationState curRegState = mNetworkRegistrationStates.get(i);
+ if (curRegState.getTransportType() == regState.getTransportType()
+ && curRegState.getDomain() == regState.getDomain()) {
+ mNetworkRegistrationStates.remove(i);
+ break;
+ }
+ }
+
+ mNetworkRegistrationStates.add(regState);
+ }
+ }
+
}
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.mk b/tests/ActivityManagerPerfTests/test-app/Android.mk
index b0a5db7..767e899 100644
--- a/tests/ActivityManagerPerfTests/test-app/Android.mk
+++ b/tests/ActivityManagerPerfTests/test-app/Android.mk
@@ -23,6 +23,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
ActivityManagerPerfTestsUtils
+LOCAL_MIN_SDK_VERSION := 25
+
LOCAL_PACKAGE_NAME := ActivityManagerPerfTestsTestApp
include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/tests/Android.mk b/tests/ActivityManagerPerfTests/tests/Android.mk
index daf603d..7597e69 100644
--- a/tests/ActivityManagerPerfTests/tests/Android.mk
+++ b/tests/ActivityManagerPerfTests/tests/Android.mk
@@ -27,6 +27,8 @@
LOCAL_PACKAGE_NAME := ActivityManagerPerfTests
+LOCAL_MIN_SDK_VERSION := 25
+
# For android.permission.FORCE_STOP_PACKAGES permission
LOCAL_CERTIFICATE := platform
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index bdbc149..a61ac54 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -15,6 +15,7 @@
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -986,11 +987,16 @@
legacyResults[i] = new RttResult();
legacyResults[i].status = result.getStatus();
legacyResults[i].bssid = result.getMacAddress().toString();
- legacyResults[i].distance = result.getDistanceMm() / 10;
- legacyResults[i].distanceStandardDeviation =
- result.getDistanceStdDevMm() / 10;
- legacyResults[i].rssi = result.getRssi();
- legacyResults[i].ts = result.getRangingTimestampUs();
+ if (result.getStatus() == RangingResult.STATUS_SUCCESS) {
+ legacyResults[i].distance = result.getDistanceMm() / 10;
+ legacyResults[i].distanceStandardDeviation =
+ result.getDistanceStdDevMm() / 10;
+ legacyResults[i].rssi = result.getRssi();
+ legacyResults[i].ts = result.getRangingTimestampUs();
+ } else {
+ // just in case legacy API needed some relatively real timestamp
+ legacyResults[i].ts = SystemClock.elapsedRealtime() * 1000;
+ }
}
listener.onSuccess(legacyResults);
}