Merge changes I9a4e1eee,I3d086741 into rvc-dev
* changes:
Fix flaky ActivityBlockingActivityTest.
Ignore invisible stacks in ABA
diff --git a/evs/apps/default/ConfigManager.h b/evs/apps/default/ConfigManager.h
index b3d283e..6acd83d 100644
--- a/evs/apps/default/ConfigManager.h
+++ b/evs/apps/default/ConfigManager.h
@@ -89,6 +89,8 @@
}
const std::vector<DisplayInfo>& getDisplays() const { return mDisplays; };
const DisplayInfo& getActiveDisplay() const { return mDisplays[mActiveDisplayId]; };
+ void useExternalMemory(bool flag) { mUseExternalMemory = flag; }
+ bool getUseExternalMemory() const { return mUseExternalMemory; }
private:
// Camera information
@@ -98,6 +100,9 @@
std::vector<DisplayInfo> mDisplays;
int mActiveDisplayId;
+ // Memory management
+ bool mUseExternalMemory;
+
// Car body information (assumes front wheel steering and origin at center of rear axel)
// Note that units aren't specified and don't matter as long as all length units are consistent
// within the JSON file from which we parse. That is, if everything is in meters, that's fine.
diff --git a/evs/apps/default/EvsStateControl.cpp b/evs/apps/default/EvsStateControl.cpp
index b963551..e45fe2f 100644
--- a/evs/apps/default/EvsStateControl.cpp
+++ b/evs/apps/default/EvsStateControl.cpp
@@ -303,7 +303,8 @@
if (mCameraList[desiredState].size() == 1) {
// We have a camera assigned to this state for direct view.
mDesiredRenderer = std::make_unique<RenderDirectView>(mEvs,
- mCameraDescList[desiredState][0]);
+ mCameraDescList[desiredState][0],
+ mConfig);
if (!mDesiredRenderer) {
LOG(ERROR) << "Failed to construct direct renderer. Skipping state change.";
return false;
diff --git a/evs/apps/default/RenderDirectView.cpp b/evs/apps/default/RenderDirectView.cpp
index 4a8db70..2938521 100644
--- a/evs/apps/default/RenderDirectView.cpp
+++ b/evs/apps/default/RenderDirectView.cpp
@@ -42,9 +42,11 @@
RenderDirectView::RenderDirectView(sp<IEvsEnumerator> enumerator,
- const CameraDesc& camDesc) :
+ const CameraDesc& camDesc,
+ const ConfigManager& config) :
mEnumerator(enumerator),
- mCameraDesc(camDesc) {
+ mCameraDesc(camDesc),
+ mConfig(config) {
/* Nothing to do */
}
@@ -113,7 +115,8 @@
mTexture.reset(createVideoTexture(mEnumerator,
mCameraDesc.v1.cameraId.c_str(),
foundCfg ? std::move(targetCfg) : nullptr,
- sDisplay));
+ sDisplay,
+ mConfig.getUseExternalMemory()));
if (!mTexture) {
LOG(ERROR) << "Failed to set up video texture for " << mCameraDesc.v1.cameraId;
// TODO: For production use, we may actually want to fail in this case, but not yet...
diff --git a/evs/apps/default/RenderDirectView.h b/evs/apps/default/RenderDirectView.h
index 3514e05..65a94e2 100644
--- a/evs/apps/default/RenderDirectView.h
+++ b/evs/apps/default/RenderDirectView.h
@@ -35,7 +35,8 @@
class RenderDirectView: public RenderBase {
public:
RenderDirectView(sp<IEvsEnumerator> enumerator,
- const CameraDesc& camDesc);
+ const CameraDesc& camDesc,
+ const ConfigManager& config);
virtual bool activate() override;
virtual void deactivate() override;
@@ -46,6 +47,7 @@
sp<IEvsEnumerator> mEnumerator;
ConfigManager::CameraInfo mCameraInfo;
CameraDesc mCameraDesc;
+ const ConfigManager& mConfig;
std::unique_ptr<VideoTex> mTexture;
diff --git a/evs/apps/default/StreamHandler.cpp b/evs/apps/default/StreamHandler.cpp
index 328f454..b1cfd1f 100644
--- a/evs/apps/default/StreamHandler.cpp
+++ b/evs/apps/default/StreamHandler.cpp
@@ -21,16 +21,73 @@
#include <android-base/logging.h>
#include <cutils/native_handle.h>
+#include <ui/GraphicBufferAllocator.h>
using ::android::hardware::automotive::evs::V1_0::EvsResult;
-StreamHandler::StreamHandler(android::sp <IEvsCamera> pCamera) :
- mCamera(pCamera)
-{
- // We rely on the camera having at least two buffers available since we'll hold one and
- // expect the camera to be able to capture a new image in the background.
- pCamera->setMaxFramesInFlight(2);
+buffer_handle_t memHandle = nullptr;
+StreamHandler::StreamHandler(android::sp <IEvsCamera> pCamera,
+ uint32_t numBuffers,
+ bool useOwnBuffers,
+ int32_t width,
+ int32_t height)
+ : mCamera(pCamera),
+ mUseOwnBuffers(useOwnBuffers) {
+ if (!useOwnBuffers) {
+ // We rely on the camera having at least two buffers available since we'll hold one and
+ // expect the camera to be able to capture a new image in the background.
+ pCamera->setMaxFramesInFlight(numBuffers);
+ } else {
+ mOwnBuffers.resize(numBuffers);
+
+ // Acquire the graphics buffer allocator
+ android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
+ const auto usage = GRALLOC_USAGE_HW_TEXTURE |
+ GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
+ for (auto i = 0; i < numBuffers; ++i) {
+ unsigned pixelsPerLine;
+ android::status_t result = alloc.allocate(width,
+ height,
+ format,
+ 1,
+ usage,
+ &memHandle,
+ &pixelsPerLine,
+ 0,
+ "EvsApp");
+ if (result != android::NO_ERROR) {
+ LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
+ } else {
+ BufferDesc_1_1 buf;
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc *>(&buf.buffer.description);
+ pDesc->width = 640;
+ pDesc->height = 360;
+ pDesc->layers = 1;
+ pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
+ pDesc->usage = GRALLOC_USAGE_HW_TEXTURE |
+ GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_OFTEN;
+ pDesc->stride = pixelsPerLine;
+ buf.buffer.nativeHandle = memHandle;
+ buf.bufferId = i; // Unique number to identify this buffer
+ mOwnBuffers[i] = buf;
+ }
+ }
+
+ int delta = 0;
+ EvsResult result = EvsResult::OK;
+ pCamera->importExternalBuffers(mOwnBuffers,
+ [&](auto _result, auto _delta) {
+ result = _result;
+ delta = _delta;
+ });
+
+ LOG(INFO) << delta << " buffers are imported by EVS.";
+ }
}
@@ -42,6 +99,15 @@
// At this point, the receiver thread is no longer running, so we can safely drop
// our remote object references so they can be freed
mCamera = nullptr;
+
+ if (mUseOwnBuffers) {
+ android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
+ for (auto& b : mOwnBuffers) {
+ alloc.free(b.buffer.nativeHandle);
+ }
+
+ mOwnBuffers.resize(0);
+ }
}
diff --git a/evs/apps/default/StreamHandler.h b/evs/apps/default/StreamHandler.h
index cb7a288..f877c78 100644
--- a/evs/apps/default/StreamHandler.h
+++ b/evs/apps/default/StreamHandler.h
@@ -48,7 +48,11 @@
public:
virtual ~StreamHandler() { shutdown(); };
- StreamHandler(android::sp <IEvsCamera> pCamera);
+ StreamHandler(android::sp <IEvsCamera> pCamera,
+ uint32_t numBuffers = 2,
+ bool useOwnBuffers = false,
+ int32_t width = 640,
+ int32_t height = 360);
void shutdown();
bool startStream();
@@ -83,6 +87,8 @@
BufferDesc mBuffers[2];
int mHeldBuffer = -1; // Index of the one currently held by the client
int mReadyBuffer = -1; // Index of the newest available buffer
+ hidl_vec<BufferDesc_1_1> mOwnBuffers;
+ bool mUseOwnBuffers;
};
diff --git a/evs/apps/default/VideoTex.cpp b/evs/apps/default/VideoTex.cpp
index c9fc895..94e734a 100644
--- a/evs/apps/default/VideoTex.cpp
+++ b/evs/apps/default/VideoTex.cpp
@@ -136,7 +136,8 @@
VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char* evsCameraId,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay) {
+ EGLDisplay glDisplay,
+ bool useExternalMemory) {
// Set up the camera to feed this texture
sp<IEvsCamera> pCamera = nullptr;
if (streamCfg != nullptr) {
@@ -153,7 +154,11 @@
}
// Initialize the stream that will help us update this texture's contents
- sp<StreamHandler> pStreamHandler = new StreamHandler(pCamera);
+ sp<StreamHandler> pStreamHandler = new StreamHandler(pCamera,
+ 2, // number of buffers
+ useExternalMemory,
+ streamCfg->width,
+ streamCfg->height);
if (pStreamHandler.get() == nullptr) {
LOG(ERROR) << "Failed to allocate FrameHandler";
return nullptr;
diff --git a/evs/apps/default/VideoTex.h b/evs/apps/default/VideoTex.h
index 00e9faa..d884faa 100644
--- a/evs/apps/default/VideoTex.h
+++ b/evs/apps/default/VideoTex.h
@@ -37,7 +37,8 @@
friend VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char *evsCameraId,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay);
+ EGLDisplay glDisplay,
+ bool useExternalMemory);
public:
VideoTex() = delete;
@@ -64,6 +65,7 @@
VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char * deviceName,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay);
+ EGLDisplay glDisplay,
+ bool useExternalMemory = false);
#endif // VIDEOTEX_H
diff --git a/evs/apps/default/evs_app.cpp b/evs/apps/default/evs_app.cpp
index 65519c7..a968990 100644
--- a/evs/apps/default/evs_app.cpp
+++ b/evs/apps/default/evs_app.cpp
@@ -76,6 +76,7 @@
bool printHelp = false;
const char* evsServiceName = "default";
int displayId = 1;
+ bool useExternalMemory = false;
for (int i=1; i< argc; i++) {
if (strcmp(argv[i], "--test") == 0) {
useVehicleHal = false;
@@ -87,6 +88,8 @@
printHelp = true;
} else if (strcmp(argv[i], "--display") == 0) {
displayId = std::stoi(argv[++i]);
+ } else if (strcmp(argv[i], "--extmem") == 0) {
+ useExternalMemory = true;
} else {
printf("Ignoring unrecognized command line arg '%s'\n", argv[i]);
printHelp = true;
@@ -98,6 +101,7 @@
printf(" --hw Bypass EvsManager by connecting directly to EvsEnumeratorHw\n");
printf(" --mock Connect directly to EvsEnumeratorHw-Mock\n");
printf(" --display Specify the display to use\n");
+ printf(" --extmem Application allocates buffers to capture camera frames\n");
}
// Load our configuration information
@@ -135,6 +139,7 @@
return 1;
}
config.setActiveDisplayId(displayId);
+ config.useExternalMemory(useExternalMemory);
// Connect to the Vehicle HAL so we can monitor state
sp<IVehicle> pVnet;
diff --git a/evs/manager/1.1/HalCamera.cpp b/evs/manager/1.1/HalCamera.cpp
index 902366e..fef7e9e 100644
--- a/evs/manager/1.1/HalCamera.cpp
+++ b/evs/manager/1.1/HalCamera.cpp
@@ -153,6 +153,58 @@
}
+bool HalCamera::changeFramesInFlight(const hidl_vec<BufferDesc_1_1>& buffers,
+ int* delta) {
+ // Return immediately if a list is empty.
+ if (buffers.size() < 1) {
+ LOG(DEBUG) << "No external buffers to add.";
+ return true;
+ }
+
+ // Walk all our clients and count their currently required frames
+ auto bufferCount = 0;
+ for (auto&& client : mClients) {
+ sp<VirtualCamera> virtCam = client.promote();
+ if (virtCam != nullptr) {
+ bufferCount += virtCam->getAllowedBuffers();
+ }
+ }
+
+ EvsResult status = EvsResult::OK;
+ // Ask the hardware for the resulting buffer count
+ mHwCamera->importExternalBuffers(buffers,
+ [&](auto result, auto added) {
+ status = result;
+ *delta = added;
+ });
+ if (status != EvsResult::OK) {
+ LOG(ERROR) << "Failed to add external capture buffers.";
+ return false;
+ }
+
+ bufferCount += *delta;
+
+ // Update the size of our array of outstanding frame records
+ std::vector<FrameRecord> newRecords;
+ newRecords.reserve(bufferCount);
+
+ // Copy and compact the old records that are still active
+ for (const auto& rec : mFrames) {
+ if (rec.refCount > 0) {
+ newRecords.emplace_back(rec);
+ }
+ }
+
+ if (newRecords.size() > (unsigned)bufferCount) {
+ LOG(WARNING) << "We found more frames in use than requested.";
+ }
+
+ mFrames.swap(newRecords);
+
+ return true;
+}
+
+
UniqueFence HalCamera::requestNewFrame(sp<VirtualCamera> client,
const int64_t lastTimestamp) {
if (!mSyncSupported) {
diff --git a/evs/manager/1.1/HalCamera.h b/evs/manager/1.1/HalCamera.h
index b888add..970dc16 100644
--- a/evs/manager/1.1/HalCamera.h
+++ b/evs/manager/1.1/HalCamera.h
@@ -79,6 +79,8 @@
std::string getId() { return mId; }
Stream& getStreamConfig() { return mStreamConfig; }
bool changeFramesInFlight(int delta);
+ bool changeFramesInFlight(const hardware::hidl_vec<BufferDesc_1_1>& buffers,
+ int* delta);
UniqueFence requestNewFrame(sp<VirtualCamera> virtualCamera,
const int64_t timestamp);
diff --git a/evs/manager/1.1/VirtualCamera.cpp b/evs/manager/1.1/VirtualCamera.cpp
index 6e203aa..e9d7b3f 100644
--- a/evs/manager/1.1/VirtualCamera.cpp
+++ b/evs/manager/1.1/VirtualCamera.cpp
@@ -865,6 +865,34 @@
}
+Return<void>
+VirtualCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) {
+ if (mHalCamera.size() > 1) {
+ LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ auto pHwCamera = mHalCamera.begin()->second.promote();
+ if (pHwCamera == nullptr) {
+ LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ int delta = 0;
+ if (!pHwCamera->changeFramesInFlight(buffers, &delta)) {
+ LOG(ERROR) << "Failed to add extenral capture buffers.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ mFramesAllowed += delta;
+ _hidl_cb(EvsResult::OK, delta);
+ return {};
+}
+
} // namespace implementation
} // namespace V1_1
} // namespace evs
diff --git a/evs/manager/1.1/VirtualCamera.h b/evs/manager/1.1/VirtualCamera.h
index 63744d9..764d6c5 100644
--- a/evs/manager/1.1/VirtualCamera.h
+++ b/evs/manager/1.1/VirtualCamera.h
@@ -105,7 +105,8 @@
const hidl_vec<uint8_t>& opaqueValue) override;
Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) override;
-
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) override;
private:
diff --git a/evs/sampleDriver/EvsV4lCamera.cpp b/evs/sampleDriver/EvsV4lCamera.cpp
index eefad2a..fdb8937 100644
--- a/evs/sampleDriver/EvsV4lCamera.cpp
+++ b/evs/sampleDriver/EvsV4lCamera.cpp
@@ -449,6 +449,84 @@
}
+Return<void>
+EvsV4lCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) {
+ LOG(DEBUG) << __FUNCTION__;
+
+ // If we've been displaced by another owner of the camera, then we can't do anything else
+ if (!mVideo.isOpen()) {
+ LOG(WARNING) << "Ignoring a request add external buffers "
+ << "when camera has been lost.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, mFramesAllowed);
+ return {};
+ }
+
+ auto numBuffersToAdd = buffers.size();
+ if (numBuffersToAdd < 1) {
+ LOG(DEBUG) << "No buffers to add.";
+ _hidl_cb(EvsResult::OK, mFramesAllowed);
+ return {};
+ }
+
+ {
+ std::scoped_lock<std::mutex> lock(mAccessLock);
+
+ if (numBuffersToAdd > (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed)) {
+ numBuffersToAdd -= (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed);
+ LOG(WARNING) << "Exceed the limit on number of buffers. "
+ << numBuffersToAdd << " buffers will be added only.";
+ }
+
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ const auto before = mFramesAllowed;
+ for (auto i = 0; i < numBuffersToAdd; ++i) {
+ // TODO: reject if external buffer is configured differently.
+ auto& b = buffers[i];
+ const AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<const AHardwareBuffer_Desc *>(&b.buffer.description);
+
+ // Import a buffer to add
+ buffer_handle_t memHandle = nullptr;
+ status_t result = mapper.importBuffer(b.buffer.nativeHandle,
+ pDesc->width,
+ pDesc->height,
+ 1,
+ pDesc->format,
+ pDesc->usage,
+ pDesc->stride,
+ &memHandle);
+ if (result != android::NO_ERROR || !memHandle) {
+ LOG(WARNING) << "Failed to import a buffer " << b.bufferId;
+ continue;
+ }
+
+ auto stored = false;
+ for (auto&& rec : mBuffers) {
+ if (rec.handle == nullptr) {
+ // Use this existing entry
+ rec.handle = memHandle;
+ rec.inUse = false;
+
+ stored = true;
+ break;
+ }
+ }
+
+ if (!stored) {
+ // Add a BufferRecord wrapping this handle to our set of available buffers
+ mBuffers.emplace_back(memHandle);
+ }
+
+ ++mFramesAllowed;
+ }
+
+ _hidl_cb(EvsResult::OK, mFramesAllowed - before);
+ return {};
+ }
+}
+
+
EvsResult EvsV4lCamera::doneWithFrame_impl(const uint32_t bufferId,
const buffer_handle_t memHandle) {
std::lock_guard <std::mutex> lock(mAccessLock);
@@ -649,7 +727,7 @@
}
if (!readyForFrame) {
- // We need to return the vide buffer so it can capture a new frame
+ // We need to return the video buffer so it can capture a new frame
mVideo.markFrameConsumed();
} else {
// Assemble the buffer description we'll transmit below
@@ -675,10 +753,11 @@
// causes SEGV_MAPPER.
void *targetPixels = nullptr;
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- status_t result = mapper.lock(bufDesc_1_1.buffer.nativeHandle,
- GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
- android::Rect(pDesc->width, pDesc->height),
- (void **)&targetPixels);
+ status_t result =
+ mapper.lock(bufDesc_1_1.buffer.nativeHandle,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
+ android::Rect(pDesc->width, pDesc->height),
+ (void **)&targetPixels);
// If we failed to lock the pixel buffer, we're about to crash, but log it first
if (!targetPixels) {
@@ -740,6 +819,7 @@
// Since we didn't actually deliver it, mark the frame as available
std::lock_guard<std::mutex> lock(mAccessLock);
mBuffers[idx].inUse = false;
+
mFramesInUse--;
}
}
diff --git a/evs/sampleDriver/EvsV4lCamera.h b/evs/sampleDriver/EvsV4lCamera.h
index 3dc9f06..c5b15a9 100644
--- a/evs/sampleDriver/EvsV4lCamera.h
+++ b/evs/sampleDriver/EvsV4lCamera.h
@@ -24,8 +24,9 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <ui/GraphicBuffer.h>
-#include <thread>
#include <functional>
+#include <thread>
+#include <set>
#include "VideoCapture.h"
#include "ConfigManager.h"
@@ -85,6 +86,8 @@
const hidl_vec<uint8_t>& opaqueValue) override;
Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) override;
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) override;
static sp<EvsV4lCamera> Create(const char *deviceName);
static sp<EvsV4lCamera> Create(const char *deviceName,
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index eec31b3..047ce18 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -24,6 +24,7 @@
import android.car.ICar;
import android.car.cluster.renderer.IInstrumentClusterNavigation;
import android.car.user.CarUserManager;
+import android.car.user.CarUserManager.UserLifecycleEvent;
import android.car.userlib.CarUserManagerHelper;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -352,24 +353,15 @@
public void onUserLifecycleEvent(int eventType, long timestampMs, int fromUserId,
int toUserId) {
assertCallingFromSystemProcess();
- Log.i(TAG, "onUserLifecycleEvent(" + CarUserManager.lifecycleEventTypeToString(eventType)
- + ", " + toUserId + ")");
- mUserMetrics.onEvent(eventType, timestampMs, fromUserId, toUserId);
+ Log.i(TAG, "onUserLifecycleEvent("
+ + CarUserManager.lifecycleEventTypeToString(eventType) + ", " + toUserId + ")");
+ mCarUserService.onUserLifecycleEvent(new UserLifecycleEvent(eventType, toUserId));
if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING) {
- setUserLockStatus(toUserId);
- } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
- onSwitchUser(toUserId);
+ // TODO(b/145689885): CarMediaService should implement UserLifecycleListener,
+ // eliminiating the need for this check.
+ mCarMediaService.setUserLockStatus(toUserId, /* unlocked= */ true);
}
- }
-
- private void setUserLockStatus(int userId) {
- mCarUserService.setUserLockStatus(userId, /* unlocked= */ true);
- mCarMediaService.setUserLockStatus(userId, /* unlocked= */ true);
- }
-
- private void onSwitchUser(int userId) {
- Log.i(TAG, "Foreground user switched to " + userId);
- mCarUserService.onSwitchUser(userId);
+ mUserMetrics.onEvent(eventType, timestampMs, fromUserId, toUserId);
}
@Override
diff --git a/service/src/com/android/car/stats/CarStatsService.java b/service/src/com/android/car/stats/CarStatsService.java
index 41b7013..20b451c 100644
--- a/service/src/com/android/car/stats/CarStatsService.java
+++ b/service/src/com/android/car/stats/CarStatsService.java
@@ -159,6 +159,7 @@
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeInt(entry.getUid())
+ .addBooleanAnnotation(CarStatsLog.ANNOTATION_ID_IS_UID, true)
.writeInt(entry.getLayerType())
.writeInt(entry.getLayerChannel())
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index ec10818..cfd3364 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -693,26 +693,11 @@
}
}
- /**
- * Sets user lock/unlocking status. This is coming from system server through ICar binder call.
- *
- * @param userId User id whoes lock status is changed.
- * @param unlocked Unlocked (={@code true}) or locked (={@code false}).
- *
- * @deprecated TODO(b/151895715): method to be folded into onUserLifecycleEvent
- */
- @Deprecated
- public void setUserLockStatus(@UserIdInt int userId, boolean unlocked) {
- TimingsTraceLog t = new TimingsTraceLog(TAG_USER,
- Trace.TRACE_TAG_SYSTEM_SERVER);
- notifyUserLifecycleListeners(t,
+ private void unlockUser(@UserIdInt int userId) {
+ TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
+ notifyUserLifecycleListeners(
new UserLifecycleEvent(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING, userId));
-
- if (!unlocked) { // nothing else to do when it is locked back.
- return;
- }
-
- t.traceBegin("setUserLockStatus-UnlockTasks-" + userId);
+ t.traceBegin("UnlockTasks-" + userId);
ArrayList<Runnable> tasks = null;
synchronized (mLockUser) {
if (userId == UserHandle.USER_SYSTEM) {
@@ -720,7 +705,7 @@
updateDefaultUserRestriction();
tasks = new ArrayList<>(mUser0UnlockTasks);
mUser0UnlockTasks.clear();
- mUser0Unlocked = unlocked;
+ mUser0Unlocked = true;
}
} else { // none user0
Integer user = userId;
@@ -836,13 +821,82 @@
}
/**
- * Called when new foreground user started to boot.
- *
- * @param userId User id of new user.
- * @deprecated TODO(b/151895715): method to be folded into onUserLifecycleEvent
+ * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
*/
- @Deprecated
- public void onSwitchUser(@UserIdInt int userId) {
+ public void onUserLifecycleEvent(UserLifecycleEvent event) {
+ int userId = event.getUserId();
+ if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
+ onSwitchUser(userId);
+ } else if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING) {
+ unlockUser(userId);
+ }
+
+ // TODO(b/144120654): right now just the app listeners are running in the background so the
+ // CTS tests pass (as otherwise they might fail if a car service callback takes too long),
+ // but once we refactor the car service callback into lifecycle listeners, we should use a
+ // proper thread management (like a Threadpool / executor);
+
+ // Notify all user listeners
+ notifyUserLifecycleListeners(event);
+
+ // Notify all app listeners
+ notifyAppLifecycleListeners(event);
+ }
+
+ private void notifyAppLifecycleListeners(UserLifecycleEvent event) {
+ int listenersSize = mLifecycleListeners.size();
+ if (listenersSize == 0) {
+ Log.i(TAG_USER, "No app listener to be notified");
+ return;
+ }
+ new Thread(() -> {
+ // Must use a different TimingsTraceLog because it's another thread
+ TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
+ Log.i(TAG_USER, "Notifying " + listenersSize + " app listeners");
+ int userId = event.getUserId();
+ for (int i = 0; i < listenersSize; i++) {
+ int uid = mLifecycleListeners.keyAt(i);
+ IResultReceiver listener = mLifecycleListeners.valueAt(i);
+ t.traceBegin("notify-" + event.getEventType() + "-app-listener-" + uid);
+ Bundle data = new Bundle();
+ data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, event.getEventType());
+ // TODO(b/144120654): should pass currentId from CarServiceHelperService so it
+ // can set BUNDLE_PARAM_PREVIOUS_USER_ID (and unit test it)
+ if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
+ Log.d(TAG_USER, "Notifying listener for uid " + uid);
+ }
+ try {
+ listener.send(userId, data);
+ } catch (RemoteException e) {
+ Log.e(TAG_USER, "Error calling lifecycle listener", e);
+ } finally {
+ t.traceEnd();
+ }
+ }
+ }, "SwitchUser-" + event.getUserId() + "-Listeners").start();
+ }
+
+ private void notifyUserLifecycleListeners(UserLifecycleEvent event) {
+ TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
+ if (mUserLifecycleListeners.isEmpty()) {
+ Log.i(TAG_USER, "Not notifying internal UserLifecycleListeners");
+ return;
+ }
+ t.traceBegin("notifyInternalUserLifecycleListeners");
+ for (UserLifecycleListener listener : mUserLifecycleListeners) {
+ t.traceBegin("notify-" + event.getEventType() + "-listener-" + listener);
+ try {
+ listener.onEvent(event);
+ } catch (RuntimeException e) {
+ Log.e(TAG_USER,
+ "Exception raised when invoking onEvent for " + listener, e);
+ }
+ t.traceEnd();
+ }
+ t.traceEnd();
+ }
+
+ private void onSwitchUser(@UserIdInt int userId) {
Log.i(TAG_USER, "onSwitchUser() callback for user " + userId);
TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
t.traceBegin("onSwitchUser-" + userId);
@@ -857,63 +911,6 @@
setupPassengerUser();
startFirstPassenger(userId);
}
-
- // TODO(b/144120654): right now just the app listeners are running in the background so the
- // CTS tests pass (as otherwise they might fail if a car service callback takes too long),
- // but once we refactor the car service callback into lifecycle listeners, we should use a
- // proper thread management (like a Threadpool / executor);
-
- int listenersSize = mLifecycleListeners.size();
- if (listenersSize == 0) {
- Log.i(TAG_USER, "Not notifying app listeners");
- } else {
- new Thread(() -> {
- // Must use a different TimingsTraceLog because it's another thread
- TimingsTraceLog t2 = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
- Log.i(TAG_USER, "Notifying " + listenersSize + " listeners");
- for (int i = 0; i < listenersSize; i++) {
- int uid = mLifecycleListeners.keyAt(i);
- IResultReceiver listener = mLifecycleListeners.valueAt(i);
- t2.traceBegin("notify-listener-" + uid);
- Bundle data = new Bundle();
- data.putInt(CarUserManager.BUNDLE_PARAM_ACTION,
- CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING);
- // TODO(b/144120654): should pass currentId from CarServiceHelperService so it
- // can set BUNDLE_PARAM_PREVIOUS_USER_ID (and unit test it)
- if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
- Log.d(TAG_USER, "Notifying listener for uid " + uid);
- }
- try {
- listener.send(userId, data);
- } catch (RemoteException e) {
- Log.e(TAG_USER, "Error calling lifecycle listener", e);
- } finally {
- t2.traceEnd();
- }
- }
-
- }, "SwitchUser-" + userId + "-Listeners").start();
- }
-
- // TODO(b/145689885): not passing `from` parameter until it gets properly replaced
- // the expected Binder call.
- notifyUserLifecycleListeners(t,
- new UserLifecycleEvent(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, userId));
- }
-
- private void notifyUserLifecycleListeners(TimingsTraceLog t, UserLifecycleEvent event) {
- t.traceBegin("notifyInternalUserLifecycleListeners");
- for (UserLifecycleListener listener : mUserLifecycleListeners) {
- t.traceBegin("onEvent-" + listener.getClass().getSimpleName());
- try {
- listener.onEvent(event);
- } catch (RuntimeException e) {
- Log.e(TAG_USER,
- "Exception raised when invoking onEvent for " + listener, e);
- }
- t.traceEnd();
- }
- t.traceEnd();
}
/**
@@ -1186,4 +1183,4 @@
List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
}
-}
\ No newline at end of file
+}
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml b/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
index 0a329af..5c3bd12 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
@@ -79,14 +79,30 @@
android:id="@+id/sms_tel_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="+1-650-000-0000 "
- android:inputType="text" />
+ android:text="+1-650-000-0000, comma separated"
+ android:inputType="text"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
<Button
android:id="@+id/sms_new_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/sms_new_message_button"/>
+ <Button
+ android:id="@+id/mms_new_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/mms_new_message_button"/>
+ <Button
+ android:id="@+id/reset_message_counter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/reset_message_counter_button"/>
</LinearLayout>
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
index da2d341..00d73d6 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
@@ -257,7 +257,9 @@
<string name="sms_connect" translatable="false">Connect</string>
<string name="sms_disconnect" translatable="false">Disconnect</string>
<string name="sms_send_message" translatable="false">Send</string>
- <string name="sms_new_message_button" translatable="false">Send new message</string>
+ <string name="sms_new_message_button" translatable="false">Send new message (Short)</string>
+ <string name="mms_new_message_button" translatable="false">Send new message (Long)</string>
+ <string name="reset_message_counter_button" translatable="false">Reset message counter</string>
<string name="sms_notifications" translatable="false">Toggle Notifications</string>
<string name="sms_listing_button" translatable="false">List SMS</string>
<string name="sms_listing_label_folder" translatable="false">Folder</string>
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
index 2f2e9fe..d73f6e3 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
@@ -50,12 +50,53 @@
import com.google.android.car.kitchensink.R;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MapMceTestFragment extends Fragment {
- static final String MESSAGE_TO_SEND = "Im Busy Driving";
- static final String NEW_MESSAGE_TO_SEND = "This is new msg";
+ static final String REPLY_MESSAGE_TO_SEND = "I am currently driving.";
+ static final String NEW_MESSAGE_TO_SEND_SHORT = "This is a new message.";
+ static final String NEW_MESSAGE_TO_SEND_LONG = "Lorem ipsum dolor sit amet, consectetur "
+ + "adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna "
+ + "aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi "
+ + "ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in "
+ + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
+ + "occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim "
+ + "id est laborum.\n\nCurabitur pretium tincidunt lacus. Nulla gravida orci a odio. "
+ + "Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus "
+ + "magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis "
+ + "ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. "
+ + "Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt "
+ + "sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. "
+ + "Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, "
+ + "consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl "
+ + "adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque "
+ + "nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, "
+ + "laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, "
+ + "feugiat in, orci. In hac habitasse platea dictumst.\n\nLorem ipsum dolor sit "
+ + "amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et "
+ + "dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
+ + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
+ + "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. "
+ + "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia "
+ + "deserunt mollit anim id est laborum.\n\nCurabitur pretium tincidunt lacus. Nulla "
+ + "gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum "
+ + "elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh "
+ + "euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus "
+ + "a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod "
+ + "turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec "
+ + "fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, "
+ + "commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, "
+ + "felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis "
+ + "scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus "
+ + "quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, "
+ + "feugiat in, orci. In hac habitasse platea dictumst.";
+ private static final int SEND_NEW_SMS_SHORT = 1;
+ private static final int SEND_NEW_SMS_LONG = 2;
+ private static final int SEND_NEW_MMS_SHORT = 3;
+ private static final int SEND_NEW_MMS_LONG = 4;
+ private int mSendNewMsgCounter = 0;
private static final String TAG = "CAR.BLUETOOTH.KS";
private static final int SEND_SMS_PERMISSIONS_REQUEST = 1;
BluetoothMapClient mMapProfile;
@@ -86,7 +127,9 @@
Button reply = (Button) v.findViewById(R.id.reply);
Button checkMessages = (Button) v.findViewById(R.id.check_messages);
mBluetoothDevice = (TextView) v.findViewById(R.id.bluetoothDevice);
- Button sendNewMsg = (Button) v.findViewById(R.id.sms_new_message);
+ Button sendNewMsgShort = (Button) v.findViewById(R.id.sms_new_message);
+ Button sendNewMsgLong = (Button) v.findViewById(R.id.mms_new_message);
+ Button resetSendNewMsgCounter = (Button) v.findViewById(R.id.reset_message_counter);
mSmsTelNum = (EditText) v.findViewById(R.id.sms_tel_num);
mOriginator = (EditText) v.findViewById(R.id.messageOriginator);
mOriginatorDisplayName = (TextView) v.findViewById(R.id.messageOriginatorDisplayName);
@@ -114,18 +157,29 @@
@Override
public void onClick(View view) {
sendMessage(new Uri[]{Uri.parse(mOriginator.getText().toString())},
- MESSAGE_TO_SEND);
+ REPLY_MESSAGE_TO_SEND);
}
});
- sendNewMsg.setOnClickListener(new View.OnClickListener() {
+ sendNewMsgShort.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- String s = mSmsTelNum.getText().toString();
- Toast.makeText(getContext(), "sending msg to " + s, Toast.LENGTH_SHORT).show();
- Uri.Builder builder = new Uri.Builder();
- Uri uri = builder.appendPath(s).scheme(PhoneAccount.SCHEME_TEL).build();
- sendMessage(new Uri[]{uri}, NEW_MESSAGE_TO_SEND);
+ sendNewMsgOnClick(SEND_NEW_SMS_SHORT);
+ }
+ });
+
+ sendNewMsgLong.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ sendNewMsgOnClick(SEND_NEW_MMS_LONG);
+ }
+ });
+
+ resetSendNewMsgCounter.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mSendNewMsgCounter = 0;
+ Toast.makeText(getContext(), "Counter reset to zero.", Toast.LENGTH_SHORT).show();
}
});
@@ -212,6 +266,28 @@
}
}
+ private void sendNewMsgOnClick(int msgType) {
+ String messageToSend = "";
+ switch (msgType) {
+ case SEND_NEW_SMS_SHORT:
+ messageToSend = NEW_MESSAGE_TO_SEND_SHORT;
+ break;
+ case SEND_NEW_MMS_LONG:
+ messageToSend = NEW_MESSAGE_TO_SEND_LONG;
+ break;
+ }
+ String s = mSmsTelNum.getText().toString();
+ Toast.makeText(getContext(), "sending msg to " + s, Toast.LENGTH_SHORT).show();
+ HashSet<Uri> uris = new HashSet<Uri>();
+ Uri.Builder builder = new Uri.Builder();
+ for (String telNum : s.split(",")) {
+ uris.add(builder.path(telNum).scheme(PhoneAccount.SCHEME_TEL).build());
+ }
+ sendMessage(uris.toArray(new Uri[uris.size()]), Integer.toString(mSendNewMsgCounter)
+ + ": " + messageToSend);
+ mSendNewMsgCounter += 1;
+ }
+
private int getUploadingFeatureValue() {
synchronized (mLock) {
BluetoothDevice remoteDevice;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/packageinfo/PackageInfoFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/packageinfo/PackageInfoFragment.java
index a43c510..039cc8c 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/packageinfo/PackageInfoFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/packageinfo/PackageInfoFragment.java
@@ -59,6 +59,7 @@
private static final boolean DEBUG = true;
private static final int PACKAGE_FLAGS = PackageManager.GET_META_DATA
| PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES
+ | PackageManager.GET_PROVIDERS | PackageManager.GET_RECEIVERS
| PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES;
private static final List<String> IMPORTANT_PERMISSIONS = Arrays.asList(
"android.permission.INTERACT_ACROSS_USERS",
@@ -96,10 +97,7 @@
private void refreshPackages() {
List<PackageInfo> packages = new ArrayList<PackageInfo>();
try {
- packages = mPackageManager.getInstalledPackagesAsUser(PackageManager.GET_META_DATA
- | PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES
- | PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES,
- mUserToShow.id);
+ packages = mPackageManager.getInstalledPackagesAsUser(PACKAGE_FLAGS, mUserToShow.id);
if (DEBUG) {
Log.d(TAG, "total packages found: " + packages.size());
}
diff --git a/tests/OccupantAwarenessUxRestriction/Android.bp b/tests/OccupantAwarenessUxRestriction/Android.bp
deleted file mode 100644
index 0ee599a..0000000
--- a/tests/OccupantAwarenessUxRestriction/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-android_app {
- name: "OccupantAwarenessUxRestriction",
- platform_apis: true,
-
- srcs: ["src/**/*.java"],
-
- resource_dirs: ["res"],
-
- libs: [
- "android.car",
- ],
-
- static_libs: [
- "vehicle-hal-support-lib",
- "car-experimental-api-static-lib",
- "com.google.android.material_material",
- "androidx.appcompat_appcompat",
- "androidx-constraintlayout_constraintlayout",
- ],
-
- certificate: "platform",
-
- optimize: {
- enabled: false,
- },
-
- privileged: true,
-
- dex_preopt: {
- enabled: false,
- },
-
- product_variables: {
- pdk: {
- enabled: false,
- },
- },
-}
diff --git a/tests/OccupantAwarenessUxRestriction/AndroidManifest.xml b/tests/OccupantAwarenessUxRestriction/AndroidManifest.xml
deleted file mode 100644
index 3e90224..0000000
--- a/tests/OccupantAwarenessUxRestriction/AndroidManifest.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.car.uxr.oas"
- android:sharedUserId="android.uid.system">
-
- <uses-sdk android:minSdkVersion="28"/>
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
- <uses-permission android:name="android.car.permission.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE"/>
- <application
- android:allowBackup="true"
- android:icon="@mipmap/adam_icon">
- <activity
- android:name=".LaunchpadActivity"
- android:theme="@android:style/Theme.Black.NoTitleBar"
- android:label="UxRestrictionLauncher"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <service
- android:name=".OccupantAwarenessUxRestriction"
- android:exported="true"
- android:enabled="true">
- </service>
- <service
- android:name=".AttentionProvider"
- android:exported="true">
- </service>
- </application>
-</manifest>
diff --git a/tests/OccupantAwarenessUxRestriction/README.md b/tests/OccupantAwarenessUxRestriction/README.md
deleted file mode 100644
index 9e1a1d2..0000000
--- a/tests/OccupantAwarenessUxRestriction/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# The application monitors Occupant Awareness detections and based on attention
-
-# value of driver, it restricts user interaction.
-
-# Start the application using command -
-
-``` shell
-adb shell am start
-com.google.android.car.uxr.sample/com.google.android.car.uxr.sample.LaunchpadActivity
-```
-
-# Stop the application using command -
-
-``` shell
-adb shell am force-stop com.google.android.car.uxr.sample
-```
diff --git a/tests/OccupantAwarenessUxRestriction/res/drawable/attention_buffer_progress_bar.xml b/tests/OccupantAwarenessUxRestriction/res/drawable/attention_buffer_progress_bar.xml
deleted file mode 100644
index e7a8fd0..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/drawable/attention_buffer_progress_bar.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-<item android:id="@android:id/progress">
- <clip>
- <shape>
- <gradient
- android:startColor="#33FF33"
- android:endColor="#008000"
- android:angle="270"/>
- </shape>
- </clip>
-</item>
-</layer-list>
diff --git a/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_cyan.xml b/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_cyan.xml
deleted file mode 100644
index 0f5f079..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_cyan.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-<item android:id="@android:id/background">
- <shape>
- <corners android:radius="80dip"/>
- <solid android:color="#779d9e9d"/>
- </shape>
-</item>
-<item
- android:id="@android:id/progress">
- <clip>
- <shape>
- <corners android:radius="80dip"/>
- <solid android:color="#7707b4f9"/>
- </shape>
- </clip>
-</item>
-</layer-list>
diff --git a/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_green.xml b/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_green.xml
deleted file mode 100644
index 965a4a2..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/drawable/speedbump_progress_bar_green.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-<item android:id="@android:id/background">
- <shape>
- <corners android:radius="80dip"/>
- <solid android:color="#779d9e9d"/>
- </shape>
-</item>
-<item
- android:id="@android:id/progress">
- <clip>
- <shape>
- <corners android:radius="80dip"/>
- <solid android:color="#7733FF33"/>
- </shape>
- </clip>
-</item>
-</layer-list>
diff --git a/tests/OccupantAwarenessUxRestriction/res/layout-land/activity_launchpad.xml b/tests/OccupantAwarenessUxRestriction/res/layout-land/activity_launchpad.xml
deleted file mode 100644
index 1185067..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/layout-land/activity_launchpad.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".LaunchpadActivity">
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/tests/OccupantAwarenessUxRestriction/res/layout-land/view_ux_restriction.xml b/tests/OccupantAwarenessUxRestriction/res/layout-land/view_ux_restriction.xml
deleted file mode 100644
index 09dae9c..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/layout-land/view_ux_restriction.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:orientation="vertical"
- android:background="#D9000000"
- android:clickable="false"
- android:focusable="false">
- <ProgressBar
- android:id="@+id/pbDriverAttentionBuffer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/progressBarStyleHorizontal"
- android:progressDrawable="@drawable/attention_buffer_progress_bar"
- android:max="100"/>
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal">
- <ProgressBar
- android:id="@+id/pbSpeedBump"
- android:layout_width="600dp"
- android:layout_height="80dp"
- android:layout_marginTop="400dp"
- style="?android:attr/progressBarStyleHorizontal"
- android:progressDrawable="@drawable/speedbump_progress_bar_cyan"/>
- <TextView
- android:text="Focus on the road"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#000000"
- android:layout_alignLeft="@+id/pbSpeedBump"
- android:layout_alignRight="@+id/pbSpeedBump"
- android:layout_alignTop="@+id/pbSpeedBump"
- android:layout_alignBottom="@+id/pbSpeedBump"
- android:gravity="center"/>
- </RelativeLayout>
-</LinearLayout>
diff --git a/tests/OccupantAwarenessUxRestriction/res/layout-port/activity_launchpad.xml b/tests/OccupantAwarenessUxRestriction/res/layout-port/activity_launchpad.xml
deleted file mode 100644
index efbef43..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/layout-port/activity_launchpad.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".LaunchpadActivity">
-</android.support.constraint.ConstraintLayout>
diff --git a/tests/OccupantAwarenessUxRestriction/res/layout-port/view_ux_restriction.xml b/tests/OccupantAwarenessUxRestriction/res/layout-port/view_ux_restriction.xml
deleted file mode 100644
index 09dae9c..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/layout-port/view_ux_restriction.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:orientation="vertical"
- android:background="#D9000000"
- android:clickable="false"
- android:focusable="false">
- <ProgressBar
- android:id="@+id/pbDriverAttentionBuffer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/progressBarStyleHorizontal"
- android:progressDrawable="@drawable/attention_buffer_progress_bar"
- android:max="100"/>
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal">
- <ProgressBar
- android:id="@+id/pbSpeedBump"
- android:layout_width="600dp"
- android:layout_height="80dp"
- android:layout_marginTop="400dp"
- style="?android:attr/progressBarStyleHorizontal"
- android:progressDrawable="@drawable/speedbump_progress_bar_cyan"/>
- <TextView
- android:text="Focus on the road"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#000000"
- android:layout_alignLeft="@+id/pbSpeedBump"
- android:layout_alignRight="@+id/pbSpeedBump"
- android:layout_alignTop="@+id/pbSpeedBump"
- android:layout_alignBottom="@+id/pbSpeedBump"
- android:gravity="center"/>
- </RelativeLayout>
-</LinearLayout>
diff --git a/tests/OccupantAwarenessUxRestriction/res/mipmap-xxhdpi/adam_icon.png b/tests/OccupantAwarenessUxRestriction/res/mipmap-xxhdpi/adam_icon.png
deleted file mode 100644
index 85e28ca..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/mipmap-xxhdpi/adam_icon.png
+++ /dev/null
Binary files differ
diff --git a/tests/OccupantAwarenessUxRestriction/res/xml/device_filter.xml b/tests/OccupantAwarenessUxRestriction/res/xml/device_filter.xml
deleted file mode 100644
index 42cf9d5..0000000
--- a/tests/OccupantAwarenessUxRestriction/res/xml/device_filter.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-
-<resource>
- <!-- Intel realsense D435 camera in hex is 8086:0b07. The values below are in decimal -->
- <usb-device vendor-id="32902" product-id="2823"/>
-</resource>
diff --git a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/AttentionProvider.java b/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/AttentionProvider.java
deleted file mode 100644
index 54d69c2..0000000
--- a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/AttentionProvider.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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 com.google.android.car.uxr.oas;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.car.Car;
-import android.car.occupantawareness.OccupantAwarenessDetection;
-import android.car.occupantawareness.OccupantAwarenessManager;
-import android.car.occupantawareness.SystemStatusEvent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-public final class AttentionProvider extends Service {
- private static final String TAG = AttentionProvider.class.getSimpleName();
- private static final String NOTIFICATION_CHANNEL_ID = "adam_notification_channel_0";
- private static final CharSequence NOTIFICATION_CHANNEL_NAME = "adam_channel_name";
- private static final String NOTIFICATION_TITLE = "Android Automotive OS";
- private static final String NOTIFICATION_TEXT = "ADAM Service";
- private static final int NOTIFICATION_IMPORTANCE = NotificationManager.IMPORTANCE_NONE;
- private static final int NOTIFICATION_ID = 101;
- private static boolean sIsServiceRunning = false;
-
- private OccupantAwarenessManager mOasManager;
- private Car mCar;
-
- @Override
- public void onCreate() {
- Log.i(TAG, "onCreate()");
-
- Notification notification;
- NotificationChannel channel =
- new NotificationChannel(
- NOTIFICATION_CHANNEL_ID,
- NOTIFICATION_CHANNEL_NAME, NOTIFICATION_IMPORTANCE);
-
- NotificationManager notificationManager =
- (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.createNotificationChannel(channel);
-
- notification =
- new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
- .setSmallIcon(R.mipmap.adam_icon)
- .setCategory(Notification.CATEGORY_SERVICE)
- .setContentTitle(NOTIFICATION_TITLE)
- .setContentText(NOTIFICATION_TEXT)
- .build();
-
- startForeground(NOTIFICATION_ID, notification);
-
-
- mCar = Car.createCar(this);
- mOasManager = (OccupantAwarenessManager) mCar.getCarManager(Car.OCCUPANT_AWARENESS_SERVICE);
-
- if (mOasManager == null) {
- Log.e(TAG, "Occupant Awareness Manager is NULL. Check that occupant awareness "
- + "feature is enabled");
- } else {
- Log.i(TAG, "Connected to Occupant Awareness Manager");
-
- int caps =
- mOasManager.getCapabilityForRole(
- OccupantAwarenessDetection.VEHICLE_OCCUPANT_DRIVER);
- Log.i(TAG, "Driver capabilities: " + caps);
-
- Log.i(TAG, "Registering callback");
- mOasManager.registerChangeCallback(new CallbackHandler());
-
- Log.i(TAG, "Setup complete!");
- }
-
- UxRestriction.getInstance().enableUxRestriction(this);
- sIsServiceRunning = true;
- }
-
- public static synchronized Boolean getIsServiceRunning() {
- return sIsServiceRunning;
- }
-
- String systemToText(int statusCode) {
- switch (statusCode) {
- case SystemStatusEvent.SYSTEM_STATUS_READY:
- return "ready";
- case SystemStatusEvent.SYSTEM_STATUS_NOT_SUPPORTED:
- return "not supported";
- case SystemStatusEvent.SYSTEM_STATUS_NOT_READY:
- return "not ready";
- case SystemStatusEvent.SYSTEM_STATUS_SYSTEM_FAILURE:
- return "failure";
- default:
- return "unknown code";
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // We don't bind to anything.
- return null;
- }
-
- @Override
- public void onDestroy() {
- sIsServiceRunning = false;
- super.onDestroy();
- }
-
- private final class CallbackHandler extends OccupantAwarenessManager.ChangeCallback {
- @Override
- public void onDetectionEvent(OccupantAwarenessDetection event) {
- Log.i(TAG, "Got occupant awareness detection: " + event);
- if (event.driverMonitoringDetection != null) {
- UxRestriction.getInstance().setAttentionBufferValue(
- (int) (event.driverMonitoringDetection.gazeDurationMillis / 60));
- }
- }
-
- @Override
- public void onSystemStateChanged(SystemStatusEvent systemStatus) {
- Log.i(TAG, "Got occupant awareness system status: " + systemStatus + " ("
- + systemToText(systemStatus.systemStatus) + ").");
- }
- }
-}
diff --git a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/LaunchpadActivity.java b/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/LaunchpadActivity.java
deleted file mode 100644
index d4592cb..0000000
--- a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/LaunchpadActivity.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 com.google.android.car.uxr.oas;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * A blank activity whose sole purpose is to start the ADAM service(s), for ease of manual testing.
- */
-public class LaunchpadActivity extends Activity {
- private static final String TAG = LaunchpadActivity.class.getSimpleName();
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- Log.i(TAG, "onCreate()");
- super.onCreate(savedInstanceState);
- // setContentView(R.layout.activity_launchpad);
- this.startForegroundService(new Intent(this, AttentionProvider.class));
- onPause();
- }
-
- @Override
- protected void onDestroy() {
- Log.i(TAG, "onDestroy()");
- super.onDestroy();
- }
-}
diff --git a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/UxRestriction.java b/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/UxRestriction.java
deleted file mode 100644
index 9e660eb..0000000
--- a/tests/OccupantAwarenessUxRestriction/src/com/google/android/car/uxr/oas/UxRestriction.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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 com.google.android.car.uxr.oas;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.widget.ProgressBar;
-
-public final class UxRestriction {
-
- private static UxRestriction sUxRestriction;
-
- private static final String TAG = UxRestriction.class.getSimpleName();
- private static final int UXR_OVERLAY_VIEW_MIN_HEIGHT = 10;
- private static final int ATTENTION_BUFFER_THRESHOLD_RESTRICT_TOUCH = 0;
- private static final int ATTENTION_BUFFER_THRESHOLD_ENABLE_TOUCH = 40;
- private static final int SPEEDBUMP_THRESHOLD_TURN_GREEN =
- (int) (ATTENTION_BUFFER_THRESHOLD_ENABLE_TOUCH * 0.7);
- private static final int ATTENTION_BUFFER_ENABLED_BACKGROUND_COLOR = 0xffff0000;
- private static final int ATTENTION_BUFFER_DISABLED_BACKGROUND_COLOR = 0xff111111;
- private static final int ATTENTION_BUFFER_DEFAULT_VALUE = 50;
- private static final Handler sUiHandler = new Handler();
-
- private boolean mIsTouchRestricted;
- private WindowManager mWindowManager;
- private View mUxrOverlayView;
- private ProgressBar mPbDriverAttentionBuffer;
- private ProgressBar mPbSpeedBump;
- private LayoutParams mLayoutParamsEnableTouch;
- private LayoutParams mLayoutParamsDisableTouch;
-
- private Drawable mDrawableSpeedBumpCyan;
- private Drawable mDrawableSpeedBumpGreen;
-
- private UxRestriction() {
- // private constructor to prevent direct instantiation of this class.
- }
-
- public static UxRestriction getInstance() {
- if (sUxRestriction == null) {
- sUxRestriction = new UxRestriction();
- }
- return sUxRestriction;
- }
-
- public void enableUxRestriction(Context context) {
- Log.i(TAG, "onCreate()");
- mUxrOverlayView = LayoutInflater.from(context).inflate(R.layout.view_ux_restriction, null);
- mPbDriverAttentionBuffer = mUxrOverlayView.findViewById(R.id.pbDriverAttentionBuffer);
- mPbDriverAttentionBuffer.setBackgroundColor(ATTENTION_BUFFER_ENABLED_BACKGROUND_COLOR);
-
- mPbSpeedBump = mUxrOverlayView.findViewById(R.id.pbSpeedBump);
- mPbSpeedBump.setMax(ATTENTION_BUFFER_THRESHOLD_ENABLE_TOUCH);
- mDrawableSpeedBumpCyan =
- context.getResources().getDrawable(R.drawable.speedbump_progress_bar_cyan);
- mDrawableSpeedBumpGreen =
- context.getResources().getDrawable(R.drawable.speedbump_progress_bar_green);
-
- mLayoutParamsEnableTouch =
- new LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- UXR_OVERLAY_VIEW_MIN_HEIGHT,
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- mLayoutParamsEnableTouch.gravity = Gravity.TOP | Gravity.RIGHT;
-
- mLayoutParamsDisableTouch =
- new LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- mLayoutParamsDisableTouch.gravity = Gravity.TOP | Gravity.RIGHT;
-
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mWindowManager.addView(mUxrOverlayView, mLayoutParamsEnableTouch);
-
- setAttentionBufferValue(ATTENTION_BUFFER_DEFAULT_VALUE);
- }
-
- private void runOnUiThread(Runnable runnable) {
- sUiHandler.post(runnable);
- }
-
- private void restrictTouch() {
- if (!mIsTouchRestricted) {
- mIsTouchRestricted = true;
- runOnUiThread(() -> mWindowManager.updateViewLayout(
- mUxrOverlayView, mLayoutParamsDisableTouch));
- Log.i(TAG, "Touch disabled.");
- }
- }
-
- private void enableTouch() {
- if (mIsTouchRestricted) {
- mIsTouchRestricted = false;
- runOnUiThread(() -> mWindowManager.updateViewLayout(
- mUxrOverlayView, mLayoutParamsEnableTouch));
- Log.i(TAG, "Touch enabled.");
- }
- }
-
- public void setAttentionBufferValue(int value) {
- mPbDriverAttentionBuffer.post(() -> mPbDriverAttentionBuffer.setProgress(value));
- if (value <= ATTENTION_BUFFER_THRESHOLD_RESTRICT_TOUCH) {
- restrictTouch();
- } else if (value > ATTENTION_BUFFER_THRESHOLD_ENABLE_TOUCH) {
- enableTouch();
- }
-
- if (value <= ATTENTION_BUFFER_THRESHOLD_ENABLE_TOUCH) {
- mPbSpeedBump.post(() -> mPbSpeedBump.setProgress(value));
- if (value > SPEEDBUMP_THRESHOLD_TURN_GREEN) {
- mPbSpeedBump.post(() -> mPbSpeedBump.setProgressDrawable(mDrawableSpeedBumpGreen));
- } else {
- mPbSpeedBump.post(() -> mPbSpeedBump.setProgressDrawable(mDrawableSpeedBumpCyan));
- }
- }
- }
-
- public void disableUxRestriction() {
- if (mUxrOverlayView != null) {
- mWindowManager.removeView(mUxrOverlayView);
- }
- }
-
- public void destroy() {
- disableUxRestriction();
- }
-}
diff --git a/tests/carservice_unit_test/src/com/android/car/pm/VendorServiceControllerTest.java b/tests/carservice_unit_test/src/com/android/car/pm/VendorServiceControllerTest.java
index 01e22b7..450ae93 100644
--- a/tests/carservice_unit_test/src/com/android/car/pm/VendorServiceControllerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/pm/VendorServiceControllerTest.java
@@ -28,6 +28,8 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
+import android.car.user.CarUserManager;
+import android.car.user.CarUserManager.UserLifecycleEvent;
import android.car.userlib.CarUserManagerHelper;
import android.content.ComponentName;
import android.content.Context;
@@ -146,8 +148,9 @@
// Unlock system user
mockUserUnlock(UserHandle.USER_SYSTEM);
- runOnMainThreadAndWaitForIdle(() -> mCarUserService.setUserLockStatus(
- UserHandle.USER_SYSTEM, true));
+ runOnMainThreadAndWaitForIdle(() -> mCarUserService.onUserLifecycleEvent(
+ new UserLifecycleEvent(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING,
+ UserHandle.USER_SYSTEM)));
mContext.assertStartedService(SERVICE_START_SYSTEM_UNLOCKED);
mContext.verifyNoMoreServiceLaunches();
@@ -161,7 +164,10 @@
// Switch user to foreground
mockGetCurrentUser(FG_USER_ID);
- runOnMainThreadAndWaitForIdle(() -> mCarUserService.onSwitchUser(FG_USER_ID));
+ when(ActivityManager.getCurrentUser()).thenReturn(FG_USER_ID);
+ runOnMainThreadAndWaitForIdle(() -> mCarUserService.onUserLifecycleEvent(
+ new UserLifecycleEvent(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING,
+ FG_USER_ID)));
// Expect only services with ASAP trigger to be started
mContext.assertBoundService(SERVICE_BIND_ALL_USERS_ASAP);
@@ -169,7 +175,9 @@
// Unlock foreground user
mockUserUnlock(FG_USER_ID);
- runOnMainThreadAndWaitForIdle(() -> mCarUserService.setUserLockStatus(FG_USER_ID, true));
+ runOnMainThreadAndWaitForIdle(() -> mCarUserService.onUserLifecycleEvent(
+ new UserLifecycleEvent(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING,
+ FG_USER_ID)));
mContext.assertBoundService(SERVICE_BIND_FG_USER_UNLOCKED);
mContext.verifyNoMoreServiceLaunches();
diff --git a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
index eebcd29..36136f5 100644
--- a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
@@ -206,7 +206,7 @@
@Test
public void testDoesNotSetSystemUserRestrictions_IfRestrictionsAlreadySet() {
putSettingsInt(CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
verify(mMockedUserManager, never())
.setUserRestriction(
UserManager.DISALLOW_MODIFY_ACCOUNTS,
@@ -233,7 +233,7 @@
// Act
int anyNewUserId = 11;
- mCarUserService.onSwitchUser(anyNewUserId);
+ onUserSwitching(anyNewUserId);
// Verify
verifyListenerOnEventInvoked(anyNewUserId,
@@ -254,7 +254,7 @@
// Act
int anyNewUserId = 11;
- mCarUserService.onSwitchUser(anyNewUserId);
+ onUserSwitching(anyNewUserId);
// Verify
verifyListenerOnEventInvoked(anyNewUserId,
@@ -274,7 +274,7 @@
*/
@Test
public void testDisableLocationForHeadlessSystemUserOnFirstRun() {
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
verify(mLocationManager).setLocationEnabledForUser(
/* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
}
@@ -289,7 +289,7 @@
NO_USER_INFO_FLAGS);
doReturn(persistentUser).when(mMockedUserManager).getUserInfo(lastActiveUserId);
- mCarUserService.onSwitchUser(lastActiveUserId);
+ onUserSwitching(lastActiveUserId);
verify(mMockedCarUserManagerHelper).setLastActiveUser(lastActiveUserId);
}
@@ -299,7 +299,7 @@
*/
@Test
public void testInitializeGuestRestrictions_IfNotAlreadySet() {
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
assertThat(getSettingsInt(CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET)).isEqualTo(1);
}
@@ -309,14 +309,14 @@
@Test
public void test_DoesNotInitializeGuestRestrictions_IfAlreadySet() {
putSettingsInt(CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
verify(mMockedUserManager, never()).setDefaultGuestRestrictions(any(Bundle.class));
}
@Test
public void testRunOnUser0UnlockImmediate() {
mUser0TaskExecuted = false;
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
mCarUserService.runOnUser0Unlock(() -> {
mUser0TaskExecuted = true;
});
@@ -330,7 +330,7 @@
mUser0TaskExecuted = true;
});
assertFalse(mUser0TaskExecuted);
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
assertTrue(mUser0TaskExecuted);
}
@@ -359,35 +359,31 @@
doReturn(user5Info).when(mMockedUserManager).getUserInfo(user5);
doReturn(user1).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
// user 0 should never go to that list.
assertTrue(mCarUserService.getBackgroundUsersToRestart().isEmpty());
- mCarUserService.setUserLockStatus(user1, true);
+ sendUserUnlockingEvent(user1);
assertEquals(new Integer[]{user1},
mCarUserService.getBackgroundUsersToRestart().toArray());
// user 2 background, ignore in restart list
- mCarUserService.setUserLockStatus(user2, true);
- mCarUserService.setUserLockStatus(user1, false);
+ sendUserUnlockingEvent(user2);
assertEquals(new Integer[]{user1},
mCarUserService.getBackgroundUsersToRestart().toArray());
doReturn(user3).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(user3, true);
- mCarUserService.setUserLockStatus(user2, false);
+ sendUserUnlockingEvent(user3);
assertEquals(new Integer[]{user3, user1},
mCarUserService.getBackgroundUsersToRestart().toArray());
doReturn(user4Guest).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(user4Guest, true);
- mCarUserService.setUserLockStatus(user3, false);
+ sendUserUnlockingEvent(user4Guest);
assertEquals(new Integer[]{user3, user1},
mCarUserService.getBackgroundUsersToRestart().toArray());
doReturn(user5).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(user5, true);
- mCarUserService.setUserLockStatus(user4Guest, false);
+ sendUserUnlockingEvent(user5);
assertEquals(new Integer[]{user5, user3},
mCarUserService.getBackgroundUsersToRestart().toArray());
}
@@ -410,14 +406,13 @@
doReturn(user3Info).when(mMockedUserManager).getUserInfo(user3);
doReturn(user1).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(UserHandle.USER_SYSTEM, true);
- mCarUserService.setUserLockStatus(user1, true);
+ sendUserUnlockingEvent(UserHandle.USER_SYSTEM);
+ sendUserUnlockingEvent(user1);
doReturn(user2).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(user2, true);
- mCarUserService.setUserLockStatus(user1, false);
+ sendUserUnlockingEvent(user2);
+ sendUserUnlockingEvent(user1);
doReturn(user3).when(() -> ActivityManager.getCurrentUser());
- mCarUserService.setUserLockStatus(user3, true);
- mCarUserService.setUserLockStatus(user2, false);
+ sendUserUnlockingEvent(user3);
assertEquals(new Integer[]{user3, user2},
mCarUserService.getBackgroundUsersToRestart().toArray());
@@ -427,7 +422,7 @@
null, null, null);
assertEquals(new Integer[]{user2},
mCarUserService.startAllBackgroundUsers().toArray());
- mCarUserService.setUserLockStatus(user2, true);
+ sendUserUnlockingEvent(user2);
assertEquals(new Integer[]{user3, user2},
mCarUserService.getBackgroundUsersToRestart().toArray());
@@ -438,7 +433,6 @@
assertTrue(mCarUserService.stopBackgroundUser(user2));
assertEquals(new Integer[]{user3, user2},
mCarUserService.getBackgroundUsersToRestart().toArray());
- mCarUserService.setUserLockStatus(user2, false);
assertEquals(new Integer[]{user3, user2},
mCarUserService.getBackgroundUsersToRestart().toArray());
}
@@ -965,28 +959,28 @@
int actualAction = resultData.getInt(CarUserService.BUNDLE_INITIAL_INFO_ACTION);
assertWithMessage("wrong request type on bundle extra %s",
CarUserService.BUNDLE_INITIAL_INFO_ACTION).that(actualAction)
- .isEqualTo(expectedAction);
+ .isEqualTo(expectedAction);
}
private void assertSwitchUserStatus(@NonNull Bundle resultData, int expectedStatus) {
int actualStatus = resultData.getInt(CarUserManager.BUNDLE_USER_SWITCH_STATUS);
assertWithMessage("wrong status on bundle extra %s",
CarUserManager.BUNDLE_USER_SWITCH_STATUS).that(actualStatus)
- .isEqualTo(expectedStatus);
+ .isEqualTo(expectedStatus);
}
private void assertSwitchUserMessageType(@NonNull Bundle resultData, int expectedType) {
int actualType = resultData.getInt(CarUserManager.BUNDLE_USER_SWITCH_MSG_TYPE);
assertWithMessage("wrong message type on bundle extra %s",
CarUserManager.BUNDLE_USER_SWITCH_MSG_TYPE).that(actualType)
- .isEqualTo(expectedType);
+ .isEqualTo(expectedType);
}
private void assertSwitchUserErrorMessage(@NonNull Bundle resultData, String expectedMsg) {
String actualMsg = resultData.getString(CarUserManager.BUNDLE_USER_SWITCH_ERROR_MSG);
assertWithMessage("wrong error message on bundle extra %s",
CarUserManager.BUNDLE_USER_SWITCH_ERROR_MSG).that(actualMsg)
- .isEqualTo(expectedMsg);
+ .isEqualTo(expectedMsg);
}
static final class FakeCarOccupantZoneService {
@@ -1031,7 +1025,6 @@
}
}
-
// TODO(b/148403316): Refactor to use common fake settings provider
private void mockSettingsGlobal() {
when(Settings.Global.putInt(any(), eq(CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET),
@@ -1056,6 +1049,16 @@
key, /* default= */ 0);
}
+ private void sendUserUnlockingEvent(int userId) {
+ mCarUserService.onUserLifecycleEvent(new UserLifecycleEvent(
+ CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING, userId));
+ }
+
+ private void onUserSwitching(int userId) {
+ mCarUserService.onUserLifecycleEvent(new UserLifecycleEvent(
+ CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, userId));
+ }
+
// TODO(b/149099817): move stuff below to common code
/**
diff --git a/watchdog/sepolicy/private/carwatchdog.te b/watchdog/sepolicy/private/carwatchdog.te
index 2e7cc9d..28473b0 100644
--- a/watchdog/sepolicy/private/carwatchdog.te
+++ b/watchdog/sepolicy/private/carwatchdog.te
@@ -1,5 +1,6 @@
# Car watchdog server
typeattribute carwatchdogd coredomain;
+typeattribute carwatchdogd mlstrustedsubject;
type carwatchdogd_exec, exec_type, file_type, system_file_type;
@@ -8,6 +9,9 @@
binder_use(carwatchdogd)
binder_service(carwatchdogd)
+# Scan through /proc/pid for all processes
+r_dir_file(carwatchdogd, domain)
+
# Read /proc/uid_io/stats
allow carwatchdogd proc_uid_io_stats:file r_file_perms;
diff --git a/watchdog/server/Android.bp b/watchdog/server/Android.bp
index 8f5c452..ee301db 100644
--- a/watchdog/server/Android.bp
+++ b/watchdog/server/Android.bp
@@ -56,6 +56,9 @@
"src/ProcStat.cpp",
"src/UidIoStats.cpp",
],
+ whole_static_libs: [
+ "libwatchdog_properties",
+ ],
export_include_dirs: [
"src",
],
diff --git a/watchdog/server/carwatchdogd.rc b/watchdog/server/carwatchdogd.rc
index 3220b90..b7027d7 100644
--- a/watchdog/server/carwatchdogd.rc
+++ b/watchdog/server/carwatchdogd.rc
@@ -12,7 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+on early-init
+ # Number of top stats per category
+ setprop ro.carwatchdog.top_n_stats_per_category 5
+
+ # Number of top stats per sub-category
+ setprop ro.carwatchdog.top_n_stats_per_subcategory 3
+
+ # Below intervals are in seconds
+ setprop ro.carwatchdog.boottime_collection_interval 1
+ setprop ro.carwatchdog.periodic_collection_interval 10
+
+ # Cache size for the periodically collected records
+ setprop ro.carwatchdog.periodic_collection_buffer_size 180
+
service carwatchdogd /system/bin/carwatchdogd
class core
user system
- group system
+ group system readproc
diff --git a/watchdog/server/src/IoPerfCollection.cpp b/watchdog/server/src/IoPerfCollection.cpp
index bae5766..c4f0864 100644
--- a/watchdog/server/src/IoPerfCollection.cpp
+++ b/watchdog/server/src/IoPerfCollection.cpp
@@ -18,6 +18,7 @@
#include "IoPerfCollection.h"
+#include <WatchdogProperties.sysprop.h>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
@@ -54,6 +55,20 @@
namespace {
+const int32_t kDefaultTopNStatsPerCategory = 5;
+const int32_t kDefaultTopNStatsPerSubcategory = 3;
+const std::chrono::seconds kDefaultBoottimeCollectionInterval = 1s;
+const std::chrono::seconds kDefaultPeriodicCollectionInterval = 10s;
+// Number of periodic collection perf data snapshots to cache in memory.
+const int32_t kDefaultPeriodicCollectionBufferSize = 180;
+
+// Minimum collection interval between subsequent collections.
+const std::chrono::nanoseconds kMinCollectionInterval = 1s;
+
+// Default values for the custom collection interval and max_duration.
+const std::chrono::nanoseconds kCustomCollectionInterval = 10s;
+const std::chrono::nanoseconds kCustomCollectionDuration = 30min;
+
const std::string kDumpMajorDelimiter = std::string(100, '-') + "\n";
double percentage(uint64_t numer, uint64_t denom) {
@@ -219,20 +234,30 @@
return Error(INVALID_OPERATION)
<< "Cannot start I/O performance collection more than once";
}
-
- // TODO(b/148489461): Once |kTopNStatsPerCategory|, |kBoottimeCollectionInterval| and
- // |kPeriodicCollectionInterval| constants are moved to read-only persistent properties,
- // read and store them in the collection infos.
-
+ mTopNStatsPerCategory = static_cast<int>(
+ sysprop::topNStatsPerCategory().value_or(kDefaultTopNStatsPerCategory));
+ mTopNStatsPerSubcategory = static_cast<int>(
+ sysprop::topNStatsPerSubcategory().value_or(kDefaultTopNStatsPerSubcategory));
+ std::chrono::nanoseconds boottimeCollectionInterval =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::seconds(sysprop::boottimeCollectionInterval().value_or(
+ kDefaultBoottimeCollectionInterval.count())));
+ std::chrono::nanoseconds periodicCollectionInterval =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::seconds(sysprop::periodicCollectionInterval().value_or(
+ kDefaultPeriodicCollectionInterval.count())));
+ size_t periodicCollectionBufferSize =
+ static_cast<size_t>(sysprop::periodicCollectionBufferSize().value_or(
+ kDefaultPeriodicCollectionBufferSize));
mBoottimeCollection = {
- .interval = kBoottimeCollectionInterval,
+ .interval = boottimeCollectionInterval,
.maxCacheSize = std::numeric_limits<std::size_t>::max(),
.lastCollectionUptime = 0,
.records = {},
};
mPeriodicCollection = {
- .interval = kPeriodicCollectionInterval,
- .maxCacheSize = kPeriodicCollectionBufferSize,
+ .interval = periodicCollectionInterval,
+ .maxCacheSize = periodicCollectionBufferSize,
.lastCollectionUptime = 0,
.records = {},
};
@@ -646,7 +671,7 @@
for (const auto& usage : topNReads) {
if (usage->ios.isZero()) {
// End of non-zero usage records. This case occurs when the number of UIDs with active
- // I/O operations is < |kTopNStatsPerCategory|.
+ // I/O operations is < |ro.carwatchdog.top_n_stats_per_category|.
break;
}
UidIoPerfData::Stats stats = {
@@ -666,7 +691,7 @@
for (const auto& usage : topNWrites) {
if (usage->ios.isZero()) {
// End of non-zero usage records. This case occurs when the number of UIDs with active
- // I/O operations is < |kTopNStatsPerCategory|.
+ // I/O operations is < |ro.carwatchdog.top_n_stats_per_category|.
break;
}
UidIoPerfData::Stats stats = {
@@ -760,7 +785,7 @@
for (const auto& it : topNIoBlockedUids) {
if (it->ioBlockedTasksCnt == 0) {
// End of non-zero elements. This case occurs when the number of UIDs with I/O blocked
- // processes is < |kTopNStatsPerCategory|.
+ // processes is < |ro.carwatchdog.top_n_stats_per_category|.
break;
}
ProcessIoPerfData::Stats stats = {
@@ -777,7 +802,7 @@
for (const auto& it : topNMajorFaults) {
if (it->majorFaults == 0) {
// End of non-zero elements. This case occurs when the number of UIDs with major faults
- // is < |kTopNStatsPerCategory|.
+ // is < |ro.carwatchdog.top_n_stats_per_category|.
break;
}
ProcessIoPerfData::Stats stats = {
diff --git a/watchdog/server/src/IoPerfCollection.h b/watchdog/server/src/IoPerfCollection.h
index 7a242d9..4753600 100644
--- a/watchdog/server/src/IoPerfCollection.h
+++ b/watchdog/server/src/IoPerfCollection.h
@@ -45,21 +45,6 @@
namespace automotive {
namespace watchdog {
-// TODO(b/148489461): Replace the below constants (except kCustomCollection* and
-// kMinCollectionInterval constants) with read-only persistent properties.
-const int kTopNStatsPerCategory = 5;
-const std::chrono::nanoseconds kBoottimeCollectionInterval = 1s;
-const std::chrono::nanoseconds kPeriodicCollectionInterval = 10s;
-// Number of periodic collection perf data snapshots to cache in memory.
-const size_t kPeriodicCollectionBufferSize = 180;
-
-// Minimum collection interval between subsequent collections.
-const std::chrono::nanoseconds kMinCollectionInterval = 1s;
-
-// Default values for the custom collection interval and max_duration.
-const std::chrono::nanoseconds kCustomCollectionInterval = 10s;
-const std::chrono::nanoseconds kCustomCollectionDuration = 30min;
-
constexpr const char* kStartCustomCollectionFlag = "--start_io";
constexpr const char* kEndCustomCollectionFlag = "--stop_io";
constexpr const char* kIntervalFlag = "--interval";
@@ -163,7 +148,6 @@
class IoPerfCollection : public MessageHandler {
public:
IoPerfCollection() :
- mTopNStatsPerCategory(kTopNStatsPerCategory),
mHandlerLooper(new LooperWrapper()),
mBoottimeCollection({}),
mPeriodicCollection({}),
@@ -208,9 +192,8 @@
// |maxDuration| is reached, the looper receives a message to end the collection, discards the
// collected data, and starts the periodic collection. This is needed to ensure the custom
// collection doesn't run forever when a subsequent |endCustomCollection| call is not received.
- android::base::Result<void> startCustomCollection(
- std::chrono::nanoseconds interval = kCustomCollectionInterval,
- std::chrono::nanoseconds maxDuration = kCustomCollectionDuration);
+ android::base::Result<void> startCustomCollection(std::chrono::nanoseconds interval,
+ std::chrono::nanoseconds maxDuration);
// Ends the current custom collection, generates a dump, sends message to looper to start the
// periodic collection, and returns immediately. Returns an error when there is no custom
@@ -244,8 +227,12 @@
// Retrieves package manager from the default service manager.
android::base::Result<void> retrievePackageManager();
+ // Top N per-UID stats per category.
int mTopNStatsPerCategory;
+ // Top N per-process stats per subcategory.
+ int mTopNStatsPerSubcategory;
+
// Thread on which the actual collection happens.
std::thread mCollectionThread;
@@ -260,7 +247,7 @@
CollectionInfo mBoottimeCollection GUARDED_BY(mMutex);
// Info for the |CollectionEvent::PERIODIC| collection event. The cache size is limited by
- // |kPeriodicCollectionBufferSize|.
+ // |ro.carwatchdog.periodic_collection_buffer_size|.
CollectionInfo mPeriodicCollection GUARDED_BY(mMutex);
// Info for the |CollectionEvent::CUSTOM| collection event. The info is cleared at the end of
diff --git a/watchdog/server/sysprop/Android.bp b/watchdog/server/sysprop/Android.bp
new file mode 100644
index 0000000..a3c507a
--- /dev/null
+++ b/watchdog/server/sysprop/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+sysprop_library {
+ name: "libwatchdog_properties",
+ srcs: ["*.sysprop"],
+ property_owner: "Platform",
+ api_packages: ["android.sysprop"],
+ recovery_available: true,
+}
diff --git a/watchdog/server/sysprop/WatchdogProperties.sysprop b/watchdog/server/sysprop/WatchdogProperties.sysprop
new file mode 100644
index 0000000..3a4b21a
--- /dev/null
+++ b/watchdog/server/sysprop/WatchdogProperties.sysprop
@@ -0,0 +1,61 @@
+# 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.
+
+module: "android.automotive.watchdog.sysprop"
+owner: Platform
+
+# Top N per-UID statistics/category collected by the performance data collector.
+prop {
+ api_name: "topNStatsPerCategory"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "ro.carwatchdog.top_n_stats_per_category"
+}
+
+# Top N per-process statistics/category collected by the performance data collector.
+prop {
+ api_name: "topNStatsPerSubcategory"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "ro.carwatchdog.top_n_stats_per_subcategory"
+}
+
+# Interval in seconds between consecutive boot-time performance data collections.
+prop {
+ api_name: "boottimeCollectionInterval"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "ro.carwatchdog.boottime_collection_interval"
+}
+
+# Interval in seconds between consecutive periodic performance data collections.
+prop {
+ api_name: "periodicCollectionInterval"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "ro.carwatchdog.periodic_collection_interval"
+}
+
+# Maximum number of periodically collected records to be cached in memory.
+prop {
+ api_name: "periodicCollectionBufferSize"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "ro.carwatchdog.periodic_collection_buffer_size"
+}
diff --git a/watchdog/server/sysprop/api/libwatchdog_properties-current.txt b/watchdog/server/sysprop/api/libwatchdog_properties-current.txt
new file mode 100644
index 0000000..ab59538
--- /dev/null
+++ b/watchdog/server/sysprop/api/libwatchdog_properties-current.txt
@@ -0,0 +1,33 @@
+props {
+ module: "android.automotive.watchdog.sysprop"
+ prop {
+ api_name: "boottimeCollectionInterval"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.boottime_collection_interval"
+ }
+ prop {
+ api_name: "periodicCollectionBufferSize"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.periodic_collection_buffer_size"
+ }
+ prop {
+ api_name: "periodicCollectionInterval"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.periodic_collection_interval"
+ }
+ prop {
+ api_name: "topNStatsPerCategory"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.top_n_stats_per_category"
+ }
+ prop {
+ api_name: "topNStatsPerSubcategory"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.top_n_stats_per_subcategory"
+ }
+}
diff --git a/watchdog/server/sysprop/api/libwatchdog_properties-latest.txt b/watchdog/server/sysprop/api/libwatchdog_properties-latest.txt
new file mode 100644
index 0000000..ab59538
--- /dev/null
+++ b/watchdog/server/sysprop/api/libwatchdog_properties-latest.txt
@@ -0,0 +1,33 @@
+props {
+ module: "android.automotive.watchdog.sysprop"
+ prop {
+ api_name: "boottimeCollectionInterval"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.boottime_collection_interval"
+ }
+ prop {
+ api_name: "periodicCollectionBufferSize"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.periodic_collection_buffer_size"
+ }
+ prop {
+ api_name: "periodicCollectionInterval"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.periodic_collection_interval"
+ }
+ prop {
+ api_name: "topNStatsPerCategory"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.top_n_stats_per_category"
+ }
+ prop {
+ api_name: "topNStatsPerSubcategory"
+ type: Integer
+ scope: Internal
+ prop_name: "ro.carwatchdog.top_n_stats_per_subcategory"
+ }
+}
diff --git a/watchdog/server/tests/IoPerfCollectionTest.cpp b/watchdog/server/tests/IoPerfCollectionTest.cpp
index 580de6e..47433cd 100644
--- a/watchdog/server/tests/IoPerfCollectionTest.cpp
+++ b/watchdog/server/tests/IoPerfCollectionTest.cpp
@@ -16,6 +16,7 @@
#include "IoPerfCollection.h"
+#include <WatchdogProperties.sysprop.h>
#include <android-base/file.h>
#include <cutils/android_filesystem_config.h>
@@ -172,6 +173,25 @@
ASSERT_TRUE(collector->mCollectionThread.joinable()) << "Collection thread not created";
ASSERT_FALSE(collector->start())
<< "No error returned when collector was started more than once";
+ ASSERT_TRUE(sysprop::topNStatsPerCategory().has_value());
+ ASSERT_EQ(collector->mTopNStatsPerCategory, sysprop::topNStatsPerCategory().value());
+
+ ASSERT_TRUE(sysprop::boottimeCollectionInterval().has_value());
+ ASSERT_EQ(std::chrono::duration_cast<std::chrono::seconds>(
+ collector->mBoottimeCollection.interval)
+ .count(),
+ sysprop::boottimeCollectionInterval().value());
+
+ ASSERT_TRUE(sysprop::topNStatsPerCategory().has_value());
+ ASSERT_EQ(std::chrono::duration_cast<std::chrono::seconds>(
+ collector->mPeriodicCollection.interval)
+ .count(),
+ sysprop::periodicCollectionInterval().value());
+
+ ASSERT_TRUE(sysprop::periodicCollectionBufferSize().has_value());
+ ASSERT_EQ(collector->mPeriodicCollection.maxCacheSize,
+ sysprop::periodicCollectionBufferSize().value());
+
collector->terminate();
ASSERT_FALSE(collector->mCollectionThread.joinable()) << "Collection thread did not terminate";
}
@@ -1198,6 +1218,7 @@
ASSERT_TRUE(ret) << "Failed to populate proc pid dir: " << ret.error();
IoPerfCollection collector;
+ collector.mTopNStatsPerCategory = 5;
collector.mProcPidStat = new ProcPidStat(prodDir.path);
struct ProcessIoPerfData actualProcessIoPerfData = {};
ret = collector.collectProcessIoPerfDataLocked(&actualProcessIoPerfData);