private void waitRendering(long dTime) {
   mRenderingState.sysTime = SystemClock.uptimeMillis();
   mInWaitingState = true;
   if (mUpdateInNewThread) {
     if (mThread == null) {
       return;
     }
     try {
       synchronized (drawTask) {
         if (dTime == INDEFINITE_TIME) {
           drawTask.wait();
         } else {
           drawTask.wait(dTime);
         }
         sendEmptyMessage(NOTIFY_RENDERING);
       }
     } catch (InterruptedException e) {
       e.printStackTrace();
     }
   } else {
     if (dTime == INDEFINITE_TIME) {
       removeMessages(NOTIFY_RENDERING);
       removeMessages(UPDATE);
     } else {
       removeMessages(NOTIFY_RENDERING);
       removeMessages(UPDATE);
       sendEmptyMessageDelayed(NOTIFY_RENDERING, dTime);
     }
   }
 }
 private synchronized void recordRenderingTime() {
   long lastTime = SystemClock.uptimeMillis();
   mDrawTimes.addLast(lastTime);
   int frames = mDrawTimes.size();
   if (frames > MAX_RECORD_SIZE) {
     mDrawTimes.removeFirst();
     frames = MAX_RECORD_SIZE;
   }
 }
 public long getCurrentTime() {
   if (!mReady) {
     return 0;
   }
   if (mInSeekingAction) {
     return mDesireSeekingTime;
   }
   if (quitFlag || !mInWaitingState) {
     return timer.currMillisecond - mRemainingTime;
   }
   return SystemClock.uptimeMillis() - mTimeBase;
 }
  private void updateInCurrentThread() {
    if (quitFlag) {
      return;
    }
    long startMS = SystemClock.uptimeMillis();
    long d = syncTimer(startMS);
    if (d < 0) {
      removeMessages(UPDATE);
      sendEmptyMessageDelayed(UPDATE, 60 - d);
      return;
    }
    d = mDanmakuView.drawDanmakus();
    removeMessages(UPDATE);
    if (d
        > mCordonTime2) { // this situation may be cuased by ui-thread waiting of DanmakuView, so we
                          // sync-timer at once
      timer.add(d);
      mDrawTimes.clear();
    }
    if (!mDanmakusVisible) {
      waitRendering(INDEFINITE_TIME);
      return;
    } else if (mRenderingState.nothingRendered && mIdleSleep) {
      long dTime = mRenderingState.endTime - timer.currMillisecond;
      if (dTime > 500) {
        waitRendering(dTime - 10);
        return;
      }
    }

    if (d < mFrameUpdateRate) {
      sendEmptyMessageDelayed(UPDATE, mFrameUpdateRate - d);
      return;
    }
    sendEmptyMessage(UPDATE);
  }
 private void syncTimerIfNeeded() {
   if (mInWaitingState) {
     syncTimer(SystemClock.uptimeMillis());
   }
 }
 @Override
 public void handleMessage(Message msg) {
   int what = msg.what;
   switch (what) {
     case PREPARE:
       if (mParser == null || !mDanmakuView.isViewReady()) {
         sendEmptyMessageDelayed(PREPARE, 100);
       } else {
         prepare(
             new Runnable() {
               @Override
               public void run() {
                 mReady = true;
                 if (mCallback != null) {
                   mCallback.prepared();
                 }
               }
             });
       }
       break;
     case SHOW_DANMAKUS:
       mDanmakusVisible = true;
       Long start = (Long) msg.obj;
       boolean resume = false;
       if (drawTask != null) {
         if (start == null) {
           timer.update(getCurrentTime());
           drawTask.requestClear();
         } else {
           drawTask.start();
           drawTask.seek(start);
           drawTask.requestClear();
           resume = true;
         }
       }
       if (quitFlag && mDanmakuView != null) {
         mDanmakuView.drawDanmakus();
       }
       notifyRendering();
       if (!resume) {
         break;
       }
     case START:
       Long startTime = (Long) msg.obj;
       if (startTime != null) {
         pausedPosition = startTime;
       } else {
         pausedPosition = 0;
       }
     case RESUME:
       quitFlag = false;
       if (mReady) {
         mRenderingState.reset();
         mDrawTimes.clear();
         mTimeBase = SystemClock.uptimeMillis() - pausedPosition;
         timer.update(pausedPosition);
         removeMessages(RESUME);
         sendEmptyMessage(UPDATE);
         drawTask.start();
         notifyRendering();
         mInSeekingAction = false;
       } else {
         sendEmptyMessageDelayed(RESUME, 100);
       }
       break;
     case SEEK_POS:
       quitFlag = true;
       quitUpdateThread();
       Long position = (Long) msg.obj;
       long deltaMs = position - timer.currMillisecond;
       mTimeBase -= deltaMs;
       timer.update(SystemClock.uptimeMillis() - mTimeBase);
       mContext.mGlobalFlagValues.updateMeasureFlag();
       if (drawTask != null) drawTask.seek(timer.currMillisecond);
       pausedPosition = timer.currMillisecond;
       removeMessages(RESUME);
       sendEmptyMessage(RESUME);
       break;
     case UPDATE:
       if (mUpdateInNewThread) {
         updateInNewThread();
       } else {
         updateInCurrentThread();
       }
       break;
     case NOTIFY_DISP_SIZE_CHANGED:
       mContext.mDanmakuFactory.notifyDispSizeChanged(mContext);
       Boolean updateFlag = (Boolean) msg.obj;
       if (updateFlag != null && updateFlag) {
         mContext.mGlobalFlagValues.updateMeasureFlag();
       }
       break;
     case HIDE_DANMAKUS:
       mDanmakusVisible = false;
       if (mDanmakuView != null) {
         mDanmakuView.clear();
       }
       if (this.drawTask != null) {
         this.drawTask.requestClear();
         this.drawTask.requestHide();
       }
       Boolean quitDrawTask = (Boolean) msg.obj;
       if (quitDrawTask && this.drawTask != null) {
         this.drawTask.quit();
       }
       if (!quitDrawTask) {
         break;
       }
     case PAUSE:
       removeMessages(UPDATE);
     case QUIT:
       if (what == QUIT) {
         removeCallbacksAndMessages(null);
       }
       quitFlag = true;
       syncTimerIfNeeded();
       if (mThread != null) {
         notifyRendering();
         quitUpdateThread();
       }
       pausedPosition = timer.currMillisecond;
       if (what == QUIT) {
         if (this.drawTask != null) {
           this.drawTask.quit();
         }
         if (mParser != null) {
           mParser.release();
         }
         if (this.getLooper() != Looper.getMainLooper()) this.getLooper().quit();
       }
       break;
     case NOTIFY_RENDERING:
       notifyRendering();
       break;
     case UPDATE_WHEN_PAUSED:
       if (quitFlag && mDanmakuView != null) {
         drawTask.requestClear();
         mDanmakuView.drawDanmakus();
         notifyRendering();
       }
       break;
     case CLEAR_DANMAKUS_ON_SCREEN:
       if (drawTask != null) {
         drawTask.clearDanmakusOnScreen(getCurrentTime());
       }
       break;
   }
 }