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 17 package com.android.server.wm; 18 19 import android.content.res.Resources; 20 import android.graphics.PixelFormat; 21 import android.util.Slog; 22 import android.util.TypedValue; 23 import android.view.Surface; 24 import android.view.SurfaceSession; 25 26 import 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 */ 32 class DimAnimator { 33 static final String TAG = "DimAnimator"; 34 35 Surface mDimSurface; 36 boolean mDimShown = false; 37 float mDimCurrentAlpha; 38 float mDimTargetAlpha; 39 float mDimDeltaPerMs; 40 long mLastDimAnimTime; 41 42 int mLastDimWidth, mLastDimHeight; 43 44 DimAnimator (SurfaceSession session, final int layerStack) { 45 try { 46 if (WindowManagerService.DEBUG_SURFACE_TRACE) { 47 mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 48 "DimAnimator", 49 16, 16, PixelFormat.OPAQUE, 50 Surface.FX_SURFACE_DIM | Surface.HIDDEN); 51 } else { 52 mDimSurface = new Surface(session, "DimAnimator", 53 16, 16, PixelFormat.OPAQUE, 54 Surface.FX_SURFACE_DIM | Surface.HIDDEN); 55 } 56 if (WindowManagerService.SHOW_TRANSACTIONS || 57 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 58 " DIM " + mDimSurface + ": CREATE"); 59 mDimSurface.setLayerStack(layerStack); 60 mDimSurface.setAlpha(0.0f); 61 mDimSurface.show(); 62 } catch (Exception e) { 63 Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); 64 } 65 } 66 67 /** 68 * Set's the dim surface's layer and update dim parameters that will be used in 69 * {@link #updateSurface} after all windows are examined. 70 */ 71 void updateParameters(final Resources res, final Parameters params, final long currentTime) { 72 if (mDimSurface == null) { 73 Slog.e(TAG, "updateParameters: no Surface"); 74 return; 75 } 76 77 // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a 78 // corner. 79 final int dw = (int) (params.mDimWidth * 1.5); 80 final int dh = (int) (params.mDimHeight * 1.5); 81 final WindowStateAnimator winAnimator = params.mDimWinAnimator; 82 final float target = params.mDimTarget; 83 if (!mDimShown) { 84 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 85 " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")"); 86 mDimShown = true; 87 try { 88 mLastDimWidth = dw; 89 mLastDimHeight = dh; 90 // back off position so mDimXXX/4 is before and mDimXXX/4 is after 91 mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6); 92 mDimSurface.setSize(dw, dh); 93 mDimSurface.show(); 94 } catch (RuntimeException e) { 95 Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e); 96 } 97 } else if (mLastDimWidth != dw || mLastDimHeight != dh) { 98 mLastDimWidth = dw; 99 mLastDimHeight = dh; 100 mDimSurface.setSize(dw, dh); 101 // back off position so mDimXXX/4 is before and mDimXXX/4 is after 102 mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6); 103 } 104 105 mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM); 106 107 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 108 + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target); 109 if (mDimTargetAlpha != target) { 110 // If the desired dim level has changed, then 111 // start an animation to it. 112 mLastDimAnimTime = currentTime; 113 long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null) 114 ? winAnimator.mAnimation.computeDurationHint() 115 : WindowManagerService.DEFAULT_DIM_DURATION; 116 if (target > mDimTargetAlpha) { 117 TypedValue tv = new TypedValue(); 118 res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration, 119 tv, true); 120 if (tv.type == TypedValue.TYPE_FRACTION) { 121 duration = (long)tv.getFraction(duration, duration); 122 } else if (tv.type >= TypedValue.TYPE_FIRST_INT 123 && tv.type <= TypedValue.TYPE_LAST_INT) { 124 duration = tv.data; 125 } 126 } 127 if (duration < 1) { 128 // Don't divide by zero 129 duration = 1; 130 } 131 mDimTargetAlpha = target; 132 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; 133 } 134 } 135 136 /** 137 * Updating the surface's alpha. Returns true if the animation continues, or returns 138 * false when the animation is finished and the dim surface is hidden. 139 */ 140 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { 141 if (mDimSurface == null) { 142 Slog.e(TAG, "updateSurface: no Surface"); 143 return false; 144 } 145 146 if (!dimming) { 147 if (mDimTargetAlpha != 0) { 148 mLastDimAnimTime = currentTime; 149 mDimTargetAlpha = 0; 150 mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION; 151 } 152 } 153 154 boolean animating = mLastDimAnimTime != 0; 155 if (animating) { 156 mDimCurrentAlpha += mDimDeltaPerMs 157 * (currentTime-mLastDimAnimTime); 158 if (displayFrozen) { 159 // If the display is frozen, there is no reason to animate. 160 animating = false; 161 } else if (mDimDeltaPerMs > 0) { 162 if (mDimCurrentAlpha > mDimTargetAlpha) { 163 animating = false; 164 } 165 } else if (mDimDeltaPerMs < 0) { 166 if (mDimCurrentAlpha < mDimTargetAlpha) { 167 animating = false; 168 } 169 } else { 170 animating = false; 171 } 172 173 // Do we need to continue animating? 174 if (animating) { 175 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 176 + mDimSurface + ": alpha=" + mDimCurrentAlpha); 177 mLastDimAnimTime = currentTime; 178 mDimSurface.setAlpha(mDimCurrentAlpha); 179 } else { 180 mDimCurrentAlpha = mDimTargetAlpha; 181 mLastDimAnimTime = 0; 182 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " 183 + mDimSurface + ": final alpha=" + mDimCurrentAlpha); 184 mDimSurface.setAlpha(mDimCurrentAlpha); 185 if (!dimming) { 186 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface 187 + ": HIDE"); 188 try { 189 mDimSurface.hide(); 190 } catch (RuntimeException e) { 191 Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface"); 192 } 193 mDimShown = false; 194 } 195 } 196 } 197 return animating; 198 } 199 200 public void kill() { 201 if (mDimSurface != null) { 202 mDimSurface.destroy(); 203 mDimSurface = null; 204 } 205 } 206 207 public void printTo(String prefix, PrintWriter pw) { 208 pw.print(prefix); 209 pw.print("mDimSurface="); pw.print(mDimSurface); 210 pw.print(" "); pw.print(mLastDimWidth); pw.print(" x "); 211 pw.println(mLastDimHeight); 212 pw.print(prefix); 213 pw.print("mDimShown="); pw.print(mDimShown); 214 pw.print(" current="); pw.print(mDimCurrentAlpha); 215 pw.print(" target="); pw.print(mDimTargetAlpha); 216 pw.print(" delta="); pw.print(mDimDeltaPerMs); 217 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); 218 } 219 220 static class Parameters { 221 final WindowStateAnimator mDimWinAnimator; 222 final int mDimWidth; 223 final int mDimHeight; 224 final float mDimTarget; 225 Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth, 226 final int dimHeight, final float dimTarget) { 227 mDimWinAnimator = dimWinAnimator; 228 mDimWidth = dimWidth; 229 mDimHeight = dimHeight; 230 mDimTarget = dimTarget; 231 } 232 233 Parameters(Parameters o) { 234 mDimWinAnimator = o.mDimWinAnimator; 235 mDimWidth = o.mDimWidth; 236 mDimHeight = o.mDimHeight; 237 mDimTarget = o.mDimTarget; 238 } 239 240 public void printTo(String prefix, PrintWriter pw) { 241 pw.print(prefix); 242 pw.print("mDimWinAnimator="); pw.print(mDimWinAnimator.mWin.mAttrs.getTitle()); 243 pw.print(" "); pw.print(mDimWidth); pw.print(" x "); 244 pw.print(mDimHeight); 245 pw.print(" mDimTarget="); pw.println(mDimTarget); 246 } 247 } 248 } 249