Skip to content

Commit

Permalink
Merge AP3A.240610.001
Browse files Browse the repository at this point in the history
Change-Id: I972413764d55f91e6d41789a781e57528de05275
  • Loading branch information
Deyao Ren committed Jun 12, 2024
2 parents c9e6a24 + aa8e064 commit 4480cb6
Show file tree
Hide file tree
Showing 190 changed files with 4,241 additions and 1,762 deletions.
8 changes: 8 additions & 0 deletions cmds/dumpstate/TEST_MAPPING
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
},
{
"name": "dumpstate_test"
},
{
"name": "CtsSecurityHostTestCases",
"options": [
{
"include-filter": "android.security.cts.SELinuxHostTest#testNoBugreportDenials"
}
]
}
],
"postsubmit": [
Expand Down
113 changes: 95 additions & 18 deletions cmds/dumpstate/dumpstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ void add_mountinfo();
#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
#define DROPBOX_DIR "/data/system/dropbox"
#define PRINT_FLAGS "/system/bin/printflags"
#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"

// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
Expand Down Expand Up @@ -1982,6 +1983,9 @@ Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
CommandOptions::WithTimeout(10).Always().DropRoot().Build());

// Dump UWB UCI logs here because apexdata requires root access
ds.AddDir(UWB_LOG_DIR, true);

if (dump_pool_) {
RETURN_IF_USER_DENIED_CONSENT();
WaitForTask(std::move(dump_traces));
Expand Down Expand Up @@ -2201,6 +2205,74 @@ static void DumpstateOnboardingOnly() {
ds.AddDir(LOGPERSIST_DATA_DIR, false);
}

static std::string GetTimestamp(const timespec& ts) {
tm tm;
localtime_r(&ts.tv_sec, &tm);

// Reserve enough space for the entire time string, includes the space
// for the '\0' to make the calculations below easier by using size for
// the total string size.
std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
if (n == 0) {
return "TIMESTAMP FAILURE";
}
int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
if (num_chars > str.size() - n) {
return "TIMESTAMP FAILURE";
}
n += static_cast<size_t>(num_chars);
if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
return "TIMESTAMP FAILURE";
}
return str;
}

static std::string GetCmdline(pid_t pid) {
std::string cmdline;
if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
&cmdline)) {
return "UNKNOWN";
}
// There are '\0' terminators between arguments, convert them to spaces.
// But start by skipping all trailing '\0' values.
size_t cur = cmdline.size() - 1;
while (cur != 0 && cmdline[cur] == '\0') {
cur--;
}
if (cur == 0) {
return "UNKNOWN";
}
while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
cmdline[cur] = ' ';
}
return cmdline;
}

static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
// For consistency, the header to this message matches the one
// dumped by debuggerd.
dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
}

static void DumpPidFooter(int fd, pid_t pid) {
// For consistency, the footer to this message matches the one
// dumped by debuggerd.
dprintf(fd, "----- end %d -----\n", pid);
}

static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
int ret = dump_backtrace_to_file_timeout(
pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
if (ret == -1 && is_java_process) {
// Tried to unwind as a java process, try a native unwind.
dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
}
return ret != -1;
}

Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
const size_t buf_size = temp_file_pattern.length() + 1;
Expand Down Expand Up @@ -2249,16 +2321,6 @@ Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
continue;
}

// Skip cached processes.
if (IsCached(pid)) {
// For consistency, the header and footer to this message match those
// dumped by debuggerd in the success case.
dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
dprintf(fd, "Dump skipped for cached process.\n");
dprintf(fd, "---- end %d ----", pid);
continue;
}

const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
std::string exe;
if (!android::base::Readlink(link_name, &exe)) {
Expand Down Expand Up @@ -2287,16 +2349,31 @@ Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
break;
}

timespec start_timespec;
clock_gettime(CLOCK_REALTIME, &start_timespec);
if (IsCached(pid)) {
DumpPidHeader(fd, pid, start_timespec);
dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
DumpPidFooter(fd, pid);
continue;
}

