summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaurabh Shah <saurshah@codeaurora.org>2015-05-07 14:10:23 +0530
committerLinux Build Service Account <lnxbuild@localhost>2015-10-06 03:27:54 -0600
commitd5282e055963a44df64265e4a592750e31bd9901 (patch)
treeb01acebb234f1ff3a1ab950418da6f7ec5728154
parent65093cc820e098e0ea1d1e64b4af0f3a58b80fc9 (diff)
downloadframeworks_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.java12
-rw-r--r--core/java/android/util/ResolutionOverride.java140
-rw-r--r--core/java/android/view/SurfaceView.java19
-rw-r--r--core/java/com/android/internal/app/ActivityTrigger.java29
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java4
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