Don't use IPC in isolateProcess
Fixes: 74395652
Test: hwuiunit passes in 'shell stop' state (pseudo-isolated process),
manually checked non-isolated processes still have working vsync
via systrace of RT animations demo
Change-Id: I630ea011dc7eb2efa265b25673d3304b3b2510d3
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8dd0f42..99bcdb9f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5652,6 +5652,7 @@
// Allow application-generated systrace messages if we're debuggable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
+ ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
if (isAppDebuggable && data.enableBinderTracking) {
Binder.enableTracing();
}
@@ -5710,6 +5711,8 @@
} finally {
StrictMode.setThreadPolicyMask(oldMask);
}
+ } else {
+ ThreadedRenderer.setIsolatedProcess(true);
}
// If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8d076f7..5eb7e9c 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -20,13 +20,11 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedVectorDrawable;
-import android.os.Build;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -936,6 +934,20 @@
nSetHighContrastText(highContrastText);
}
+ /**
+ * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+ */
+ public static void setIsolatedProcess(boolean isIsolated) {
+ nSetIsolatedProcess(isIsolated);
+ }
+
+ /**
+ * If set extra graphics debugging abilities will be enabled such as dumping skp
+ */
+ public static void setDebuggingEnabled(boolean enable) {
+ nSetDebuggingEnabled(enable);
+ }
+
@Override
protected void finalize() throws Throwable {
try {
@@ -1071,10 +1083,6 @@
initSched(renderProxy);
if (mAppContext != null) {
- final boolean appDebuggable =
- (mAppContext.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)
- != 0;
- nSetDebuggingEnabled(appDebuggable || Build.IS_DEBUGGABLE);
initGraphicsStats();
}
}
@@ -1204,4 +1212,5 @@
// For temporary experimentation b/66945974
private static native void nHackySetRTAnimationsEnabled(boolean enabled);
private static native void nSetDebuggingEnabled(boolean enabled);
+ private static native void nSetIsolatedProcess(boolean enabled);
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index b614c89..451f278 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -988,6 +988,11 @@
Properties::debuggingEnabled = enable;
}
+static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
+ Properties::isolatedProcess = isolated;
+}
+
+
// ----------------------------------------------------------------------------
// FrameMetricsObserver
// ----------------------------------------------------------------------------
@@ -1097,6 +1102,7 @@
{ "nHackySetRTAnimationsEnabled", "(Z)V",
(void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled },
{ "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
+ { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
};
static JavaVM* mJvm = nullptr;
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index e416287..40cc73a 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -16,6 +16,8 @@
#include <DeviceInfo.h>
+#include "Properties.h"
+
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
@@ -29,6 +31,19 @@
namespace android {
namespace uirenderer {
+static constexpr android::DisplayInfo sDummyDisplay {
+ 1080, // w
+ 1920, // h
+ 320.0, // xdpi
+ 320.0, // ydpi
+ 60.0, // fps
+ 2.0, // density
+ 0, // orientation
+ false, // secure?
+ 0, // appVsyncOffset
+ 0, // presentationDeadline
+};
+
static DeviceInfo* sDeviceInfo = nullptr;
static std::once_flag sInitializedFlag;
@@ -47,20 +62,26 @@
void DeviceInfo::initialize(int maxTextureSize) {
std::call_once(sInitializedFlag, [maxTextureSize]() {
sDeviceInfo = new DeviceInfo();
- sDeviceInfo->loadDisplayInfo();
+ sDeviceInfo->mDisplayInfo = DeviceInfo::queryDisplayInfo();
sDeviceInfo->mMaxTextureSize = maxTextureSize;
});
}
void DeviceInfo::load() {
- loadDisplayInfo();
+ mDisplayInfo = queryDisplayInfo();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
}
-void DeviceInfo::loadDisplayInfo() {
+DisplayInfo DeviceInfo::queryDisplayInfo() {
+ if (Properties::isolatedProcess) {
+ return sDummyDisplay;
+ }
+
+ DisplayInfo displayInfo;
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
+ status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &displayInfo);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info, error %d", status);
+ return displayInfo;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index a0b2f06..297b266 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -47,12 +47,13 @@
return di.w * di.h * in;
}
+ static DisplayInfo queryDisplayInfo();
+
private:
DeviceInfo() {}
~DeviceInfo() {}
void load();
- void loadDisplayInfo();
int mMaxTextureSize;
DisplayInfo mDisplayInfo;
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index e9adbdc..1602b4b 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -63,6 +63,7 @@
bool Properties::runningInEmulator = false;
bool Properties::debuggingEnabled = false;
+bool Properties::isolatedProcess = false;
static int property_get_int(const char* key, int defaultValue) {
char buf[PROPERTY_VALUE_MAX] = {
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 3f44c21..81a3657 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -269,6 +269,7 @@
static bool runningInEmulator;
ANDROID_API static bool debuggingEnabled;
+ ANDROID_API static bool isolatedProcess;
private:
static ProfileType sProfileType;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 8e0546b..6a2a025 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,6 +17,7 @@
#include "RenderThread.h"
#include "CanvasContext.h"
+#include "DeviceInfo.h"
#include "EglManager.h"
#include "OpenGLReadback.h"
#include "RenderProxy.h"
@@ -29,10 +30,9 @@
#include "renderstate/RenderState.h"
#include "renderthread/OpenGLPipeline.h"
#include "utils/FatVector.h"
+#include "utils/TimeUtils.h"
#include <gui/DisplayEventReceiver.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
#include <sys/resource.h>
#include <utils/Condition.h>
#include <utils/Log.h>
@@ -54,6 +54,58 @@
static void (*gOnStartHook)() = nullptr;
+class DisplayEventReceiverWrapper : public VsyncSource {
+public:
+ DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
+ : mDisplayEventReceiver(std::move(receiver)) {}
+
+ virtual void requestNextVsync() override {
+ status_t status = mDisplayEventReceiver->requestNextVsync();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+ nsecs_t latest = 0;
+ ssize_t n;
+ while ((n = mDisplayEventReceiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+ for (ssize_t i = 0; i < n; i++) {
+ const DisplayEventReceiver::Event& ev = buf[i];
+ switch (ev.header.type) {
+ case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ latest = ev.header.timestamp;
+ break;
+ }
+ }
+ }
+ if (n < 0) {
+ ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
+ }
+ return latest;
+ }
+
+private:
+ std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+};
+
+class DummyVsyncSource : public VsyncSource {
+public:
+ DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
+
+ virtual void requestNextVsync() override {
+ mRenderThread->queue().postDelayed(16_ms, [this]() {
+ mRenderThread->drainDisplayEventQueue();
+ });
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ return systemTime(CLOCK_MONOTONIC);
+ }
+
+private:
+ RenderThread* mRenderThread;
+};
+
bool RenderThread::hasInstance() {
return gHasRenderThreadInstance;
}
@@ -74,7 +126,7 @@
RenderThread::RenderThread()
: ThreadBase()
- , mDisplayEventReceiver(nullptr)
+ , mVsyncSource(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
, mRenderState(nullptr)
@@ -89,23 +141,27 @@
}
void RenderThread::initializeDisplayEventReceiver() {
- LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
- mDisplayEventReceiver = new DisplayEventReceiver();
- status_t status = mDisplayEventReceiver->initCheck();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
- "Initialization of DisplayEventReceiver "
- "failed with status: %d",
- status);
+ LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second DisplayEventReceiver?");
- // Register the FD
- mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
- RenderThread::displayEventReceiverCallback, this);
+ if (!Properties::isolatedProcess) {
+ auto receiver = std::make_unique<DisplayEventReceiver>();
+ status_t status = receiver->initCheck();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+ "Initialization of DisplayEventReceiver "
+ "failed with status: %d",
+ status);
+
+ // Register the FD
+ mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
+ RenderThread::displayEventReceiverCallback, this);
+ mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver));
+ } else {
+ mVsyncSource = new DummyVsyncSource(this);
+ }
}
void RenderThread::initThreadLocals() {
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
- LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
+ mDisplayInfo = DeviceInfo::queryDisplayInfo();
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
mTimeLord.setFrameInterval(frameIntervalNanos);
initializeDisplayEventReceiver();
@@ -201,29 +257,9 @@
return 1; // keep the callback
}
-static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- nsecs_t latest = 0;
- ssize_t n;
- while ((n = receiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- for (ssize_t i = 0; i < n; i++) {
- const DisplayEventReceiver::Event& ev = buf[i];
- switch (ev.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
- latest = ev.header.timestamp;
- break;
- }
- }
- }
- if (n < 0) {
- ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
- }
- return latest;
-}
-
void RenderThread::drainDisplayEventQueue() {
ATRACE_CALL();
- nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
+ nsecs_t vsyncEvent = mVsyncSource->latestVsyncEvent();
if (vsyncEvent > 0) {
mVsyncRequested = false;
if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
@@ -256,8 +292,7 @@
void RenderThread::requestVsync() {
if (!mVsyncRequested) {
mVsyncRequested = true;
- status_t status = mDisplayEventReceiver->requestNextVsync();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
+ mVsyncSource->requestNextVsync();
}
}
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 3aa5487..689f518 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -39,7 +39,6 @@
namespace android {
class Bitmap;
-class DisplayEventReceiver;
namespace uirenderer {
@@ -63,6 +62,14 @@
~IFrameCallback() {}
};
+struct VsyncSource {
+ virtual void requestNextVsync() = 0;
+ virtual nsecs_t latestVsyncEvent() = 0;
+ virtual ~VsyncSource() {}
+};
+
+class DummyVsyncSource;
+
class RenderThread : private ThreadBase {
PREVENT_COPY_AND_ASSIGN(RenderThread);
@@ -110,6 +117,7 @@
private:
friend class DispatchFrameCallbacks;
friend class RenderProxy;
+ friend class DummyVsyncSource;
friend class android::uirenderer::TestUtils;
RenderThread();
@@ -127,7 +135,7 @@
DisplayInfo mDisplayInfo;
- DisplayEventReceiver* mDisplayEventReceiver;
+ VsyncSource* mVsyncSource;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;
// We defer the actual registration of these callbacks until
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 406255d..9e6d9a8 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -21,6 +21,7 @@
#include "debug/GlesDriver.h"
#include "debug/NullGlesDriver.h"
#include "hwui/Typeface.h"
+#include "Properties.h"
#include "tests/common/LeakChecker.h"
#include "thread/TaskManager.h"
@@ -67,6 +68,7 @@
// Replace the default GLES driver
debug::GlesDriver::replace(std::make_unique<debug::NullGlesDriver>());
+ Properties::isolatedProcess = true;
// Run the tests
testing::InitGoogleTest(&argc, argv);