Home | History | Annotate | Download | only in wm
      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     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) {
     43         if (mDimSurface == null) {
     44             try {
     45                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
     46                     mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
     47                         "DimAnimator",
     48                         -1, 16, 16, PixelFormat.OPAQUE,
     49                         Surface.FX_SURFACE_DIM);
     50                 } else {
     51                     mDimSurface = new Surface(session, 0,
     52                         "DimAnimator",
     53                         -1, 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 }