const uint64_t start = Nanotime();
const int ret = dump_backtrace_to_file_timeout(
pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
if (!DumpBacktrace(fd, pid, is_java_process)) {
if (IsCached(pid)) {
DumpPidHeader(fd, pid, start_timespec);
dprintf(fd, "Backtrace failed, but process has become cached.\n");
DumpPidFooter(fd, pid);
continue;
}

if (ret == -1) {
// For consistency, the header and footer to this message match those
// dumped by debuggerd in the success case.
dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
dprintf(fd, "Dump failed, likely due to a timeout.\n");
dprintf(fd, "---- end %d ----", pid);
DumpPidHeader(fd, pid, start_timespec);
dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
DumpPidFooter(fd, pid);

dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
is_java_process ? "dalvik" : "native", pid,
(float)(Nanotime() - start) / NANOS_PER_SEC);
timeout_failures++;
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion cmds/installd/file_parsing.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ bool ParseFile(std::istream& input_stream, Func parse) {
}

template<typename Func>
bool ParseFile(std::string_view str_file, Func parse) {
bool ParseFile(const std::string& str_file, Func parse) {
std::ifstream ifs(str_file);
if (!ifs.is_open()) {
return false;
Expand Down
22 changes: 21 additions & 1 deletion cmds/installd/otapreopt_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,27 @@ else
exit 1
fi

if pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
# A source that infinitely emits arbitrary lines.
# When connected to STDIN of another process, this source keeps STDIN open until
# the consumer process closes STDIN or this script dies.
function infinite_source {
while echo .; do
sleep 1
done
}

# Delegate to Pre-reboot Dexopt, a feature of ART Service.
# ART Service decides what to do with this request:
# - If Pre-reboot Dexopt is disabled or unsupported, the command returns
# non-zero. This is always the case if the current system is Android 14 or
# earlier.
# - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks
# until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or
# not. This is the default behavior if the current system is Android 15.
# - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules
# an asynchronous job and returns 0 immediately. The job will then run by the
# job scheduler when the device is idle and charging.
if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
# Handled by Pre-reboot Dexopt.
exit 0
fi
Expand Down
1 change: 0 additions & 1 deletion include/android/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,6 @@ enum {
* Keyboard types.
*
* Refer to the documentation on android.view.InputDevice for more details.
* Note: When adding a new keyboard type here InputDeviceInfo::setKeyboardType needs to be updated.
*/
enum {
/** none */
Expand Down
1 change: 1 addition & 0 deletions include/binder/Common.h
10 changes: 10 additions & 0 deletions include/input/Input.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,16 @@ enum class KeyState {
ftl_last = VIRTUAL,
};

/**
* The keyboard type. This should have 1:1 correspondence with the values of anonymous enum
* defined in input.h
*/
enum class KeyboardType {
NONE = AINPUT_KEYBOARD_TYPE_NONE,
NON_ALPHABETIC = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
ALPHABETIC = AINPUT_KEYBOARD_TYPE_ALPHABETIC,
};

bool isStylusToolType(ToolType toolType);

struct PointerProperties;
Expand Down
53 changes: 53 additions & 0 deletions include/input/KeyboardClassifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2024 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.
*/

#pragma once

#include <android-base/result.h>
#include <input/Input.h>
#include <input/InputDevice.h>

#include "rust/cxx.h"

namespace android {

namespace input {
namespace keyboardClassifier {
struct KeyboardClassifier;
}
} // namespace input

/*
* Keyboard classifier to classify keyboard into alphabetic and non-alphabetic keyboards
*/
class KeyboardClassifier {
public:
KeyboardClassifier();
/**
* Get the type of keyboard that the classifier currently believes the device to be.
*/
KeyboardType getKeyboardType(DeviceId deviceId);
void notifyKeyboardChanged(DeviceId deviceId, const InputDeviceIdentifier& identifier,
uint32_t deviceClasses);
void processKey(DeviceId deviceId, int32_t evdevCode, uint32_t metaState);

private:
std::optional<rust::Box<android::input::keyboardClassifier::KeyboardClassifier>>
mRustClassifier;
std::unordered_map<DeviceId, KeyboardType> mKeyboardTypeMap;
};

} // namespace android
Loading

0 comments on commit 4480cb6

Please sign in to comment.