13cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka/* 23cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * Copyright (C) 2011 The Android Open Source Project 33cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * 43cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 53cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * you may not use this file except in compliance with the License. 63cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * You may obtain a copy of the License at 73cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * 83cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 93cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * 103cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * Unless required by applicable law or agreed to in writing, software 113cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 123cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * See the License for the specific language governing permissions and 143cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka * limitations under the License. 153cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka */ 163cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 173cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkapackage com.android.systemui.recent; 183cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 193cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.content.Context; 203cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.content.res.TypedArray; 213cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.Canvas; 223cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.LinearGradient; 233cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.Matrix; 243cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.Paint; 253cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.Shader; 263cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.util.AttributeSet; 273cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.view.View; 283cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.view.ViewConfiguration; 293cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.widget.LinearLayout; 303cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 313cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport com.android.systemui.R; 323cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 333cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkapublic class RecentsScrollViewPerformanceHelper { 343cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true; 353cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true; 363cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private View mScrollView; 373cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 383cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private int mFadingEdgeLength; 393cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private boolean mIsVertical; 403cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka private boolean mSoftwareRendered = false; 413cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 423cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public static RecentsScrollViewPerformanceHelper create(Context context, 433cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka AttributeSet attrs, View scrollView, boolean isVertical) { 443cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka boolean isTablet = context.getResources(). 453cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka getBoolean(R.bool.config_recents_interface_for_tablets); 463cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (!isTablet && (OPTIMIZE_SW_RENDERED_RECENTS || USE_DARK_FADE_IN_HW_ACCELERATED_MODE)) { 473cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return new RecentsScrollViewPerformanceHelper(context, attrs, scrollView, isVertical); 483cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } else { 493cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return null; 503cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 513cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 523cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 533cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public RecentsScrollViewPerformanceHelper(Context context, 543cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka AttributeSet attrs, View scrollView, boolean isVertical) { 553cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mScrollView = scrollView; 563cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View); 573cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength, 583cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka ViewConfiguration.get(context).getScaledFadingEdgeLength()); 593cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mIsVertical = isVertical; 603cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 613cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 623cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void onAttachedToWindowCallback( 633cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka RecentsCallback callback, LinearLayout layout, boolean hardwareAccelerated) { 643cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mSoftwareRendered = !hardwareAccelerated; 653cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 663cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 673cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mScrollView.setVerticalFadingEdgeEnabled(false); 683cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka mScrollView.setHorizontalFadingEdgeEnabled(false); 693cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 703cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 713cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 723cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void addViewCallback(View newLinearLayoutChild) { 733cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { 74261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka final RecentsPanelView.ViewHolder holder = 75261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka (RecentsPanelView.ViewHolder) newLinearLayoutChild.getTag(); 76261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka holder.labelView.setDrawingCacheEnabled(true); 77261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka holder.labelView.buildDrawingCache(); 783cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 793cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 803cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 813cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void drawCallback(Canvas canvas, 823cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka int left, int right, int top, int bottom, int scrollX, int scrollY, 833cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float topFadingEdgeStrength, float bottomFadingEdgeStrength, 843cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float leftFadingEdgeStrength, float rightFadingEdgeStrength) { 853cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 863cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) 873cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { 883cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka Paint p = new Paint(); 893cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka Matrix matrix = new Matrix(); 903cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // use use a height of 1, and then wack the matrix each time we 913cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // actually use it. 923cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka Shader fade = new LinearGradient(0, 0, 0, 1, 0xCC000000, 0, Shader.TileMode.CLAMP); 933cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // PULL OUT THIS CONSTANT 943cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 953cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka p.setShader(fade); 963cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 973cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // draw the fade effect 983cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka boolean drawTop = false; 993cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka boolean drawBottom = false; 1003cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka boolean drawLeft = false; 1013cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka boolean drawRight = false; 1023cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1033cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float topFadeStrength = 0.0f; 1043cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float bottomFadeStrength = 0.0f; 1053cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float leftFadeStrength = 0.0f; 1063cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka float rightFadeStrength = 0.0f; 1073cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1083cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka final float fadeHeight = mFadingEdgeLength; 1093cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka int length = (int) fadeHeight; 1103cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1113cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // clip the fade length if top and bottom fades overlap 1123cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // overlapping fades produce odd-looking artifacts 1133cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (mIsVertical && (top + length > bottom - length)) { 1143cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka length = (bottom - top) / 2; 1153cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1163cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1173cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka // also clip horizontal fades if necessary 1183cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (!mIsVertical && (left + length > right - length)) { 1193cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka length = (right - left) / 2; 1203cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1213cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1223cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (mIsVertical) { 1233cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka topFadeStrength = Math.max(0.0f, Math.min(1.0f, topFadingEdgeStrength)); 1243cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka drawTop = topFadeStrength * fadeHeight > 1.0f; 1253cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, bottomFadingEdgeStrength)); 1263cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 1273cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1283cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1293cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (!mIsVertical) { 1303cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka leftFadeStrength = Math.max(0.0f, Math.min(1.0f, leftFadingEdgeStrength)); 1313cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka drawLeft = leftFadeStrength * fadeHeight > 1.0f; 1323cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka rightFadeStrength = Math.max(0.0f, Math.min(1.0f, rightFadingEdgeStrength)); 1333cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka drawRight = rightFadeStrength * fadeHeight > 1.0f; 1343cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1353cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1363cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (drawTop) { 1373cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.setScale(1, fadeHeight * topFadeStrength); 1383cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postTranslate(left, top); 1393cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka fade.setLocalMatrix(matrix); 1403cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka canvas.drawRect(left, top, right, top + length, p); 1413cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1423cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1433cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (drawBottom) { 1443cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.setScale(1, fadeHeight * bottomFadeStrength); 1453cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postRotate(180); 1463cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postTranslate(left, bottom); 1473cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka fade.setLocalMatrix(matrix); 1483cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka canvas.drawRect(left, bottom - length, right, bottom, p); 1493cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1503cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1513cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (drawLeft) { 1523cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.setScale(1, fadeHeight * leftFadeStrength); 1533cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postRotate(-90); 1543cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postTranslate(left, top); 1553cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka fade.setLocalMatrix(matrix); 1563cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka canvas.drawRect(left, top, left + length, bottom, p); 1573cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1583cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1593cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka if (drawRight) { 1603cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.setScale(1, fadeHeight * rightFadeStrength); 1613cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postRotate(90); 1623cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka matrix.postTranslate(right, top); 1633cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka fade.setLocalMatrix(matrix); 1643cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka canvas.drawRect(right - length, top, right, bottom, p); 1653cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1663cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1673cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1683cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1693cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public int getVerticalFadingEdgeLengthCallback() { 1703cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return mFadingEdgeLength; 1713cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1723cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1733cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public int getHorizontalFadingEdgeLengthCallback() { 1743cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return mFadingEdgeLength; 1753cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1763cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1773cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka} 178