DisplayDevice.cpp \
DispSync.cpp \
EventControlThread.cpp \
+ StartBootAnimThread.cpp \
EventThread.cpp \
FrameTracker.cpp \
GpuService.cpp \
}
-#endif // ANDROID_DISPSYNC_H
+#endif // ANDROID_EVENTCONTROLTHREAD_H
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/properties.h>
+#include "StartBootAnimThread.h"
+
+namespace android {
+
+StartBootAnimThread::StartBootAnimThread():
+ Thread(false) {
+}
+
+status_t StartBootAnimThread::Start() {
+ return run("SurfaceFlinger::StartBootAnimThread", PRIORITY_NORMAL);
+}
+
+bool StartBootAnimThread::threadLoop() {
+ property_set("service.bootanim.exit", "0");
+ property_set("ctl.start", "bootanim");
+ // Exit immediately
+ return false;
+}
+
+} // namespace android
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_STARTBOOTANIMTHREAD_H
+#define ANDROID_STARTBOOTANIMTHREAD_H
+
+#include <stddef.h>
+
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+class StartBootAnimThread : public Thread {
+// Boot animation is triggered via calls to "property_set()" which can block
+// if init's executing slow operation such as 'mount_all --late' (currently
+// happening 1/10th with fsck) concurrently. Running in a separate thread
+// allows to pursue the SurfaceFlinger's init process without blocking.
+// see b/34499826.
+public:
+ StartBootAnimThread();
+ status_t Start();
+private:
+ virtual bool threadLoop();
+};
+
+}
+
+#endif // ANDROID_STARTBOOTANIMTHREAD_H
void SurfaceFlinger::bootFinished()
{
+ if (mStartBootAnimThread->join() != NO_ERROR) {
+ ALOGE("Join StartBootAnimThread failed!");
+ }
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mRenderEngine->primeCache();
- // start boot animation
- startBootAnim();
+ mStartBootAnimThread = new StartBootAnimThread();
+ if (mStartBootAnimThread->Start() != NO_ERROR) {
+ ALOGE("Run StartBootAnimThread failed!");
+ }
ALOGV("Done initializing");
}
void SurfaceFlinger::startBootAnim() {
- // start boot animation
- property_set("service.bootanim.exit", "0");
- property_set("ctl.start", "bootanim");
+ // Start boot animation service by setting a property mailbox
+ // if property setting thread is already running, Start() will be just a NOP
+ mStartBootAnimThread->Start();
+ // Wait until property was set
+ if (mStartBootAnimThread->join() != NO_ERROR) {
+ ALOGE("Join StartBootAnimThread failed!");
+ }
}
size_t SurfaceFlinger::getMaxTextureSize() const {
#include "LayerVector.h"
#include "MessageQueue.h"
#include "SurfaceInterceptor.h"
+#include "StartBootAnimThread.h"
#include "DisplayHardware/HWComposer.h"
#include "Effects/Daltonizer.h"
bool useIdentityTransform, Transform::orientation_flags rotation,
bool isLocalScreenshot);
+ sp<StartBootAnimThread> mStartBootAnimThread = nullptr;
+
/* ------------------------------------------------------------------------
* EGL
*/
void SurfaceFlinger::bootFinished()
{
+ if (mStartBootAnimThread->join() != NO_ERROR) {
+ ALOGE("Join StartBootAnimThread failed!");
+ }
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mRenderEngine->primeCache();
- // start boot animation
- startBootAnim();
+ mStartBootAnimThread = new StartBootAnimThread();
+ if (mStartBootAnimThread->Start() != NO_ERROR) {
+ ALOGE("Run StartBootAnimThread failed!");
+ }
+
+ ALOGV("Done initializing");
}
int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
}
void SurfaceFlinger::startBootAnim() {
- // start boot animation
- property_set("service.bootanim.exit", "0");
- property_set("ctl.start", "bootanim");
+ // Start boot animation service by setting a property mailbox
+ // if property setting thread is already running, Start() will be just a NOP
+ mStartBootAnimThread->Start();
+ // Wait until property was set
+ if (mStartBootAnimThread->join() != NO_ERROR) {
+ ALOGE("Join StartBootAnimThread failed!");
+ }
}
size_t SurfaceFlinger::getMaxTextureSize() const {