use of android.util.BoostFramework in project android_frameworks_base by AOSPA.
the class UserController method finishUserUnlockedCompleted.
private void finishUserUnlockedCompleted(UserState uss) {
final int userId = uss.mHandle.getIdentifier();
synchronized (mService) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss)
return;
final UserInfo userInfo = getUserInfo(userId);
if (userInfo == null) {
return;
}
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId))
return;
// Remember that we logged in
mUserManager.onUserLoggedIn(userId);
if (!userInfo.isInitialized()) {
if (userId != UserHandle.USER_SYSTEM) {
Slog.d(TAG, "Initializing user #" + userId);
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mService.broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// Note: performReceive is called with mService lock held
getUserManager().makeInitialized(userInfo.id);
}
}, 0, null, null, null, AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
/**
* For boosting right after boot
*/
final int[] mBoostParamVal = mService.mContext.getResources().getIntArray(com.android.internal.R.array.onbootboost_param_value);
final boolean lIsPerfBoostEnabled = mBoostParamVal.length != 0;
if (lIsPerfBoostEnabled) {
int mBoostDuration = mService.mContext.getResources().getInteger(com.android.internal.R.integer.onbootboost_duration);
BoostFramework mPerf = new BoostFramework();
Slog.i(TAG, "Bootup boost was triggered for " + mBoostDuration + " seconds!");
if (mBoostDuration != 0)
// Convert seconds to milliseconds
mBoostDuration = mBoostDuration * 1000;
mPerf.perfLockAcquire(mBoostDuration, mBoostParamVal);
}
Slog.d(TAG, "Sending BOOT_COMPLETE user #" + userId);
// Do not report secondary users, runtime restarts or first boot/upgrade
if (userId == UserHandle.USER_SYSTEM && !mService.mSystemServiceManager.isRuntimeRestarted() && !isFirstBootOrUpgrade()) {
int uptimeSeconds = (int) (SystemClock.elapsedRealtime() / 1000);
MetricsLogger.histogram(mService.mContext, "framework_boot_completed", uptimeSeconds);
}
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mService.broadcastIntentLocked(null, null, bootIntent, null, null, 0, null, null, new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED }, AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
use of android.util.BoostFramework in project android_frameworks_base by AOSPA.
the class Activity method dispatchTouchEvent.
/**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mDragBoostPossible == -1) {
mDragBoostPossible = 0;
String currentActivity = getPackageName();
String[] activityList = getResources().getStringArray(com.android.internal.R.array.boost_activityList);
if (activityList != null) {
for (String match : activityList) {
if (currentActivity.indexOf(match) != -1) {
mDragBoostPossible = 1;
break;
}
}
}
}
Context context = getApplicationContext();
if (mDragBoostPossible == 1) {
final boolean override = context.getResources().getBoolean(com.android.internal.R.bool.config_debugBoost);
if (mPerf == null) {
mPerf = new BoostFramework();
}
if (!override) {
if (mPerfLockDuration == -1) {
mPerfLockDuration = getResources().getInteger(com.android.internal.R.integer.ascrollboost_timeout);
mAsParamVal = getResources().getIntArray(com.android.internal.R.array.ascrollboost_param_value);
}
if (mPerfLockDuration != 0 && mAsParamVal.length != 0) {
mPerf.perfLockAcquireTouch(ev, getResources().getDisplayMetrics(), mPerfLockDuration, mAsParamVal);
}
} else {
mPerf.enableDebugBoost(context, ev, getResources().getDisplayMetrics());
}
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
use of android.util.BoostFramework in project android_frameworks_base by AOSPA.
the class ActivityStack method resumeTopActivityInnerLocked.
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (DEBUG_LOCKSCREEN)
mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
ActivityRecord parent = mActivityContainer.mParentActivity;
if ((parent != null && parent.state != ActivityState.RESUMED) || !mActivityContainer.isAttachedLocked()) {
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
}
mStackSupervisor.cancelInitializingActivities();
// Find the first activity that is not finishing.
final ActivityRecord next = topRunningActivityLocked();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
// stack is not covering the entire screen.
return mStackSupervisor.resumeFocusedStackTopActivityLocked(mStackSupervisor.getFocusedStack(), prev, null);
}
// Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return false;
}
final TaskRecord nextTask = next.task;
if (prevTask != null && prevTask.stack == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
// This task is going away but it was supposed to return to the home stack.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else if (!isOnHomeDisplay()) {
return false;
} else if (!isHomeStack()) {
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Launching home next");
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
}
}
// activity is paused, well that is the state we want.
if (mService.isSleepingOrShuttingDownLocked() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// another user's activities to the top of the stack.
if (!mService.mUserController.hasStartedUserState(next.userId)) {
Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped");
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Resuming " + next);
mActivityTrigger.activityResumeTrigger(next.intent, next.info, next.appInfo, next.task.mFullscreen);
// until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES)
Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return false;
}
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
// We need to start pausing the current activity so the top one can be resumed...
final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
if (mResumedActivity != null) {
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES)
Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing");
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
} else if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) {
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// sure to finish it as we're making a new activity topmost.
if (mService.isSleepingLocked() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) {
if (DEBUG_STATES)
Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume");
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, null, "resume-no-history", false);
mLastNoHistoryActivity = null;
}
if (prev != null && prev != next) {
if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev) && next != null && !next.nowVisible) {
mStackSupervisor.mWaitingVisibleActivities.add(prev);
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Resuming top, waiting visible to hide: " + prev);
} else {
// new one is found to be full-screen or not.
if (prev.finishing) {
mWindowManager.setAppVisibility(prev.appToken, false);
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + ", nowVisible=" + next.nowVisible);
} else {
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mWaitingVisibleActivities.contains(prev) + ", nowVisible=" + next.nowVisible);
}
}
}
// considered stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(next.packageName, false, next.userId);
/* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package " + next.packageName + ": " + e);
}
// We are starting up the next activity, so tell the window manager
// that the previous one will be hidden soon. This way it can know
// to ignore it when computing the desired screen orientation.
boolean anim = true;
if (mIsAnimationBoostEnabled == true && mPerf == null) {
mPerf = new BoostFramework();
}
if (prev != null) {
if (prev.finishing) {
if (DEBUG_TRANSITION)
Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task ? TRANSIT_ACTIVITY_CLOSE : TRANSIT_TASK_CLOSE, false);
if (prev.task != next.task && mPerf != null) {
mPerf.perfLockAcquire(aBoostTimeOut, aBoostParamVal);
}
}
mWindowManager.setAppVisibility(prev.appToken, false);
} else {
if (DEBUG_TRANSITION)
Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task ? TRANSIT_ACTIVITY_OPEN : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND : TRANSIT_TASK_OPEN, false);
if (prev.task != next.task && mPerf != null) {
mPerf.perfLockAcquire(aBoostTimeOut, aBoostParamVal);
}
}
}
} else {
if (DEBUG_TRANSITION)
Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
}
}
Bundle resumeAnimOptions = null;
if (anim) {
ActivityOptions opts = next.getOptionsForTargetActivityLocked();
if (opts != null) {
resumeAnimOptions = opts.toBundle();
}
next.applyOptionsLocked();
} else {
next.clearOptionsLocked();
}
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped + " visible=" + next.visible);
// If the previous activity is translucent, force a visibility update of
// the next activity, so that it's added to WM's opening app list, and
// transition animation can be set up properly.
// For example, pressing Home button with a translucent activity in focus.
// Launcher is already visible in this case. If we don't add it to opening
// apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
// TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
final boolean lastActivityTranslucent = lastStack != null && (!lastStack.mFullscreen || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen));
// This activity is now becoming visible.
if (!next.visible || next.stopped || lastActivityTranslucent) {
mWindowManager.setAppVisibility(next.appToken, true);
}
// schedule launch ticks to collect information about slow apps.
next.startLaunchTickingLocked();
ActivityRecord lastResumedActivity = lastStack == null ? null : lastStack.mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
if (DEBUG_STATES)
Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
next.state = ActivityState.RESUMED;
mResumedActivity = next;
next.task.touchActiveTime();
mRecentTasks.addLocked(next.task);
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
mService.updateOomAdjLocked();
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
boolean notUpdated = true;
if (mStackSupervisor.isFocusedStack(this)) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(mService.mConfiguration, next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
if (config != null) {
next.frozenBeforeDestroy = true;
}
notUpdated = !mService.updateConfigurationLocked(config, next, false);
}
if (notUpdated) {
// The configuration update wasn't able to keep the existing
// instance of the activity, and instead started a new one.
// We should be all done, but let's just make sure our activity
// is still at the top and schedule another run if something
// weird happened.
ActivityRecord nextNext = topRunningActivityLocked();
if (DEBUG_SWITCH || DEBUG_STATES)
Slog.i(TAG_STATES, "Activity config changed during resume: " + next + ", new next: " + nextNext);
if (nextNext != next) {
// Do over!
mStackSupervisor.scheduleResumeTopActivities();
}
if (mStackSupervisor.reportResumedActivityLocked(next)) {
mNoAnimActivities.clear();
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
}
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return false;
}
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS)
Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
boolean allowSavedSurface = true;
if (next.newIntents != null) {
// what's left last time.
for (int i = next.newIntents.size() - 1; i >= 0; i--) {
final Intent intent = next.newIntents.get(i);
if (intent != null && !ActivityRecord.isMainIntent(intent)) {
allowSavedSurface = false;
break;
}
}
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken, false);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
mWindowManager.notifyAppResumed(next.appToken, next.stopped, allowSavedSurface);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, System.identityHashCode(next), next.task.taskId, next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions);
mStackSupervisor.checkReadyForSleepLocked();
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
} catch (Exception e) {
// Whoops, need to restart this activity!
if (DEBUG_STATES)
Slog.v(TAG_STATES, "Resume failed; resetting state to " + lastState + ": " + next);
next.state = lastState;
if (lastStack != null) {
lastStack.mResumedActivity = lastResumedActivity;
}
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && mStackSupervisor.isFrontStack(lastStack)) {
next.showStartingWindow(null, true);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// to recover the activity.
try {
completeResumeLocked(next);
} catch (Exception e) {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception", true);
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
}
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null, true);
}
if (DEBUG_SWITCH)
Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES)
Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK)
mStackSupervisor.validateTopActivitiesLocked();
return true;
}
use of android.util.BoostFramework in project android_frameworks_base by AOSPA.
the class ViewRootImpl method draw.
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (!surface.isValid()) {
return;
}
if (DEBUG_FPS) {
trackFPS();
}
if (!sFirstDrawComplete) {
synchronized (sFirstDrawHandlers) {
sFirstDrawComplete = true;
final int count = sFirstDrawHandlers.size();
for (int i = 0; i < count; i++) {
mHandler.post(sFirstDrawHandlers.get(i));
}
}
}
scrollToRectOrFocus(null, false);
if (mAttachInfo.mViewScrollChanged) {
if (mIsPreFlingBoostEnabled && mHaveMoveEvent && !mIsPerfLockAcquired) {
mIsPerfLockAcquired = true;
if (mPerf == null) {
mPerf = new BoostFramework();
}
if (mPerf != null) {
mPerf.perfLockAcquire(mPreFlingBoostTimeOut, mPreFlingBoostParamVal);
}
}
mAttachInfo.mViewScrollChanged = false;
mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
}
boolean animating = mScroller != null && mScroller.computeScrollOffset();
final int curScrollY;
if (animating) {
curScrollY = mScroller.getCurrY();
} else {
curScrollY = mScrollY;
}
if (mCurScrollY != curScrollY) {
mCurScrollY = curScrollY;
fullRedrawNeeded = true;
if (mView instanceof RootViewSurfaceTaker) {
((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY);
}
}
final float appScale = mAttachInfo.mApplicationScale;
final boolean scalingRequired = mAttachInfo.mScalingRequired;
int resizeAlpha = 0;
final Rect dirty = mDirty;
if (mSurfaceHolder != null) {
// The app owns the surface, we won't draw.
dirty.setEmpty();
if (animating && mScroller != null) {
mScroller.abortAnimation();
}
return;
}
if (fullRedrawNeeded) {
mAttachInfo.mIgnoreDirtyState = true;
dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
}
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Log.v(mTag, "Draw " + mView + "/" + mWindowAttributes.getTitle() + ": dirty={" + dirty.left + "," + dirty.top + "," + dirty.right + "," + dirty.bottom + "} surface=" + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" + appScale + ", width=" + mWidth + ", height=" + mHeight);
}
mAttachInfo.mTreeObserver.dispatchOnDraw();
int xOffset = -mCanvasOffsetX;
int yOffset = -mCanvasOffsetY + curScrollY;
final WindowManager.LayoutParams params = mWindowAttributes;
final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
if (surfaceInsets != null) {
xOffset -= surfaceInsets.left;
yOffset -= surfaceInsets.top;
// Offset dirty rect for surface insets.
dirty.offset(surfaceInsets.left, surfaceInsets.right);
}
boolean accessibilityFocusDirty = false;
final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
if (drawable != null) {
final Rect bounds = mAttachInfo.mTmpInvalRect;
final boolean hasFocus = getAccessibilityFocusedRect(bounds);
if (!hasFocus) {
bounds.setEmpty();
}
if (!bounds.equals(drawable.getBounds())) {
accessibilityFocusDirty = true;
}
}
mAttachInfo.mDrawingTime = mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
// If accessibility focus moved, always invalidate the root.
boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;
mInvalidateRootRequested = false;
// Draw with hardware renderer.
mIsAnimating = false;
if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
mHardwareYOffset = yOffset;
mHardwareXOffset = xOffset;
invalidateRoot = true;
}
if (invalidateRoot) {
mAttachInfo.mHardwareRenderer.invalidateRoot();
}
dirty.setEmpty();
// Stage the content drawn size now. It will be transferred to the renderer
// shortly before the draw commands get send to the renderer.
final boolean updated = updateContentDrawBounds();
if (mReportNextDraw) {
// report next draw overrides setStopped()
// This value is re-sync'd to the value of mStopped
// in the handling of mReportNextDraw post-draw.
mAttachInfo.mHardwareRenderer.setStopped(false);
}
if (updated) {
requestDrawWindow();
}
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
} else {
// eglTerminate() for instance.
if (mAttachInfo.mHardwareRenderer != null && !mAttachInfo.mHardwareRenderer.isEnabled() && mAttachInfo.mHardwareRenderer.isRequested()) {
try {
mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
mFullRedrawNeeded = true;
scheduleTraversals();
return;
}
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
}
if (animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}
}
Aggregations