Merge "Added callback to enable CarSysUI for showing user switch dialog during before user switching" into rvc-dev
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index 3160e9e..099d56a 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -988,6 +988,10 @@
/**
* A factory method that creates Car instance for all Car API access.
+ *
+ * <p>Instance created with this should be disconnected from car service by calling
+ * {@link #disconnect()} before the passed {code Context} is released.
+ *
* @param context App's Context. This should not be null. If you are passing
* {@link ContextWrapper}, make sure that its base Context is non-null as well.
* Otherwise it will throw {@link java.lang.NullPointerException}.
@@ -1020,6 +1024,9 @@
* A factory method that creates Car instance for all Car API access using main thread {@code
* Looper}.
*
+ * <p>Instance created with this should be disconnected from car service by calling
+ * {@link #disconnect()} before the passed {code Context} is released.
+ *
* @see #createCar(Context, ServiceConnection, Handler)
*
* @deprecated use {@link #createCar(Context, Handler)} instead.
@@ -1032,6 +1039,9 @@
/**
* Creates new {@link Car} object which connected synchronously to Car Service and ready to use.
*
+ * <p>Instance created with this should be disconnected from car service by calling
+ * {@link #disconnect()} before the passed {code Context} is released.
+ *
* @param context application's context
*
* @return Car object if operation succeeded, otherwise null.
@@ -1044,6 +1054,9 @@
/**
* Creates new {@link Car} object which connected synchronously to Car Service and ready to use.
*
+ * <p>Instance created with this should be disconnected from car service by calling
+ * {@link #disconnect()} before the passed {code Context} is released.
+ *
* @param context App's Context. This should not be null. If you are passing
* {@link ContextWrapper}, make sure that its base Context is non-null as well.
* Otherwise it will throw {@link java.lang.NullPointerException}.
@@ -1111,6 +1124,9 @@
/**
* Creates new {@link Car} object with {@link CarServiceLifecycleListener}.
*
+ * <p>Instance created with this should be disconnected from car service by calling
+ * {@link #disconnect()} before the passed {code Context} is released.
+ *
* <p> If car service is ready inside this call and if the caller is running in the main thread,
* {@link CarServiceLifecycleListener#onLifecycleChanged(Car, boolean)} will be called
* with ready set to be true. Otherwise,
diff --git a/car-lib/src/android/car/navigation/CarNavigationInstrumentCluster.java b/car-lib/src/android/car/navigation/CarNavigationInstrumentCluster.java
index b41c7de..444f82a 100644
--- a/car-lib/src/android/car/navigation/CarNavigationInstrumentCluster.java
+++ b/car-lib/src/android/car/navigation/CarNavigationInstrumentCluster.java
@@ -57,25 +57,31 @@
private final Bundle mExtra;
- public static final Parcelable.Creator<CarNavigationInstrumentCluster> CREATOR
- = new Parcelable.Creator<CarNavigationInstrumentCluster>() {
- public CarNavigationInstrumentCluster createFromParcel(Parcel in) {
- return new CarNavigationInstrumentCluster(in);
- }
+ public static final Parcelable.Creator<CarNavigationInstrumentCluster> CREATOR =
+ new Parcelable.Creator<CarNavigationInstrumentCluster>() {
+ public CarNavigationInstrumentCluster createFromParcel(Parcel in) {
+ return new CarNavigationInstrumentCluster(in);
+ }
- public CarNavigationInstrumentCluster[] newArray(int size) {
- return new CarNavigationInstrumentCluster[size];
- }
- };
+ public CarNavigationInstrumentCluster[] newArray(int size) {
+ return new CarNavigationInstrumentCluster[size];
+ }
+ };
+ /**
+ * Creates a new {@link CarNavigationInstrumentCluster}.
+ */
public static CarNavigationInstrumentCluster createCluster(int minIntervalMillis) {
return new CarNavigationInstrumentCluster(minIntervalMillis, CLUSTER_TYPE_IMAGE_CODES_ONLY,
0, 0, 0);
}
- public static CarNavigationInstrumentCluster createCustomImageCluster(int minIntervalMs,
+ /**
+ * Creates a new {@link CarNavigationInstrumentCluster}.
+ */
+ public static CarNavigationInstrumentCluster createCustomImageCluster(int minIntervalMillis,
int imageWidth, int imageHeight, int imageColorDepthBits) {
- return new CarNavigationInstrumentCluster(minIntervalMs,
+ return new CarNavigationInstrumentCluster(minIntervalMillis,
CLUSTER_TYPE_CUSTOM_IMAGES_SUPPORTED,
imageWidth, imageHeight, imageColorDepthBits);
}
@@ -108,7 +114,9 @@
* Contains extra information about instrument cluster.
* @hide
*/
- public Bundle getExtra() { return mExtra; }
+ public Bundle getExtra() {
+ return mExtra;
+ }
/**
* If instrument cluster is image, number of bits of colour depth it supports (8, 16, or 32).
@@ -127,10 +135,9 @@
/**
* Whether cluster support custom image or not.
- * @return
*/
public boolean supportsCustomImages() {
- return mType == CLUSTER_TYPE_CUSTOM_IMAGES_SUPPORTED;
+ return mType == CLUSTER_TYPE_CUSTOM_IMAGES_SUPPORTED;
}
private CarNavigationInstrumentCluster(
@@ -174,12 +181,12 @@
/** Converts to string for debug purpose */
@Override
public String toString() {
- return CarNavigationInstrumentCluster.class.getSimpleName() + "{ " +
- "minIntervalMillis: " + mMinIntervalMillis + ", " +
- "type: " + mType + ", " +
- "imageWidth: " + mImageWidth + ", " +
- "imageHeight: " + mImageHeight + ", " +
- "imageColourDepthBits: " + mImageColorDepthBits +
- "extra: " + mExtra + " }";
+ return CarNavigationInstrumentCluster.class.getSimpleName() + "{ "
+ + "minIntervalMillis: " + mMinIntervalMillis + ", "
+ + "type: " + mType + ", "
+ + "imageWidth: " + mImageWidth + ", "
+ + "imageHeight: " + mImageHeight + ", "
+ + "imageColourDepthBits: " + mImageColorDepthBits
+ + "extra: " + mExtra + " }";
}
}
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index b901ec2..2ae56cb 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -36,6 +36,7 @@
import android.car.user.GetUserIdentificationAssociationResponse;
import android.car.user.UserSwitchResult;
import android.car.userlib.CarUserManagerHelper;
+import android.car.userlib.CommonConstants.CarUserServiceConstants;
import android.car.userlib.HalCallback;
import android.car.userlib.UserHalHelper;
import android.content.Context;
@@ -103,13 +104,14 @@
private static final String TAG = TAG_USER;
/** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
- public static final String BUNDLE_USER_ID = "user.id";
+ public static final String BUNDLE_USER_ID = CarUserServiceConstants.BUNDLE_USER_ID;
/** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
- public static final String BUNDLE_USER_FLAGS = "user.flags";
+ public static final String BUNDLE_USER_FLAGS = CarUserServiceConstants.BUNDLE_USER_FLAGS;
/** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
- public static final String BUNDLE_USER_NAME = "user.name";
+ public static final String BUNDLE_USER_NAME = CarUserServiceConstants.BUNDLE_USER_NAME;
/** {@code int} extra used to represent the info action {@link IResultReceiver} response. */
- public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
+ public static final String BUNDLE_INITIAL_INFO_ACTION =
+ CarUserServiceConstants.BUNDLE_INITIAL_INFO_ACTION;
private final Context mContext;
private final CarUserManagerHelper mCarUserManagerHelper;
diff --git a/user/car-user-lib/src/android/car/userlib/CommonConstants.java b/user/car-user-lib/src/android/car/userlib/CommonConstants.java
new file mode 100644
index 0000000..ef9a354
--- /dev/null
+++ b/user/car-user-lib/src/android/car/userlib/CommonConstants.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.userlib;
+
+/**
+ * Provides constants used by both CarService and CarServiceHelper packages.
+ */
+public final class CommonConstants {
+
+ private CommonConstants() {
+ throw new UnsupportedOperationException("contains only static constants");
+ }
+
+ /**
+ * Constants used on {@link android.os.Bundle bundles} sent by
+ * {@link com.android.car.user.CarUserService} on binder calls.
+ */
+ public static final class CarUserServiceConstants {
+
+ public static final String BUNDLE_USER_ID = "user.id";
+ public static final String BUNDLE_USER_FLAGS = "user.flags";
+ public static final String BUNDLE_USER_NAME = "user.name";
+ public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
+
+ private CarUserServiceConstants() {
+ throw new UnsupportedOperationException("contains only static constants");
+ }
+ }
+}
diff --git a/watchdog/server/src/IoPerfCollection.cpp b/watchdog/server/src/IoPerfCollection.cpp
index a97858b..2799417 100644
--- a/watchdog/server/src/IoPerfCollection.cpp
+++ b/watchdog/server/src/IoPerfCollection.cpp
@@ -55,6 +55,7 @@
using android::base::Result;
using android::base::Split;
using android::base::StringAppendF;
+using android::base::StringPrintf;
using android::base::WriteStringToFd;
using android::content::pm::IPackageManagerNative;
@@ -76,6 +77,24 @@
const std::string kDumpMajorDelimiter = std::string(100, '-') + "\n";
+constexpr const char* kHelpText =
+ "\nCustom I/O performance data collection dump options:\n"
+ "%s: Starts custom I/O performance data collection. Customize the collection behavior with "
+ "the following optional arguments:\n"
+ "\t%s <seconds>: Modifies the collection interval. Default behavior is to collect once "
+ "every %lld seconds.\n"
+ "\t%s <seconds>: Modifies the maximum collection duration. Default behavior is to collect "
+ "until %ld minutes before automatically stopping the custom collection and discarding "
+ "the collected data.\n"
+ "\t%s <package name>,<package, name>,...: Comma-separated value containing package names. "
+ "When provided, the results are filtered only to the provided package names. Default "
+ "behavior is to list the results for the top %d packages.\n"
+ "%s: Stops custom I/O performance data collection and generates a dump of "
+ "the collection report.\n\n"
+ "When no options are specified, the carwatchdog report contains the I/O performance "
+ "data collected during boot-time and over the last %ld minutes before the report "
+ "generation.";
+
double percentage(uint64_t numer, uint64_t denom) {
return denom == 0 ? 0.0 : (static_cast<double>(numer) / static_cast<double>(denom)) * 100.0;
}
@@ -406,8 +425,8 @@
if (args[0] == String16(kStartCustomCollectionFlag)) {
if (args.size() > 7) {
- return Error(INVALID_OPERATION) << "Number of arguments to start custom "
- << "I/O performance data collection cannot exceed 7";
+ return Error(BAD_VALUE) << "Number of arguments to start custom I/O performance data "
+ << "collection cannot exceed 7";
}
std::chrono::nanoseconds interval = kCustomCollectionInterval;
std::chrono::nanoseconds maxDuration = kCustomCollectionDuration;
@@ -416,7 +435,7 @@
if (args[i] == String16(kIntervalFlag)) {
const auto& ret = parseSecondsFlag(args, i + 1);
if (!ret) {
- return Error(FAILED_TRANSACTION)
+ return Error(BAD_VALUE)
<< "Failed to parse " << kIntervalFlag << ": " << ret.error();
}
interval = std::chrono::duration_cast<std::chrono::nanoseconds>(*ret);
@@ -426,7 +445,7 @@
if (args[i] == String16(kMaxDurationFlag)) {
const auto& ret = parseSecondsFlag(args, i + 1);
if (!ret) {
- return Error(FAILED_TRANSACTION)
+ return Error(BAD_VALUE)
<< "Failed to parse " << kMaxDurationFlag << ": " << ret.error();
}
maxDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(*ret);
@@ -435,7 +454,7 @@
}
if (args[i] == String16(kFilterPackagesFlag)) {
if (args.size() < i + 1) {
- return Error(FAILED_TRANSACTION)
+ return Error(BAD_VALUE)
<< "Must provide value for '" << kFilterPackagesFlag << "' flag";
}
std::vector<std::string> packages =
@@ -447,12 +466,13 @@
}
ALOGW("Unknown flag %s provided to start custom I/O performance data collection",
String8(args[i]).string());
- return Error(INVALID_OPERATION) << "Unknown flag " << String8(args[i]).string()
- << " provided to start custom I/O performance data "
- << "collection";
+ return Error(BAD_VALUE) << "Unknown flag " << String8(args[i]).string()
+ << " provided to start custom I/O performance data "
+ << "collection";
}
const auto& ret = startCustomCollection(interval, maxDuration, filterPackages);
if (!ret) {
+ WriteStringToFd(ret.error().message(), fd);
return ret;
}
return {};
@@ -460,19 +480,37 @@
if (args[0] == String16(kEndCustomCollectionFlag)) {
if (args.size() != 1) {
- ALOGW("Number of arguments to end custom I/O performance data collection cannot "
- "exceed 1");
+ ALOGW("Number of arguments to stop custom I/O performance data collection cannot "
+ "exceed 1. Stopping the data collection.");
+ WriteStringToFd("Number of arguments to stop custom I/O performance data collection "
+ "cannot exceed 1. Stopping the data collection.",
+ fd);
}
- const auto& ret = endCustomCollection(fd);
- if (!ret) {
- return ret;
- }
- return {};
+ return endCustomCollection(fd);
}
- return Error(INVALID_OPERATION)
- << "Dump arguments start neither with " << kStartCustomCollectionFlag << " nor with "
- << kEndCustomCollectionFlag << " flags";
+ return Error(BAD_VALUE) << "I/O perf collection dump arguments start neither with "
+ << kStartCustomCollectionFlag << " nor with "
+ << kEndCustomCollectionFlag << " flags";
+}
+
+bool IoPerfCollection::dumpHelpText(int fd) {
+ long periodicCacheMinutes =
+ (std::chrono::duration_cast<std::chrono::seconds>(mPeriodicCollection.interval)
+ .count() *
+ mPeriodicCollection.maxCacheSize) /
+ 60;
+ return WriteStringToFd(StringPrintf(kHelpText, kStartCustomCollectionFlag, kIntervalFlag,
+ std::chrono::duration_cast<std::chrono::seconds>(
+ kCustomCollectionInterval)
+ .count(),
+ kMaxDurationFlag,
+ std::chrono::duration_cast<std::chrono::minutes>(
+ kCustomCollectionDuration)
+ .count(),
+ kFilterPackagesFlag, mTopNStatsPerCategory,
+ kEndCustomCollectionFlag, periodicCacheMinutes),
+ fd);
}
Result<void> IoPerfCollection::dumpCollection(int fd) {
diff --git a/watchdog/server/src/IoPerfCollection.h b/watchdog/server/src/IoPerfCollection.h
index 9cde199..4cccb05 100644
--- a/watchdog/server/src/IoPerfCollection.h
+++ b/watchdog/server/src/IoPerfCollection.h
@@ -190,6 +190,9 @@
// Returns any error observed during the dump generation.
virtual android::base::Result<void> dump(int fd, const Vector<String16>& args);
+ // Dumps the help text.
+ bool dumpHelpText(int fd);
+
private:
// Generates a dump from the boot-time and periodic collection events.
android::base::Result<void> dumpCollection(int fd);
diff --git a/watchdog/server/src/WatchdogBinderMediator.cpp b/watchdog/server/src/WatchdogBinderMediator.cpp
index da4ea29..0a482fd 100644
--- a/watchdog/server/src/WatchdogBinderMediator.cpp
+++ b/watchdog/server/src/WatchdogBinderMediator.cpp
@@ -18,6 +18,7 @@
#include "WatchdogBinderMediator.h"
+#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android/automotive/watchdog/BootPhase.h>
@@ -38,10 +39,19 @@
using android::base::ParseUint;
using android::base::Result;
using android::base::StringPrintf;
+using android::base::WriteStringToFd;
using android::binder::Status;
namespace {
+constexpr const char* kHelpFlag = "--help";
+constexpr const char* kHelpShortFlag = "-h";
+constexpr const char* kHelpText =
+ "CarWatchdog daemon dumpsys help page:\n"
+ "Format: dumpsys android.automotive.watchdog.ICarWatchdog/default [options]\n\n"
+ "%s or %s: Displays this help text.\n"
+ "When no options are specified, carwatchdog report is generated.\n";
+
Status checkSystemPermission() {
if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
return Status::fromExceptionCode(Status::EX_SECURITY,
@@ -94,21 +104,48 @@
}
return OK;
}
+
+ if (args[0] == String16(kHelpFlag) || args[0] == String16(kHelpShortFlag)) {
+ if (!dumpHelpText(fd, "")) {
+ ALOGW("Failed to write help text to fd");
+ return FAILED_TRANSACTION;
+ }
+ return OK;
+ }
+
if (args[0] == String16(kStartCustomCollectionFlag) ||
args[0] == String16(kEndCustomCollectionFlag)) {
auto ret = mIoPerfCollection->dump(fd, args);
- std::string mode = args[0] == String16(kStartCustomCollectionFlag) ? "start" : "end";
if (!ret.ok()) {
- ALOGW("Failed to %s custom I/O perf collection: %s", mode.c_str(),
- ret.error().message().c_str());
+ std::string mode = args[0] == String16(kStartCustomCollectionFlag) ? "start" : "end";
+ std::string errorMsg = StringPrintf("Failed to %s custom I/O perf collection: %s",
+ mode.c_str(), ret.error().message().c_str());
+ if (ret.error().code() == BAD_VALUE) {
+ dumpHelpText(fd, errorMsg);
+ } else {
+ ALOGW("%s", errorMsg.c_str());
+ }
return ret.error().code();
}
return OK;
}
- ALOGW("Invalid dump arguments");
+ dumpHelpText(fd, "Invalid dump arguments");
return INVALID_OPERATION;
}
+bool WatchdogBinderMediator::dumpHelpText(int fd, std::string errorMsg) {
+ if (!errorMsg.empty()) {
+ ALOGW("Error: %s", errorMsg.c_str());
+ if (!WriteStringToFd(StringPrintf("Error: %s\n\n", errorMsg.c_str()), fd)) {
+ ALOGW("Failed to write error message to fd");
+ return false;
+ }
+ }
+
+ return WriteStringToFd(StringPrintf(kHelpText, kHelpFlag, kHelpShortFlag), fd) &&
+ mIoPerfCollection->dumpHelpText(fd);
+}
+
Status WatchdogBinderMediator::registerMediator(const sp<ICarWatchdogClient>& mediator) {
Status status = checkSystemPermission();
if (!status.isOk()) {
diff --git a/watchdog/server/src/WatchdogBinderMediator.h b/watchdog/server/src/WatchdogBinderMediator.h
index a3b19a2..530659b 100644
--- a/watchdog/server/src/WatchdogBinderMediator.h
+++ b/watchdog/server/src/WatchdogBinderMediator.h
@@ -83,6 +83,8 @@
void binderDied(const android::wp<IBinder>& who) override {
return mWatchdogProcessService->binderDied(who);
}
+ bool dumpHelpText(int fd, std::string errorMsg);
+
android::sp<WatchdogProcessService> mWatchdogProcessService;
android::sp<IoPerfCollection> mIoPerfCollection;