DimAnimator.java revision b47bbc3d80badb94229bc4ce7a2d5006faa9ef15
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wm; 18 19import android.content.res.Resources; 20import android.graphics.PixelFormat; 21import android.util.Slog; 22import android.util.TypedValue; 23import android.view.Surface; 24import android.view.SurfaceSession; 25 26import java.io.PrintWriter; 27 28/** 29 * DimAnimator class that controls the dim animation. This holds the surface and 30 * all state used for dim animation. 31 */ 32class DimAnimator { 33 Surface mDimSurface; 34 boolean mDimShown = false; 35 float mDimCurrentAlpha; 36 float mDimTargetAlpha; 37 float mDimDeltaPerMs; 38 long mLastDimAnimTime; 39 40 int mLastDimWidth, mLastDimHeight; 41 42 DimAnimator (SurfaceSession session, final int layerStack) { 43 if (mDimSurface == null) { 44 try { 45 if (WindowManagerService.DEBUG_SURFACE_TRACE) { 46 mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0, 47 "DimAnimator", 48 layerStack, 16, 16, PixelFormat.OPAQUE, 49 Surface.FX_SURFACE_DIM); 50 } else { 51 mDimSurface = new Surface(session, 0, 52 "DimAnimator", 53 layerStack, 16, 16, PixelFormat.OPAQUE, 54 Surface.FX_SURFACE_DIM); 55 } 56 if (WindowManagerService.SHOW_TRANSACTIONS || 57 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 58 " DIM " + mDimSurface + ": CREATE"); 59 mDimSurface.setAlpha(0.0f); 60 } catch (Exception e) { 61 Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); 62 } 63 } 64 } 65 66 /** 67 * Set's the dim surface's layer and update dim parameters that will be used in 68 * {@link #updateSurface} after all windows are examined. 69 */ 70 void updateParameters(final Resources res, final Parameters params, final long currentTime) { 71 // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a 72 // corner. 73 final int dw = (int) (params.mDimWidth * 1.5); 74 final int dh = (int) (params.mDimHeight * 1.5); 75 final WindowStateAnimator winAnimator = params.mDimWinAnimator; 76 final float target = params.mDimTarget; 77 if (!mDimShown) { 78 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 79 " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")"); 80 mDimShown = true; 81 try { 82 mLastDimWidth = dw; 83 mLastDimHeight = dh; 84 // back off position so mDimXXX/4 is before and mDimXXX/4 is after 85 mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6); 86 mDimSurface.setSize(dw, dh); 87 mDimSurface.show(); 88 } catch (RuntimeException e) { 89 Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e); 90 } 91 } else if (mLastDimWidth != dw || mLastDimHeight != dh) { 92 mLastDimWidth = dw; 93 mLastDimHeight = dh; 94 mDimSurface.setSize(dw, dh); 95 // back off position so mDimXXX/4 is before and mDimXXX/4 is after 96 mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6); 97 } 98 99 mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM); 100 101 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 102 + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target); 103 if (mDimTargetAlpha != target) { 104 // If the desired dim level has changed, then 105 // start an animation to it. 106 mLastDimAnimTime = currentTime; 107 long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null) 108 ? winAnimator.mAnimation.computeDurationHint() 109 : WindowManagerService.DEFAULT_DIM_DURATION; 110 if (target > mDimTargetAlpha) { 111 TypedValue tv = new TypedValue(); 112 res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration, 113 tv, true); 114 if (tv.type == TypedValue.TYPE_FRACTION) { 115 duration = (long)tv.getFraction(duration, duration); 116 } else if (tv.type >= TypedValue.TYPE_FIRST_INT 117 && tv.type <= TypedValue.TYPE_LAST_INT) { 118 duration = tv.data; 119 } 120 } 121 if (duration < 1) { 122 // Don't divide by zero 123 duration = 1; 124 } 125 mDimTargetAlpha = target; 126 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; 127 } 128 } 129 130 /** 131 * Updating the surface's alpha. Returns true if the animation continues, or returns 132 * false when the animation is finished and the dim surface is hidden. 133 */ 134 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { 135 if (!dimming) { 136 if (mDimTargetAlpha != 0) { 137 mLastDimAnimTime = currentTime; 138 mDimTargetAlpha = 0; 139 mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION; 140 } 141 } 142 143 boolean animating = mLastDimAnimTime != 0; 144 if (animating) { 145 mDimCurrentAlpha += mDimDeltaPerMs 146 * (currentTime-mLastDimAnimTime); 147 if (displayFrozen) { 148 // If the display is frozen, there is no reason to animate. 149 animating = false; 150 } else if (mDimDeltaPerMs > 0) { 151 if (mDimCurrentAlpha > mDimTargetAlpha) { 152 animating = false; 153 } 154 } else if (mDimDeltaPerMs < 0) { 155 if (mDimCurrentAlpha < mDimTargetAlpha) { 156 animating = false; 157 } 158 } else { 159 animating = false; 160 } 161 162 // Do we need to continue animating? 163 if (animating) { 164 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 165 + mDimSurface + ": alpha=" + mDimCurrentAlpha); 166 mLastDimAnimTime = currentTime; 167 mDimSurface.setAlpha(mDimCurrentAlpha); 168 } else { 169 mDimCurrentAlpha = mDimTargetAlpha; 170 mLastDimAnimTime = 0; 171 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 172 + mDimSurface + ": final alpha=" + mDimCurrentAlpha); 173 mDimSurface.setAlpha(mDimCurrentAlpha); 174 if (!dimming) { 175 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface 176 + ": HIDE"); 177 try { 178 mDimSurface.hide(); 179 } catch (RuntimeException e) { 180 Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface"); 181 } 182 mDimShown = false; 183 } 184 } 185 } 186 return animating; 187 } 188 189 public void printTo(String prefix, PrintWriter pw) { 190 pw.print(prefix); 191 pw.print("mDimSurface="); pw.print(mDimSurface); 192 pw.print(" "); pw.print(mLastDimWidth); pw.print(" x "); 193 pw.println(mLastDimHeight); 194 pw.print(prefix); 195 pw.print("mDimShown="); pw.print(mDimShown); 196 pw.print(" current="); pw.print(mDimCurrentAlpha); 197 pw.print(" target="); pw.print(mDimTargetAlpha); 198 pw.print(" delta="); pw.print(mDimDeltaPerMs); 199 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); 200 } 201 202 static class Parameters { 203 final WindowStateAnimator mDimWinAnimator; 204 final int mDimWidth; 205 final int mDimHeight; 206 final float mDimTarget; 207 Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth, 208 final int dimHeight, final float dimTarget) { 209 mDimWinAnimator = dimWinAnimator; 210 mDimWidth = dimWidth; 211 mDimHeight = dimHeight; 212 mDimTarget = dimTarget; 213 } 214 } 215}