diff options
author | Saurabh Shah <saurshah@codeaurora.org> | 2015-05-07 14:10:23 +0530 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2015-10-06 03:27:54 -0600 |
commit | d5282e055963a44df64265e4a592750e31bd9901 (patch) | |
tree | b01acebb234f1ff3a1ab950418da6f7ec5728154 | |
parent | 65093cc820e098e0ea1d1e64b4af0f3a58b80fc9 (diff) | |
download | frameworks_base-d5282e055963a44df64265e4a592750e31bd9901.zip frameworks_base-d5282e055963a44df64265e4a592750e31bd9901.tar.gz frameworks_base-d5282e055963a44df64265e4a592750e31bd9901.tar.bz2 |
frameworks/base: Add support for low resolution rendering
This change is a combination of following changes:
1) frameworks/base: Handle custom activityTrigger flags
* Take necessary action needed for each vendor specific flag
set as part of activityTrigger.
* If the HW acceleration has to be enabled for a particular
activity, populate the neccessary activityInfo flags.
* If the resolution needs to be overridden for SurfaceView
of a specific app, set the overrideRes to 1 in applicationInfo.
Author: Raj Kamal<rkamal@codeaurora.org>
Change-Id: Ic835ec1f2ebcc016542ace4050bfef5fb32f20a0
2) frameworks/base: Add support to render certain apps at lower
resolution.
Add support to render certain apps at a resolution lower than the
primary display device resolution. This would reduce the load on
GPU and would help in saving power
Author: Uday Kiran jandhyala<ukiran@codeaurora.org>
Change-Id: I7004a145f3048aafbfb456451e08ea5ba229cfe9
This change also moves out custom functionality related to
overriding resolution from SurfaceView, to a new class
ResolutionOverride.
Change-Id: Icabc17b9462a347c9c452cc53222ea7dcb6f336b
-rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 12 | ||||
-rw-r--r-- | core/java/android/util/ResolutionOverride.java | 140 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 19 | ||||
-rw-r--r-- | core/java/com/android/internal/app/ActivityTrigger.java | 29 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityStack.java | 4 |
5 files changed, 194 insertions, 10 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 6feb860..41f5233 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -465,6 +465,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public int privateFlags; /** + * Boolean indicating whether the resolution of the SurfaceView associated + * with this appplication can be overriden. + * {@hide} + */ + public int overrideRes = 0; + + /** * The required smallest screen width the application can run on. If 0, * nothing has been specified. Comes from * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp @@ -754,6 +761,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = orig.theme; flags = orig.flags; privateFlags = orig.privateFlags; + overrideRes = orig.overrideRes; requiresSmallestWidthDp = orig.requiresSmallestWidthDp; compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; @@ -807,6 +815,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(theme); dest.writeInt(flags); dest.writeInt(privateFlags); + dest.writeInt(overrideRes); dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); @@ -859,6 +868,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = source.readInt(); flags = source.readInt(); privateFlags = source.readInt(); + overrideRes = source.readInt(); requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); @@ -997,6 +1007,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; } /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; } /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; } + /** {@hide} */ public void setOverrideRes(int overrideResolution) { overrideRes = overrideResolution; } /** {@hide} */ public String getCodePath() { return scanSourceDir; } /** {@hide} */ public String getBaseCodePath() { return sourceDir; } @@ -1004,4 +1015,5 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** {@hide} */ public String getResourcePath() { return scanPublicSourceDir; } /** {@hide} */ public String getBaseResourcePath() { return publicSourceDir; } /** {@hide} */ public String[] getSplitResourcePaths() { return splitSourceDirs; } + /** {@hide} */ public int canOverrideRes() { return overrideRes; } } diff --git a/core/java/android/util/ResolutionOverride.java b/core/java/android/util/ResolutionOverride.java new file mode 100644 index 0000000..d9fc1be --- /dev/null +++ b/core/java/android/util/ResolutionOverride.java @@ -0,0 +1,140 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +package android.util; + +import android.content.ComponentName; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.Matrix; +import android.os.SystemProperties; +import android.util.Log; +import android.view.MotionEvent; +import android.view.SurfaceView; +import android.view.View; + +/** @hide */ +public class ResolutionOverride { + /** @hide */ + static private final boolean DEBUG = false; + static private final String TAG = "ResolutionOverride"; + private static final String RES_OVERRIDE = "persist.debug.app_res_override"; + private boolean mIsEnabled = false; + private int mOverrideXres = 0; + private int mOverrideYres = 0; + + /** @hide */ + public ResolutionOverride(SurfaceView view) { + boolean enable = (view.getContext().getApplicationInfo().canOverrideRes() == 1); + int orientation = view.getResources().getConfiguration().orientation; + + if(enable && (orientation == Configuration.ORIENTATION_PORTRAIT || + orientation == Configuration.ORIENTATION_LANDSCAPE)) { + String resStr = SystemProperties.get(RES_OVERRIDE, null); + + if (resStr != null && resStr.length() > 0) { + resStr = resStr.toLowerCase(); + final int pos = resStr.indexOf('x'); + if (pos > 0 && resStr.lastIndexOf('x') == pos) { + try { + mOverrideXres = Integer.parseInt(resStr.substring(0, pos)); + mOverrideYres = Integer.parseInt(resStr.substring(pos + 1)); + } catch (NumberFormatException ex) { + Log.e(TAG, "Error in extracting the overriding xres and yres"); + } + } + } + + if(orientation == Configuration.ORIENTATION_LANDSCAPE) { + int tmp = mOverrideXres; + mOverrideXres = mOverrideYres; + mOverrideYres = tmp; + } + + if(mOverrideXres > 0 && mOverrideYres > 0) { + mIsEnabled = true; + if (DEBUG) Log.i(TAG, "Orientation: " + orientation + + " Overriding resolution to" + " xres: " + mOverrideXres + + " yres: " + mOverrideYres); + } + } + } + + /** @hide */ + public void setFixedSize(SurfaceView view) { + if(!mIsEnabled) { + return; + } + + view.getHolder().setFixedSize(mOverrideXres, mOverrideYres); + } + + /** @hide */ + public void handleTouch(SurfaceView view, MotionEvent ev) { + if(!mIsEnabled) { + return; + } + + Matrix matrix = new Matrix(); + //mOverride{Xres, Yres} are already swapped if orientation is landscape + float xscale = (mOverrideXres * 1.0f) / view.getWidth(); + float yscale = (mOverrideYres * 1.0f) / view.getHeight(); + + if (DEBUG) Log.i(TAG, "Before overriding the touch event x/y : " + ev); + matrix.postScale(xscale, yscale); + ev.transform(matrix); + if (DEBUG) Log.i(TAG, "After overriding the touch event x/y : " + ev); + } + + /** @hide */ + public void handleResize(final SurfaceView surfaceView) { + if(!mIsEnabled) { + return; + } + + /* Change the visibility to GONE and back to VISIBLE and post it + * on the main thread for the touch events to be effective on the + * changed SurfaceView with the new dimensions + */ + surfaceView.post(new Runnable() { + @Override + public void run() { + surfaceView.setVisibility(View.GONE); + } + }); + + surfaceView.postDelayed(new Runnable() { + @Override + public void run() { + surfaceView.setVisibility(View.VISIBLE); + } + }, 100); + } +}; diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 7d48a9a..7d49fd3 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -33,6 +33,7 @@ import android.os.SystemClock; import android.os.ParcelFileDescriptor; import android.util.AttributeSet; import android.util.Log; +import android.util.ResolutionOverride; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -167,6 +168,7 @@ public class SurfaceView extends View { boolean mUpdateWindowNeeded; boolean mReportDrawNeeded; private Translator mTranslator; + ResolutionOverride mResolutionOverride = null; private final ViewTreeObserver.OnPreDrawListener mDrawListener = new ViewTreeObserver.OnPreDrawListener() { @@ -202,6 +204,8 @@ public class SurfaceView extends View { private void init() { setWillNotDraw(true); + mResolutionOverride = new ResolutionOverride(this); + mResolutionOverride.setFixedSize(this); } /** @@ -294,6 +298,16 @@ public class SurfaceView extends View { setMeasuredDimension(width, height); } + /** + * Transforms the touch events to the new resolution coordinate system + * if the resolution has changed + */ + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + mResolutionOverride.handleTouch(this, ev); + return super.dispatchTouchEvent(ev); + } + /** @hide */ @Override protected boolean setFrame(int left, int top, int right, int bottom) { @@ -658,11 +672,14 @@ public class SurfaceView extends View { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { - SurfaceView surfaceView = mSurfaceView.get(); + final SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (DEBUG) Log.v( "SurfaceView", surfaceView + " got resized: w=" + frame.width() + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight); + + surfaceView.mResolutionOverride.handleResize(surfaceView); + surfaceView.mSurfaceLock.lock(); try { if (reportDraw) { diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java index 75da84b..6f6949a 100644 --- a/core/java/com/android/internal/app/ActivityTrigger.java +++ b/core/java/com/android/internal/app/ActivityTrigger.java @@ -31,12 +31,19 @@ package com.android.internal.app; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.util.Log; public class ActivityTrigger { private static final String TAG = "ActivityTrigger"; + private static final int FLAG_OVERRIDE_RESOLUTION = 1; + private static final int FLAG_HARDWARE_ACCELERATED = + ActivityInfo.FLAG_HARDWARE_ACCELERATED; + + /** &hide */ public ActivityTrigger() { //Log.d(TAG, "ActivityTrigger initialized"); @@ -48,23 +55,31 @@ public class ActivityTrigger } /** &hide */ - public int activityStartTrigger(Intent intent, int flags) { + public void activityStartTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { ComponentName cn = intent.getComponent(); + int overrideFlags = 0; String activity = null; - if (cn != null) - activity = cn.flattenToString(); - flags = native_at_startActivity(activity, flags); - return flags; + if(cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + + overrideFlags = native_at_startActivity(activity, overrideFlags); + + if((overrideFlags & FLAG_HARDWARE_ACCELERATED) != 0) { + acInfo.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; + } + if((overrideFlags & FLAG_OVERRIDE_RESOLUTION) != 0) { + appInfo.setOverrideRes(1); + } } /** &hide */ - public void activityResumeTrigger(Intent intent) { + public void activityResumeTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { ComponentName cn = intent.getComponent(); String activity = null; if (cn != null) - activity = cn.flattenToString(); + activity = cn.flattenToString() + "/" + appInfo.versionCode; native_at_resumeActivity(activity); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index e9c6762..a254451 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1698,7 +1698,7 @@ final class ActivityStack { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); - mActivityTrigger.activityResumeTrigger(next.intent); + mActivityTrigger.activityResumeTrigger(next.intent, next.info, next.appInfo); // If we are currently pausing an activity, then don't do anything // until that is done. @@ -2168,7 +2168,7 @@ final class ActivityStack { task.setFrontOfTask(); r.putInHistory(); - r.info.flags = mActivityTrigger.activityStartTrigger(r.intent, r.info.flags); + mActivityTrigger.activityStartTrigger(r.intent, r.info, r.appInfo); if (!isHomeStack() || numActivities() > 0) { // We want to show the starting preview window if we are // switching to a new task, or the next activity's process is |