Bug 1367850 - Move Android UI thread runnable queue from AndroidBridge to AndroidUiThread r=jchen

MozReview-Commit-ID: 4okw7R2P2LC
This commit is contained in:
Randall Barker
2017-06-02 11:03:14 -07:00
parent dbdb7d739b
commit de958d9604
6 changed files with 153 additions and 134 deletions

View File

@@ -153,7 +153,6 @@ AndroidBridge::~AndroidBridge()
}
AndroidBridge::AndroidBridge()
: mUiTaskQueueLock("UiTaskQueue")
{
ALOG_BRIDGE("AndroidBridge::Init");
@@ -947,109 +946,6 @@ AndroidBridge::IsContentDocumentDisplayed(mozIDOMWindowProxy* aWindow)
return layerClient->IsContentDocumentDisplayed();
}
class AndroidBridge::DelayedTask
{
using TimeStamp = mozilla::TimeStamp;
using TimeDuration = mozilla::TimeDuration;
public:
DelayedTask(already_AddRefed<nsIRunnable> aTask)
: mTask(aTask)
, mRunTime() // Null timestamp representing no delay.
{}
DelayedTask(already_AddRefed<nsIRunnable> aTask, int aDelayMs)
: mTask(aTask)
, mRunTime(TimeStamp::Now() + TimeDuration::FromMilliseconds(aDelayMs))
{}
bool IsEarlierThan(const DelayedTask& aOther) const
{
if (mRunTime) {
return aOther.mRunTime ? mRunTime < aOther.mRunTime : false;
}
// In the case of no delay, we're earlier if aOther has a delay.
// Otherwise, we're not earlier, to maintain task order.
return !!aOther.mRunTime;
}
int64_t MillisecondsToRunTime() const
{
if (mRunTime) {
return int64_t((mRunTime - TimeStamp::Now()).ToMilliseconds());
}
return 0;
}
already_AddRefed<nsIRunnable> TakeTask()
{
return mTask.forget();
}
private:
nsCOMPtr<nsIRunnable> mTask;
const TimeStamp mRunTime;
};
void
AndroidBridge::PostTaskToUiThread(already_AddRefed<nsIRunnable> aTask, int aDelayMs)
{
// add the new task into the mUiTaskQueue, sorted with
// the earliest task first in the queue
size_t i;
DelayedTask newTask(aDelayMs ? DelayedTask(mozilla::Move(aTask), aDelayMs)
: DelayedTask(mozilla::Move(aTask)));
{
MutexAutoLock lock(mUiTaskQueueLock);
for (i = 0; i < mUiTaskQueue.Length(); i++) {
if (newTask.IsEarlierThan(mUiTaskQueue[i])) {
mUiTaskQueue.InsertElementAt(i, mozilla::Move(newTask));
break;
}
}
if (i == mUiTaskQueue.Length()) {
// We didn't insert the task, which means we should append it.
mUiTaskQueue.AppendElement(mozilla::Move(newTask));
}
}
if (i == 0) {
// if we're inserting it at the head of the queue, notify Java because
// we need to get a callback at an earlier time than the last scheduled
// callback
GeckoThread::RequestUiThreadCallback(int64_t(aDelayMs));
}
}
int64_t
AndroidBridge::RunDelayedUiThreadTasks()
{
MutexAutoLock lock(mUiTaskQueueLock);
while (!mUiTaskQueue.IsEmpty()) {
const int64_t timeLeft = mUiTaskQueue[0].MillisecondsToRunTime();
if (timeLeft > 0) {
// this task (and therefore all remaining tasks)
// have not yet reached their runtime. return the
// time left until we should be called again
return timeLeft;
}
// Retrieve task before unlocking/running.
nsCOMPtr<nsIRunnable> nextTask(mUiTaskQueue[0].TakeTask());
mUiTaskQueue.RemoveElementAt(0);
// Unlock to allow posting new tasks reentrantly.
MutexAutoUnlock unlock(mUiTaskQueueLock);
nextTask->Run();
}
return -1;
}
Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) {
JNIEnv* const env = GetEnvForThread();
auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(