Merge "Check clock accuracy before attempting to display clock" into nyc-mr1-dev

This commit is contained in:
Damien Bargiacchi
2016-05-19 20:56:51 +00:00
committed by Android (Google) Code Review
2 changed files with 186 additions and 10 deletions

View File

@ -18,6 +18,9 @@
#define LOG_TAG "BootAnimation" #define LOG_TAG "BootAnimation"
#include <stdint.h> #include <stdint.h>
#include <sys/inotify.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <math.h> #include <math.h>
#include <fcntl.h> #include <fcntl.h>
@ -57,23 +60,29 @@
#include "BootAnimation.h" #include "BootAnimation.h"
#include "AudioPlayer.h" #include "AudioPlayer.h"
#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
#define EXIT_PROP_NAME "service.bootanim.exit"
namespace android { namespace android {
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
static const char SYSTEM_TIME_DIR_NAME[] = "time";
static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change";
static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change";
static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate";
static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate";
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
static const int ANIM_ENTRY_NAME_MAX = 256; static const int ANIM_ENTRY_NAME_MAX = 256;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true) { BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient(); mSession = new SurfaceComposerClient();
} }
BootAnimation::~BootAnimation() { BootAnimation::~BootAnimation() {}
}
void BootAnimation::onFirstRef() { void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this); status_t err = mSession->linkToComposerDeath(this);
@ -638,11 +647,21 @@ bool BootAnimation::preloadZip(Animation& animation)
bool BootAnimation::movie() bool BootAnimation::movie()
{ {
Animation* animation = loadAnimation(mZipFileName); Animation* animation = loadAnimation(mZipFileName);
if (animation == NULL) if (animation == NULL)
return false; return false;
bool anyPartHasClock = false;
for (size_t i=0; i < animation->parts.size(); i++) {
if(animation->parts[i].clockPosY >= 0) {
anyPartHasClock = true;
break;
}
}
if (!anyPartHasClock) {
mClockEnabled = false;
}
// Blend required to draw time on top of animation frames. // Blend required to draw time on top of animation frames.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_FLAT); glShadeModel(GL_FLAT);
@ -664,7 +683,18 @@ bool BootAnimation::movie()
mClockEnabled = clockTextureInitialized; mClockEnabled = clockTextureInitialized;
} }
if (mClockEnabled && !updateIsTimeAccurate()) {
mTimeCheckThread = new TimeCheckThread(this);
mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);
}
playAnimation(*animation); playAnimation(*animation);
if (mTimeCheckThread != NULL) {
mTimeCheckThread->requestExit();
mTimeCheckThread = NULL;
}
releaseAnimation(animation); releaseAnimation(animation);
if (clockTextureInitialized) { if (clockTextureInitialized) {
@ -745,7 +775,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
// which is equivalent to mHeight - (yc + animation.height) // which is equivalent to mHeight - (yc + animation.height)
glDrawTexiOES(xc, mHeight - (yc + animation.height), glDrawTexiOES(xc, mHeight - (yc + animation.height),
0, animation.width, animation.height); 0, animation.width, animation.height);
if (mClockEnabled && part.clockPosY >= 0) { if (mClockEnabled && mTimeIsAccurate && part.clockPosY >= 0) {
drawTime(mClock, part.clockPosY); drawTime(mClock, part.clockPosY);
} }
@ -824,6 +854,132 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
mLoadedFiles.remove(fn); mLoadedFiles.remove(fn);
return animation; return animation;
} }
bool BootAnimation::updateIsTimeAccurate() {
static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days
static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes
if (mTimeIsAccurate) {
return true;
}
struct stat statResult;
if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) {
mTimeIsAccurate = true;
return true;
}
FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r");
if (file != NULL) {
long long lastChangedTime = 0;
fscanf(file, "%lld", &lastChangedTime);
fclose(file);
if (lastChangedTime > 0) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
// Match the Java timestamp format
long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL);
if (lastChangedTime > rtcNow - MAX_TIME_IN_PAST
&& lastChangedTime < rtcNow + MAX_TIME_IN_FUTURE) {
mTimeIsAccurate = true;
}
}
}
return mTimeIsAccurate;
}
BootAnimation::TimeCheckThread::TimeCheckThread(BootAnimation* bootAnimation) : Thread(false),
mInotifyFd(-1), mSystemWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {}
BootAnimation::TimeCheckThread::~TimeCheckThread() {
// mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD.
close(mInotifyFd);
}
bool BootAnimation::TimeCheckThread::threadLoop() {
bool shouldLoop = doThreadLoop() && !mBootAnimation->mTimeIsAccurate
&& mBootAnimation->mClockEnabled;
if (!shouldLoop) {
close(mInotifyFd);
mInotifyFd = -1;
}
return shouldLoop;
}
bool BootAnimation::TimeCheckThread::doThreadLoop() {
static constexpr int BUFF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1));
// Poll instead of doing a blocking read so the Thread can exit if requested.
struct pollfd pfd = { mInotifyFd, POLLIN, 0 };
ssize_t pollResult = poll(&pfd, 1, 1000);
if (pollResult == 0) {
return true;
} else if (pollResult < 0) {
ALOGE("Could not poll inotify events");
return false;
}
char buff[BUFF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));;
ssize_t length = read(mInotifyFd, buff, BUFF_LEN);
if (length == 0) {
return true;
} else if (length < 0) {
ALOGE("Could not read inotify events");
return false;
}
const struct inotify_event *event;
for (char* ptr = buff; ptr < buff + length; ptr += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *) ptr;
if (event->wd == mSystemWd && strcmp(SYSTEM_TIME_DIR_NAME, event->name) == 0) {
addTimeDirWatch();
} else if (event->wd == mTimeWd && (strcmp(LAST_TIME_CHANGED_FILE_NAME, event->name) == 0
|| strcmp(ACCURATE_TIME_FLAG_FILE_NAME, event->name) == 0)) {
return !mBootAnimation->updateIsTimeAccurate();
}
}
return true;
}
void BootAnimation::TimeCheckThread::addTimeDirWatch() {
mTimeWd = inotify_add_watch(mInotifyFd, SYSTEM_TIME_DIR_PATH,
IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB);
if (mTimeWd > 0) {
// No need to watch for the time directory to be created if it already exists
inotify_rm_watch(mInotifyFd, mSystemWd);
mSystemWd = -1;
}
}
status_t BootAnimation::TimeCheckThread::readyToRun() {
mInotifyFd = inotify_init();
if (mInotifyFd < 0) {
ALOGE("Could not initialize inotify fd");
return NO_INIT;
}
mSystemWd = inotify_add_watch(mInotifyFd, SYSTEM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB);
if (mSystemWd < 0) {
close(mInotifyFd);
mInotifyFd = -1;
ALOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH);
return NO_INIT;
}
addTimeDirWatch();
if (mBootAnimation->updateIsTimeAccurate()) {
close(mInotifyFd);
mInotifyFd = -1;
return ALREADY_EXISTS;
}
return NO_ERROR;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
} }

View File

@ -51,6 +51,24 @@ private:
virtual void onFirstRef(); virtual void onFirstRef();
virtual void binderDied(const wp<IBinder>& who); virtual void binderDied(const wp<IBinder>& who);
bool updateIsTimeAccurate();
class TimeCheckThread : public Thread {
public:
TimeCheckThread(BootAnimation* bootAnimation);
virtual ~TimeCheckThread();
private:
virtual status_t readyToRun();
virtual bool threadLoop();
bool doThreadLoop();
void addTimeDirWatch();
int mInotifyFd;
int mSystemWd;
int mTimeWd;
BootAnimation* mBootAnimation;
};
struct Texture { struct Texture {
GLint w; GLint w;
GLint h; GLint h;
@ -113,8 +131,10 @@ private:
sp<SurfaceControl> mFlingerSurfaceControl; sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface; sp<Surface> mFlingerSurface;
bool mClockEnabled; bool mClockEnabled;
bool mTimeIsAccurate;
String8 mZipFileName; String8 mZipFileName;
SortedVector<String8> mLoadedFiles; SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------