private final void stopChoreographerThread() { if (null != mChoreographerThread) { Choreographer.getInstance().removeFrameCallback(mFrameCallback); mChoreographerThread.quitSafely(); try { mChoreographerThread.join(); } catch (final Exception ignored) { } finally { mChoreographerThread = null; } } }
/** * Constructs a VSyncMonitor * * @param context The application context. * @param listener The listener receiving VSync notifications. * @param enableJBVsync Whether to allow Choreographer-based notifications on JB and up. */ public VSyncMonitor(Context context, VSyncMonitor.Listener listener, boolean enableJBVSync) { mListener = listener; float refreshRate = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay() .getRefreshRate(); if (refreshRate <= 0) refreshRate = 60; mRefreshPeriodNano = (long) (NANOSECONDS_PER_SECOND / refreshRate); if (enableJBVSync && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // Use Choreographer on JB+ to get notified of vsync. mChoreographer = Choreographer.getInstance(); mVSyncFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { TraceEvent.begin("VSync"); mGoodStartingPointNano = frameTimeNanos; onVSyncCallback(frameTimeNanos, getCurrentNanoTime()); TraceEvent.end("VSync"); } }; mVSyncRunnableCallback = null; } else { // On ICS we just hope that running tasks is relatively predictable. mChoreographer = null; mVSyncFrameCallback = null; mVSyncRunnableCallback = new Runnable() { @Override public void run() { TraceEvent.begin("VSyncTimer"); final long currentTime = getCurrentNanoTime(); onVSyncCallback(currentTime, currentTime); TraceEvent.end("VSyncTimer"); } }; mLastPostedNano = 0; } mSyntheticVSyncRunnable = new Runnable() { @Override public void run() { TraceEvent.begin("VSyncSynthetic"); final long currentTime = getCurrentNanoTime(); onVSyncCallback(estimateLastVSyncTime(currentTime), currentTime); TraceEvent.end("VSyncSynthetic"); } }; mGoodStartingPointNano = getCurrentNanoTime(); }
/** * Helper class for implement wiggle motion. * * <p>There are two ways of implement wiggle motion using {@code WiggleHelper}: use in extended view * class and use as {@link View.OnAttachStateChangeListener}. Constructor must be called from a * thread that already has a Looper associated with it. Extend view class example: * * <pre>{@code * public class WiggleView extends View { * private final WiggleHelper helper = new WiggleHelper(); * // Constructors... * @Override * protected void onAttachedToWindow() { * super.onAttachedToWindow(); * helper.onViewAttachedToWindow(this); * } * @Override * protected void onDetachedFromWindow() { * helper.onViewDetachedFromWindow(this); * super.onDetachedFromWindow(); * } * } * }</pre> * * OnAttachStateChangeListener example: * * <pre>{@code * View view = findViewById(R.id.wiggle); * view.addOnAttachStateChangeListener(new WiggleHelper()); * }</pre> * * Note: Don't share same {@code WiggleHelper} instance with multiple views. */ public class WiggleHelper implements View.OnAttachStateChangeListener { private final Choreographer choreographer = Choreographer.getInstance(); private final int[] location = new int[2]; private boolean isInitialized; private View view; private final Choreographer.FrameCallback callback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { if (isInitialized) { int oldX = location[0]; int oldY = location[1]; injectLocation(); view.setTranslationX(oldX - location[0]); view.setTranslationY(oldY - location[1]); } else { injectLocation(); isInitialized = true; } choreographer.postFrameCallback(this); } }; private void injectLocation() { ((View) view.getParent()).getLocationInWindow(location); } @Override public void onViewAttachedToWindow(View v) { isInitialized = false; view = v; choreographer.postFrameCallback(callback); } @Override public void onViewDetachedFromWindow(View v) { view = null; choreographer.removeFrameCallback(callback); } }
public DisplayPowerState( ElectronBeam electronBean, DisplayBlanker displayBlanker, LightsService.Light backlight) { mHandler = new Handler(true /*async*/); mChoreographer = Choreographer.getInstance(); mElectronBeam = electronBean; mDisplayBlanker = displayBlanker; mBacklight = backlight; mPhotonicModulator = new PhotonicModulator(); // At boot time, we know that the screen is on and the electron beam // animation is not playing. We don't know the screen's brightness though, // so prepare to set it to a known state when the state is next applied. // Although we set the brightness to full on here, the display power controller // will reset the brightness to a new level immediately before the changes // actually have a chance to be applied. mScreenOn = true; mScreenBrightness = PowerManager.BRIGHTNESS_ON; scheduleScreenUpdate(); mElectronBeamPrepared = false; mElectronBeamLevel = 1.0f; mElectronBeamReady = true; }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) private Choreographer getChoreographer() { return Choreographer.getInstance(); }
@Override public void doFrame(final long frameTimeNanos) { mSurfaceView.requestRender(); Choreographer.getInstance().postFrameCallback(this); }
/** @return an Android spring choreographer using the system {@link Choreographer} */ public static ChoreographerAndroidSpringLooper create() { return new ChoreographerAndroidSpringLooper(Choreographer.getInstance()); }
protected MainController(Context context, EventHandler eventHandler) { Util.Assert(sInstance == null, "non-null instance"); sInstance = this; mContext = context; mAppPackageName = mContext.getPackageName(); mEventHandler = eventHandler; mAppPoller = new AppPoller(context); mAppPoller.setListener(mAppPollerListener); mCanAutoDisplayLink = true; mCanDisplay = true; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (Constant.PROFILE_FPS) { mTextView = new TextView(mContext); mTextView.setTextColor(0xff00ffff); mTextView.setTextSize(32.0f); mWindowManagerParams.gravity = Gravity.TOP | Gravity.LEFT; mWindowManagerParams.x = 500; mWindowManagerParams.y = 16; mWindowManagerParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mWindowManagerParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mWindowManagerParams.type = WindowManager.LayoutParams.TYPE_PHONE; mWindowManagerParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; mWindowManagerParams.format = PixelFormat.TRANSPARENT; mWindowManagerParams.setTitle("LinkBubble: Debug Text"); mWindowManager.addView(mTextView, mWindowManagerParams); } mUpdateScheduled = false; mChoreographer = Choreographer.getInstance(); mCanvasView = new CanvasView(mContext); MainApplication app = (MainApplication) mContext.getApplicationContext(); Bus bus = app.getBus(); bus.register(this); updateIncognitoMode(Settings.get().isIncognitoMode()); LayoutInflater inflater = LayoutInflater.from(mContext); mBubbleDraggable = (BubbleDraggable) inflater.inflate(R.layout.view_bubble_draggable, null); Point bubbleRestingPoint = Settings.get().getBubbleRestingPoint(); int fromX = Settings.get().getBubbleStartingX(bubbleRestingPoint); mBubbleDraggable.configure( fromX, bubbleRestingPoint.y, bubbleRestingPoint.x, bubbleRestingPoint.y, Constant.BUBBLE_SLIDE_ON_SCREEN_TIME, mCanvasView); mBubbleDraggable.setOnUpdateListener( new BubbleDraggable.OnUpdateListener() { @Override public void onUpdate(Draggable draggable, float dt) { if (!draggable.isDragging()) { mBubbleFlowDraggable.syncWithBubble(draggable); } } }); mBubbleFlowDraggable = (BubbleFlowDraggable) inflater.inflate(R.layout.view_bubble_flow, null); mBubbleFlowDraggable.configure(null); mBubbleFlowDraggable.collapse(0, null); mBubbleFlowDraggable.setBubbleDraggable(mBubbleDraggable); mBubbleFlowDraggable.setVisibility(View.GONE); mBubbleDraggable.setBubbleFlowDraggable(mBubbleFlowDraggable); }